mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-16 19:51:41 +00:00
release/dist/cli: add verify-package-signature command (#9110)
Helper command to verify package signatures, mainly for debugging. Also fix a copy-paste mistake in error message in distsign. Updates #8760 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
parent
c86a610eb3
commit
18d9c92342
@ -224,7 +224,7 @@ func (c *Client) Download(srcPath, dstPath string) error {
|
|||||||
if !VerifyAny(sigPub, msg, sig) {
|
if !VerifyAny(sigPub, msg, sig) {
|
||||||
// Best-effort clean up of downloaded package.
|
// Best-effort clean up of downloaded package.
|
||||||
os.Remove(dstPathUnverified)
|
os.Remove(dstPathUnverified)
|
||||||
return fmt.Errorf("signature %q for key %q does not validate with the current release signing key; either you are under attack, or attempting to download an old version of Tailscale which was signed with an older signing key", sigURL, srcURL)
|
return fmt.Errorf("signature %q for file %q does not validate with the current release signing key; either you are under attack, or attempting to download an old version of Tailscale which was signed with an older signing key", sigURL, srcURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.Rename(dstPathUnverified, dstPath); err != nil {
|
if err := os.Rename(dstPathUnverified, dstPath); err != nil {
|
||||||
|
63
release/dist/cli/cli.go
vendored
63
release/dist/cli/cli.go
vendored
@ -8,10 +8,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"encoding/binary"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -119,6 +121,21 @@ func CLI(getTargets func() ([]dist.Target, error)) *ffcli.Command {
|
|||||||
return fs
|
return fs
|
||||||
})(),
|
})(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "verify-package-signature",
|
||||||
|
Exec: func(ctx context.Context, args []string) error {
|
||||||
|
return runVerifyPackageSignature(ctx)
|
||||||
|
},
|
||||||
|
ShortUsage: "dist verify-package-signature",
|
||||||
|
ShortHelp: "Verify a package signture using a signing key",
|
||||||
|
FlagSet: (func() *flag.FlagSet {
|
||||||
|
fs := flag.NewFlagSet("verify-package-signature", flag.ExitOnError)
|
||||||
|
fs.StringVar(&verifyPackageSignatureArgs.signPubPath, "sign-pub-path", "signing-public-key.pem", "path to the signing public key; this can be a bundle of multiple keys")
|
||||||
|
fs.StringVar(&verifyPackageSignatureArgs.packagePath, "package-path", "", "path to the package that was signed")
|
||||||
|
fs.StringVar(&verifyPackageSignatureArgs.sigPath, "sig-path", "signature.bin", "path to the signature file")
|
||||||
|
return fs
|
||||||
|
})(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Exec: func(context.Context, []string) error { return flag.ErrHelp },
|
Exec: func(context.Context, []string) error { return flag.ErrHelp },
|
||||||
}
|
}
|
||||||
@ -287,19 +304,20 @@ var verifyKeySignatureArgs struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runVerifyKeySignature(ctx context.Context) error {
|
func runVerifyKeySignature(ctx context.Context) error {
|
||||||
rootPubBundle, err := os.ReadFile(verifyKeySignatureArgs.rootPubPath)
|
args := verifyKeySignatureArgs
|
||||||
|
rootPubBundle, err := os.ReadFile(args.rootPubPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rootPubs, err := distsign.ParseRootKeyBundle(rootPubBundle)
|
rootPubs, err := distsign.ParseRootKeyBundle(rootPubBundle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("parsing %q: %w", verifyKeySignatureArgs.rootPubPath, err)
|
return fmt.Errorf("parsing %q: %w", args.rootPubPath, err)
|
||||||
}
|
}
|
||||||
signPubBundle, err := os.ReadFile(verifyKeySignatureArgs.signPubPath)
|
signPubBundle, err := os.ReadFile(args.signPubPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sig, err := os.ReadFile(verifyKeySignatureArgs.sigPath)
|
sig, err := os.ReadFile(args.sigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -309,3 +327,40 @@ func runVerifyKeySignature(ctx context.Context) error {
|
|||||||
fmt.Println("signature ok")
|
fmt.Println("signature ok")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var verifyPackageSignatureArgs struct {
|
||||||
|
signPubPath string
|
||||||
|
packagePath string
|
||||||
|
sigPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func runVerifyPackageSignature(ctx context.Context) error {
|
||||||
|
args := verifyPackageSignatureArgs
|
||||||
|
signPubBundle, err := os.ReadFile(args.signPubPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
signPubs, err := distsign.ParseSigningKeyBundle(signPubBundle)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parsing %q: %w", args.signPubPath, err)
|
||||||
|
}
|
||||||
|
pkg, err := os.Open(args.packagePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer pkg.Close()
|
||||||
|
pkgHash := distsign.NewPackageHash()
|
||||||
|
if _, err := io.Copy(pkgHash, pkg); err != nil {
|
||||||
|
return fmt.Errorf("reading %q: %w", args.packagePath, err)
|
||||||
|
}
|
||||||
|
hash := binary.LittleEndian.AppendUint64(pkgHash.Sum(nil), uint64(pkgHash.Len()))
|
||||||
|
sig, err := os.ReadFile(args.sigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !distsign.VerifyAny(signPubs, hash, sig) {
|
||||||
|
return errors.New("signature not valid")
|
||||||
|
}
|
||||||
|
fmt.Println("signature ok")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user