mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-11 13:18:53 +00:00
release/dist/cli: add sign-key and verify-key-signature commands (#9041)
Now we have all the commands to generate the key hierarchy and verify that signing keys were signed correctly: ``` $ ./tool/go run ./cmd/dist gen-key --priv-path root-priv.pem --pub-path root-pub.pem --root wrote private key to root-priv.pem wrote public key to root-pub.pem $ ./tool/go run ./cmd/dist gen-key --priv-path signing-priv.pem --pub-path signing-pub.pem --signing wrote private key to signing-priv.pem wrote public key to signing-pub.pem $ ./tool/go run ./cmd/dist sign-key --root-priv-path root-priv.pem --sign-pub-path signing-pub.pem wrote signature to signature.bin $ ./tool/go run ./cmd/dist verify-key-signature --root-pub-path root-pub.pem --sign-pub-path signing-pub.pem --sig-path signature.bin signature ok ``` Updates #8760 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
92
release/dist/cli/cli.go
vendored
92
release/dist/cli/cli.go
vendored
@@ -95,6 +95,36 @@ func CLI(getTargets func(unixpkgs.Signers) ([]dist.Target, error)) *ffcli.Comman
|
||||
return fs
|
||||
})(),
|
||||
},
|
||||
{
|
||||
Name: "sign-key",
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
return runSignKey(ctx)
|
||||
},
|
||||
ShortUsage: "dist sign-key",
|
||||
ShortHelp: "Sign signing keys with a root key",
|
||||
FlagSet: (func() *flag.FlagSet {
|
||||
fs := flag.NewFlagSet("sign-key", flag.ExitOnError)
|
||||
fs.StringVar(&signKeyArgs.rootPrivPath, "root-priv-path", "root-private-key.pem", "path to the root private key to sign with")
|
||||
fs.StringVar(&signKeyArgs.signPubPath, "sign-pub-path", "signing-public-keys.pem", "path to the signing public key bundle to sign; the bundle should include all active signing keys")
|
||||
fs.StringVar(&signKeyArgs.sigPath, "sig-path", "signature.bin", "oputput path for the signature")
|
||||
return fs
|
||||
})(),
|
||||
},
|
||||
{
|
||||
Name: "verify-key-signature",
|
||||
Exec: func(ctx context.Context, args []string) error {
|
||||
return runVerifyKeySignature(ctx)
|
||||
},
|
||||
ShortUsage: "dist verify-key-signature",
|
||||
ShortHelp: "Verify a root signture of the signing keys' bundle",
|
||||
FlagSet: (func() *flag.FlagSet {
|
||||
fs := flag.NewFlagSet("verify-key-signature", flag.ExitOnError)
|
||||
fs.StringVar(&verifyKeySignatureArgs.rootPubPath, "root-pub-path", "root-public-key.pem", "path to the root public key; this can be a bundle of multiple keys")
|
||||
fs.StringVar(&verifyKeySignatureArgs.signPubPath, "sign-pub-path", "", "path to the signing public key bundle that was signed")
|
||||
fs.StringVar(&verifyKeySignatureArgs.sigPath, "sig-path", "signature.bin", "path to the signature file")
|
||||
return fs
|
||||
})(),
|
||||
},
|
||||
},
|
||||
Exec: func(context.Context, []string) error { return flag.ErrHelp },
|
||||
}
|
||||
@@ -224,3 +254,65 @@ func runGenKey(ctx context.Context) error {
|
||||
fmt.Println("wrote public key to", genKeyArgs.pubPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
var signKeyArgs struct {
|
||||
rootPrivPath string
|
||||
signPubPath string
|
||||
sigPath string
|
||||
}
|
||||
|
||||
func runSignKey(ctx context.Context) error {
|
||||
rkRaw, err := os.ReadFile(signKeyArgs.rootPrivPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rk, err := distsign.ParseRootKey(rkRaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle, err := os.ReadFile(signKeyArgs.signPubPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sig, err := rk.SignSigningKeys(bundle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.WriteFile(signKeyArgs.sigPath, sig, 0400); err != nil {
|
||||
return fmt.Errorf("failed writing signature file: %w", err)
|
||||
}
|
||||
fmt.Println("wrote signature to", signKeyArgs.sigPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
var verifyKeySignatureArgs struct {
|
||||
rootPubPath string
|
||||
signPubPath string
|
||||
sigPath string
|
||||
}
|
||||
|
||||
func runVerifyKeySignature(ctx context.Context) error {
|
||||
rootPubBundle, err := os.ReadFile(verifyKeySignatureArgs.rootPubPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootPubs, err := distsign.ParseRootKeyBundle(rootPubBundle)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing %q: %w", verifyKeySignatureArgs.rootPubPath, err)
|
||||
}
|
||||
signPubBundle, err := os.ReadFile(verifyKeySignatureArgs.signPubPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sig, err := os.ReadFile(verifyKeySignatureArgs.sigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !distsign.VerifyAny(rootPubs, signPubBundle, sig) {
|
||||
return errors.New("signature not valid")
|
||||
}
|
||||
fmt.Println("signature ok")
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user