Skip to content

Commit

Permalink
Migrate cosign public-key to cobra. (#771)
Browse files Browse the repository at this point in the history
Signed-off-by: Scott Nichols <[email protected]>
  • Loading branch information
n3wscott authored Sep 23, 2021
1 parent 1aeef2c commit ef9683a
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 44 deletions.
5 changes: 3 additions & 2 deletions cmd/cosign/cli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ func New() *cobra.Command {
PublicKey(),
generate.GenerateKeyPair(),
// Signing
verify.Verify(),
sign.Sign(),
sign.SignBlob(),
Attest(),
generate.Generate(),
sign.SignBlob(),
verify.Verify(),
verify.VerifyAttestation(),
verify.VerifyBlob(),
// Manifest sub-tree
Expand Down Expand Up @@ -116,6 +116,7 @@ func New() *cobra.Command {
options.AddRootOptions(cmd, ro)

// Add sub-commands.
addPublicKey(cmd)
addSign(cmd)
addSignBlob(cmd)

Expand Down
1 change: 1 addition & 0 deletions cmd/cosign/cli/options/fulcio.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type FulcioOptions struct {
IdentityToken string
}

// AddFulcioOptions adds the Fulcio related options to cmd.
func AddFulcioOptions(cmd *cobra.Command, o *FulcioOptions) {
cmd.Flags().StringVar(&o.URL, "fulcio-url", fulcioclient.SigstorePublicServerURL,
"[EXPERIMENTAL] address of sigstore PKI server")
Expand Down
1 change: 1 addition & 0 deletions cmd/cosign/cli/options/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type OIDCOptions struct {
ClientSecret string
}

// AddOIDCOptions adds the OIDC related options to cmd.
func AddOIDCOptions(cmd *cobra.Command, o *OIDCOptions) {
cmd.Flags().StringVar(&o.Issuer, "oidc-issuer", "https://oauth2.sigstore.dev/auth",
"[EXPERIMENTAL] OIDC provider to be used to issue ID token")
Expand Down
38 changes: 38 additions & 0 deletions cmd/cosign/cli/options/public_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// Copyright 2021 The Sigstore Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package options

import (
"github.com/spf13/cobra"
)

// PublicKeyOptions is the top level wrapper for the public-key command.
type PublicKeyOptions struct {
Key string
SecurityKey SecurityKeyOptions
OutFile string
}

// AddPublicKeyOptions adds the public-key command options to cmd.
func AddPublicKeyOptions(cmd *cobra.Command, o *PublicKeyOptions) {
cmd.Flags().StringVar(&o.Key, "key", "",
"path to the private key file, KMS URI or Kubernetes Secret")

AddSecurityKeyOptions(cmd, &o.SecurityKey)

cmd.Flags().StringVar(&o.OutFile, "outfile", "",
"path to a payload file to use rather than generating one")
}
1 change: 1 addition & 0 deletions cmd/cosign/cli/options/rekor.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type RekorOptions struct {
URL string
}

// AddRekorOptions adds the Rektor related options to cmd.
func AddRekorOptions(cmd *cobra.Command, o *RekorOptions) {
cmd.Flags().StringVar(&o.URL, "rekor-url", "https://rekor.sigstore.dev",
"[EXPERIMENTAL] address of rekor STL server")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type SecurityKeyOptions struct {
Slot string
}

// AddSecurityKeyOptions adds the security key related options to cmd.
func AddSecurityKeyOptions(cmd *cobra.Command, o *SecurityKeyOptions) {
cmd.Flags().BoolVar(&o.Use, "sk", false,
"whether to use a hardware security key")
Expand Down
1 change: 1 addition & 0 deletions cmd/cosign/cli/options/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func (s *SignOptions) AnnotationsMap() (sigs.AnnotationsMap, error) {
return ann, nil
}

// AddSignOptions adds the sign command options to cmd.
func AddSignOptions(cmd *cobra.Command, o *SignOptions) {
cmd.Flags().StringVar(&o.Key, "key", "",
"path to the private key file, KMS URI or Kubernetes Secret")
Expand Down
1 change: 1 addition & 0 deletions cmd/cosign/cli/options/signblob.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type SignBlobOptions struct {
RegistryOpts RegistryOpts
}

// AddSignBlobOptions adds the sign-blob command options to cmd.
func AddSignBlobOptions(cmd *cobra.Command, o *SignBlobOptions) {
cmd.Flags().StringVar(&o.Key, "key", "",
"path to the private key file, KMS URI or Kubernetes Secret")
Expand Down
58 changes: 50 additions & 8 deletions cmd/cosign/cli/public_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/peterbourgon/ff/v3/ffcli"
"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/sigstore/cosign/cmd/cosign/cli/generate"
"github.com/sigstore/cosign/cmd/cosign/cli/options"
Expand All @@ -39,6 +40,8 @@ type NamedWriter struct {
io.Writer
}

// PublicKey subcommand for ffcli.
// Deprecated: this will be deleted when the migration from ffcli to cobra is done.
func PublicKey() *ffcli.Command {
var (
flagset = flag.NewFlagSet("cosign public-key", flag.ExitOnError)
Expand Down Expand Up @@ -75,17 +78,53 @@ EXAMPLES
cosign public-key -key hashivault://[KEY]`,
FlagSet: flagset,
Exec: func(ctx context.Context, args []string) error {
if !options.OneOf(*key, *sk) {
_ = key
_ = sk
_ = slot
_ = outFile
panic("this command is now implemented in cobra.")
},
}
}

func addPublicKey(topLevel *cobra.Command) {
o := &options.PublicKeyOptions{}

cmd := &cobra.Command{
Use: "public-key",
Short: "Gets a public key from the key-pair.",
Long: "Gets a public key from the key-pair and\nwrites to a specified file. By default, it will write to standard out.",
Example: `
# extract public key from private key to a specified out file.
cosign public-key --key <PRIVATE KEY FILE> --outfile <OUTPUT>
# extract public key from URL.
cosign public-key --key https://host.for/<FILE> --outfile <OUTPUT>
# extract public key from Azure Key Vault
cosign public-key --key azurekms://[VAULT_NAME][VAULT_URI]/[KEY]
# extract public key from AWS KMS
cosign public-key --key awskms://[ENDPOINT]/[ID/ALIAS/ARN]
# extract public key from Google Cloud KMS
cosign public-key --key gcpkms://projects/[PROJECT]/locations/global/keyRings/[KEYRING]/cryptoKeys/[KEY]
# extract public key from Hashicorp Vault KMS
cosign public-key --key hashivault://[KEY]`,

RunE: func(cmd *cobra.Command, args []string) error {
if !options.OneOf(o.Key, o.SecurityKey.Use) {
return &options.KeyParseError{}
}

writer := NamedWriter{Name: "", Writer: nil}
var f *os.File
// Open output file for public key if specified.
if *outFile != "" {
writer.Name = *outFile
if o.OutFile != "" {
writer.Name = o.OutFile
var err error
f, err = os.OpenFile(*outFile, os.O_WRONLY|os.O_CREATE, 0600)
f, err = os.OpenFile(o.OutFile, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return err
}
Expand All @@ -95,13 +134,16 @@ EXAMPLES
writer.Writer = os.Stdout
}
pk := Pkopts{
KeyRef: *key,
Sk: *sk,
Slot: *slot,
KeyRef: o.Key,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
}
return GetPublicKey(ctx, pk, writer, generate.GetPass)
return GetPublicKey(context.Background(), pk, writer, generate.GetPass)
},
}

options.AddPublicKeyOptions(cmd, o)
topLevel.AddCommand(cmd)
}

type Pkopts struct {
Expand Down
32 changes: 16 additions & 16 deletions cmd/cosign/cli/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
)

func addSign(topLevel *cobra.Command) {
so := &options.SignOptions{}
o := &options.SignOptions{}

cmd := &cobra.Command{
Use: "sign",
Expand Down Expand Up @@ -69,38 +69,38 @@ func addSign(topLevel *cobra.Command) {
if len(args) == 0 {
return flag.ErrHelp
}
switch so.Attachment {
switch o.Attachment {
case "sbom", "":
break
default:
return flag.ErrHelp
}
ko := sign.KeyOpts{
KeyRef: so.Key,
KeyRef: o.Key,
PassFunc: generate.GetPass,
Sk: so.SecurityKey.Use,
Slot: so.SecurityKey.Slot,
FulcioURL: so.Fulcio.URL,
IDToken: so.Fulcio.IdentityToken,
RekorURL: so.Rektor.URL,
OIDCIssuer: so.OIDC.Issuer,
OIDCClientID: so.OIDC.ClientID,
OIDCClientSecret: so.OIDC.ClientSecret,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
FulcioURL: o.Fulcio.URL,
IDToken: o.Fulcio.IdentityToken,
RekorURL: o.Rektor.URL,
OIDCIssuer: o.OIDC.Issuer,
OIDCClientID: o.OIDC.ClientID,
OIDCClientSecret: o.OIDC.ClientSecret,
}
annotationsMap, err := so.AnnotationsMap()
annotationsMap, err := o.AnnotationsMap()
if err != nil {
return err
}
if err := sign.SignCmd(context.Background(), ko, so.RegistryOpts, annotationsMap.Annotations, args, so.Cert, so.Upload, so.PayloadPath, so.Force, so.Recursive, so.Attachment); err != nil {
if so.Attachment == "" {
if err := sign.SignCmd(context.Background(), ko, o.RegistryOpts, annotationsMap.Annotations, args, o.Cert, o.Upload, o.PayloadPath, o.Force, o.Recursive, o.Attachment); err != nil {
if o.Attachment == "" {
return errors.Wrapf(err, "signing %v", args)
}
return errors.Wrapf(err, "signing attachement %s for image %v", so.Attachment, args)
return errors.Wrapf(err, "signing attachement %s for image %v", o.Attachment, args)
}
return nil
},
}

options.AddSignOptions(cmd, so)
options.AddSignOptions(cmd, o)
topLevel.AddCommand(cmd)
}
36 changes: 18 additions & 18 deletions cmd/cosign/cli/signblob.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
)

func addSignBlob(topLevel *cobra.Command) {
so := &options.SignBlobOptions{}
o := &options.SignBlobOptions{}

cmd := &cobra.Command{
Use: "sign-blob",
Expand All @@ -39,24 +39,24 @@ func addSignBlob(topLevel *cobra.Command) {
COSIGN_EXPERIMENTAL=1 cosign sign-blob <FILE>
# sign a blob with a local key pair file
cosign sign-blob -key cosign.key <FILE>
cosign sign-blob --key cosign.key <FILE>
# sign a blob with a key pair stored in Azure Key Vault
cosign sign-blob -key azurekms://[VAULT_NAME][VAULT_URI]/[KEY] <FILE>
cosign sign-blob --key azurekms://[VAULT_NAME][VAULT_URI]/[KEY] <FILE>
# sign a blob with a key pair stored in AWS KMS
cosign sign-blob -key awskms://[ENDPOINT]/[ID/ALIAS/ARN] <FILE>
cosign sign-blob --key awskms://[ENDPOINT]/[ID/ALIAS/ARN] <FILE>
# sign a blob with a key pair stored in Google Cloud KMS
cosign sign-blob -key gcpkms://projects/[PROJECT]/locations/global/keyRings/[KEYRING]/cryptoKeys/[KEY] <FILE>
cosign sign-blob --key gcpkms://projects/[PROJECT]/locations/global/keyRings/[KEYRING]/cryptoKeys/[KEY] <FILE>
# sign a blob with a key pair stored in Hashicorp Vault
cosign sign-blob -key hashivault://[KEY] <FILE>`,
cosign sign-blob --key hashivault://[KEY] <FILE>`,

RunE: func(cmd *cobra.Command, args []string) error {
// A key file is required unless we're in experimental mode!
if !options.EnableExperimental() {
if !options.OneOf(so.Key, so.SecurityKey.Use) {
if !options.OneOf(o.Key, o.SecurityKey.Use) {
return &options.KeyParseError{}
}
}
Expand All @@ -65,26 +65,26 @@ func addSignBlob(topLevel *cobra.Command) {
return flag.ErrHelp
}
ko := sign.KeyOpts{
KeyRef: so.Key,
KeyRef: o.Key,
PassFunc: generate.GetPass,
Sk: so.SecurityKey.Use,
Slot: so.SecurityKey.Slot,
FulcioURL: so.Fulcio.URL,
IDToken: so.Fulcio.IdentityToken,
RekorURL: so.Rektor.URL,
OIDCIssuer: so.OIDC.Issuer,
OIDCClientID: so.OIDC.ClientID,
OIDCClientSecret: so.OIDC.ClientSecret,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
FulcioURL: o.Fulcio.URL,
IDToken: o.Fulcio.IdentityToken,
RekorURL: o.Rektor.URL,
OIDCIssuer: o.OIDC.Issuer,
OIDCClientID: o.OIDC.ClientID,
OIDCClientSecret: o.OIDC.ClientSecret,
}
for _, blob := range args {
if _, err := sign.SignBlobCmd(context.Background(), ko, so.RegistryOpts, blob, so.Base64Output, so.Output); err != nil {
if _, err := sign.SignBlobCmd(context.Background(), ko, o.RegistryOpts, blob, o.Base64Output, o.Output); err != nil {
return errors.Wrapf(err, "signing %s", blob)
}
}
return nil
},
}

options.AddSignBlobOptions(cmd, so)
options.AddSignBlobOptions(cmd, o)
topLevel.AddCommand(cmd)
}
1 change: 1 addition & 0 deletions cmd/cosign/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func main() {
// escape the remaining args to let them be passed to cobra.
if len(os.Args) > 1 {
switch os.Args[1] {
case "public-key":
case "sign", "sign-blob":
// cobra.
default:
Expand Down

0 comments on commit ef9683a

Please sign in to comment.