From a3772a2733b336b5a3c6335b624d6b9ae3346fbf Mon Sep 17 00:00:00 2001 From: Carlos A Becker Date: Sun, 28 Nov 2021 22:13:42 -0300 Subject: [PATCH 1/2] feat: sign --output-certificate and verify --cert Signed-off-by: Carlos A Becker Co-authored-by: Matt Moore --- cmd/cosign/cli/options/sign.go | 25 +++++++++++------ cmd/cosign/cli/options/verify.go | 4 +++ cmd/cosign/cli/sign.go | 4 ++- cmd/cosign/cli/sign/sign.go | 38 ++++++++++++++++++++++---- cmd/cosign/cli/sign/sign_blob.go | 14 ++-------- cmd/cosign/cli/sign/sign_test.go | 2 +- cmd/cosign/cli/verify.go | 1 + cmd/cosign/cli/verify/verify.go | 41 ++++++++++++++++++++++++++-- cmd/cosign/cli/verify/verify_blob.go | 22 +-------------- doc/cosign_dockerfile_verify.md | 1 + doc/cosign_manifest_verify.md | 1 + doc/cosign_sign.md | 2 ++ doc/cosign_verify.md | 1 + test/e2e_test.go | 26 +++++++++--------- 14 files changed, 118 insertions(+), 64 deletions(-) diff --git a/cmd/cosign/cli/options/sign.go b/cmd/cosign/cli/options/sign.go index 38b59d44f7e..d5527d64b0c 100644 --- a/cmd/cosign/cli/options/sign.go +++ b/cmd/cosign/cli/options/sign.go @@ -21,14 +21,16 @@ import ( // SignOptions is the top level wrapper for the sign command. type SignOptions struct { - Key string - Cert string - Upload bool - Output string - PayloadPath string - Force bool - Recursive bool - Attachment string + Key string + Cert string + Upload bool + Output string // deprecated: TODO remove when the output flag is fully deprecated + OutputSignature string // TODO: this should be the root output file arg. + OutputCertificate string + PayloadPath string + Force bool + Recursive bool + Attachment string Rekor RekorOptions Fulcio FulcioOptions @@ -58,9 +60,16 @@ func (o *SignOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&o.Upload, "upload", true, "whether to upload the signature") + // TODO: remove when output flag is fully deprecated cmd.Flags().StringVar(&o.Output, "output", "", "write the signature to FILE") + cmd.Flags().StringVar(&o.OutputSignature, "output-signature", "", + "write the signature to FILE") + + cmd.Flags().StringVar(&o.OutputCertificate, "output-certificate", "", + "write the certificate to FILE") + cmd.Flags().StringVar(&o.PayloadPath, "payload", "", "path to a payload file to use rather than generating one") diff --git a/cmd/cosign/cli/options/verify.go b/cmd/cosign/cli/options/verify.go index 6d8f2586819..925c7db4256 100644 --- a/cmd/cosign/cli/options/verify.go +++ b/cmd/cosign/cli/options/verify.go @@ -22,6 +22,7 @@ import ( // VerifyOptions is the top level wrapper for the `verify` command. type VerifyOptions struct { Key string + Cert string CertEmail string // TODO: merge into fulcio option as read mode? CheckClaims bool Attachment string @@ -48,6 +49,9 @@ func (o *VerifyOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.Key, "key", "", "path to the public key file, KMS URI or Kubernetes Secret") + cmd.Flags().StringVar(&o.Cert, "cert", "", + "path to the public certificate") + cmd.Flags().StringVar(&o.CertEmail, "cert-email", "", "the email expected in a valid fulcio cert") diff --git a/cmd/cosign/cli/sign.go b/cmd/cosign/cli/sign.go index 0f6ab8ef7c9..b193a30318b 100644 --- a/cmd/cosign/cli/sign.go +++ b/cmd/cosign/cli/sign.go @@ -20,6 +20,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/sigstore/cosign/cmd/cosign/cli/generate" "github.com/sigstore/cosign/cmd/cosign/cli/options" @@ -28,6 +29,7 @@ import ( func Sign() *cobra.Command { o := &options.SignOptions{} + viper.RegisterAlias("output", "output-signature") cmd := &cobra.Command{ Use: "sign", @@ -89,7 +91,7 @@ func Sign() *cobra.Command { if err != nil { return err } - if err := sign.SignCmd(cmd.Context(), ko, o.Registry, annotationsMap.Annotations, args, o.Cert, o.Upload, o.Output, o.PayloadPath, o.Force, o.Recursive, o.Attachment); err != nil { + if err := sign.SignCmd(cmd.Context(), ko, o.Registry, annotationsMap.Annotations, args, o.Cert, o.Upload, o.OutputSignature, o.OutputCertificate, o.PayloadPath, o.Force, o.Recursive, o.Attachment); err != nil { if o.Attachment == "" { return errors.Wrapf(err, "signing %v", args) } diff --git a/cmd/cosign/cli/sign/sign.go b/cmd/cosign/cli/sign/sign.go index 390acc34f69..5f39ae54c16 100644 --- a/cmd/cosign/cli/sign/sign.go +++ b/cmd/cosign/cli/sign/sign.go @@ -123,7 +123,7 @@ func GetAttachedImageRef(ref name.Reference, attachment string, opts ...ociremot // nolint func SignCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOptions, annotations map[string]interface{}, - imgs []string, certPath string, upload bool, output string, payloadPath string, force bool, recursive bool, attachment string) error { + imgs []string, certPath string, upload bool, outputSignature, outputCertificate string, payloadPath string, force bool, recursive bool, attachment string) error { if options.EnableExperimental() { if options.NOf(ko.KeyRef, ko.Sk) > 1 { return &options.KeyParseError{} @@ -182,7 +182,7 @@ func SignCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOptions, a if err != nil { return errors.Wrap(err, "accessing image") } - err = signDigest(ctx, digest, staticPayload, ko, regOpts, annotations, upload, output, force, dd, sv, se) + err = signDigest(ctx, digest, staticPayload, ko, regOpts, annotations, upload, outputSignature, outputCertificate, force, dd, sv, se) if err != nil { return errors.Wrap(err, "signing digest") } @@ -202,7 +202,7 @@ func SignCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOptions, a } digest := ref.Context().Digest(d.String()) - err = signDigest(ctx, digest, staticPayload, ko, regOpts, annotations, upload, output, force, dd, sv, se) + err = signDigest(ctx, digest, staticPayload, ko, regOpts, annotations, upload, outputSignature, outputCertificate, force, dd, sv, se) if err != nil { return errors.Wrap(err, "signing digest") } @@ -216,7 +216,7 @@ func SignCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOptions, a } func signDigest(ctx context.Context, digest name.Digest, payload []byte, ko KeyOpts, - regOpts options.RegistryOptions, annotations map[string]interface{}, upload bool, output string, force bool, + regOpts options.RegistryOptions, annotations map[string]interface{}, upload bool, outputSignature, outputCertificate string, force bool, dd mutate.DupeDetector, sv *SignerVerifier, se oci.SignedEntity) error { var err error // The payload can be passed to skip generation. @@ -237,8 +237,8 @@ func signDigest(ctx context.Context, digest name.Digest, payload []byte, ko KeyO b64sig := base64.StdEncoding.EncodeToString(signature) out := os.Stdout - if output != "" { - out, err = os.Create(output) + if outputSignature != "" { + out, err = os.Create(outputSignature) if err != nil { return errors.Wrap(err, "create signature file") } @@ -288,6 +288,19 @@ func signDigest(ctx context.Context, digest name.Digest, payload []byte, ko KeyO if err := ociremote.WriteSignatures(digest.Repository, newSE, walkOpts...); err != nil { return err } + + if outputCertificate != "" { + rekorBytes, err := sv.Bytes(ctx) + if err != nil { + return err + } + + if err := os.WriteFile(outputCertificate, rekorBytes, 0600); err != nil { + return err + } + // TODO: maybe accept a --b64 flag as well? + } + return nil } @@ -474,3 +487,16 @@ func (c *SignerVerifier) Close() { c.close() } } + +func (c *SignerVerifier) Bytes(ctx context.Context) ([]byte, error) { + if c.Cert != nil { + fmt.Fprintf(os.Stderr, "using ephemeral certificate:\n%s\n", string(c.Cert)) + return c.Cert, nil + } + + pemBytes, err := sigs.PublicKeyPem(c, signatureoptions.WithContext(ctx)) + if err != nil { + return nil, err + } + return pemBytes, nil +} diff --git a/cmd/cosign/cli/sign/sign_blob.go b/cmd/cosign/cli/sign/sign_blob.go index 1f2e06cea61..f1bea897099 100644 --- a/cmd/cosign/cli/sign/sign_blob.go +++ b/cmd/cosign/cli/sign/sign_blob.go @@ -29,7 +29,6 @@ import ( "github.com/sigstore/cosign/cmd/cosign/cli/options" "github.com/sigstore/cosign/pkg/cosign" - "github.com/sigstore/cosign/pkg/signature" rekorClient "github.com/sigstore/rekor/pkg/client" signatureoptions "github.com/sigstore/sigstore/pkg/signature/options" ) @@ -84,16 +83,9 @@ func SignBlobCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOption } if options.EnableExperimental() { - // TODO: Refactor with sign.go - if sv.Cert != nil { - fmt.Fprintf(os.Stderr, "signing with ephemeral certificate:\n%s\n", string(sv.Cert)) - rekorBytes = sv.Cert - } else { - pemBytes, err := signature.PublicKeyPem(sv, signatureoptions.WithContext(ctx)) - if err != nil { - return nil, err - } - rekorBytes = pemBytes + rekorBytes, err := sv.Bytes(ctx) + if err != nil { + return nil, err } rekorClient, err := rekorClient.GetRekorClient(ko.RekorURL) if err != nil { diff --git a/cmd/cosign/cli/sign/sign_test.go b/cmd/cosign/cli/sign/sign_test.go index b8eac27691b..6d236c1bfcc 100644 --- a/cmd/cosign/cli/sign/sign_test.go +++ b/cmd/cosign/cli/sign/sign_test.go @@ -37,7 +37,7 @@ func TestSignCmdLocalKeyAndSk(t *testing.T) { Sk: true, }, } { - err := SignCmd(ctx, ko, options.RegistryOptions{}, nil, nil, "", false, "", "", false, false, "") + err := SignCmd(ctx, ko, options.RegistryOptions{}, nil, nil, "", false, "", "", "", false, false, "") if (errors.Is(err, &options.KeyParseError{}) == false) { t.Fatal("expected KeyParseError") } diff --git a/cmd/cosign/cli/verify.go b/cmd/cosign/cli/verify.go index bec8bb8003f..b3518996487 100644 --- a/cmd/cosign/cli/verify.go +++ b/cmd/cosign/cli/verify.go @@ -87,6 +87,7 @@ against the transparency log.`, RegistryOptions: o.Registry, CheckClaims: o.CheckClaims, KeyRef: o.Key, + CertRef: o.Cert, CertEmail: o.CertEmail, Sk: o.SecurityKey.Use, Slot: o.SecurityKey.Slot, diff --git a/cmd/cosign/cli/verify/verify.go b/cmd/cosign/cli/verify/verify.go index 88be54780f9..87cac352362 100644 --- a/cmd/cosign/cli/verify/verify.go +++ b/cmd/cosign/cli/verify/verify.go @@ -18,6 +18,8 @@ package verify import ( "context" "crypto" + "crypto/ecdsa" + "encoding/base64" "encoding/json" "flag" "fmt" @@ -34,6 +36,7 @@ import ( "github.com/sigstore/cosign/pkg/cosign/pkcs11key" "github.com/sigstore/cosign/pkg/oci" sigs "github.com/sigstore/cosign/pkg/signature" + "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/signature" "github.com/sigstore/sigstore/pkg/signature/payload" ) @@ -43,6 +46,7 @@ import ( type VerifyCommand struct { options.RegistryOptions CheckClaims bool + CertRef string KeyRef string CertEmail string Sk bool @@ -73,7 +77,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) { c.HashAlgorithm = crypto.SHA256 } - if !options.OneOf(c.KeyRef, c.Sk) && !options.EnableExperimental() { + if !options.OneOf(c.KeyRef, c.CertRef, c.Sk) && !options.EnableExperimental() { return &options.KeyParseError{} } ociremoteOpts, err := c.ClientOpts(ctx) @@ -93,10 +97,12 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) { co.RootCerts = fulcio.GetRoots() } keyRef := c.KeyRef + certRef := c.CertRef // Keys are optional! var pubKey signature.Verifier - if keyRef != "" { + switch { + case keyRef != "": pubKey, err = sigs.PublicKeyFromKeyRefWithHashAlgo(ctx, keyRef, c.HashAlgorithm) if err != nil { return errors.Wrap(err, "loading public key") @@ -105,7 +111,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) { if ok { defer pkcs11Key.Close() } - } else if c.Sk { + case c.Sk: sk, err := pivkey.GetKeyWithSlot(c.Slot) if err != nil { return errors.Wrap(err, "opening piv token") @@ -115,6 +121,11 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) { if err != nil { return errors.Wrap(err, "initializing piv token verifier") } + case certRef != "": + pubKey, err = loadCertFromFile(c.CertRef) + if err != nil { + return err + } } co.SigVerifier = pubKey @@ -224,3 +235,27 @@ func PrintVerification(imgRef string, verified []oci.Signature, output string) { fmt.Printf("\n%s\n", string(b)) } } + +func loadCertFromFile(path string) (*signature.ECDSAVerifier, error) { + pems, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + var out []byte + out, err = base64.StdEncoding.DecodeString(string(pems)) + if err != nil { + // not a base64 + out = pems + } + + certs, err := cryptoutils.UnmarshalCertificatesFromPEM(out) + if err != nil { + return nil, err + } + if len(certs) == 0 { + return nil, errors.New("no certs found in pem file") + } + cert := certs[0] + return signature.LoadECDSAVerifier(cert.PublicKey.(*ecdsa.PublicKey), crypto.SHA256) +} diff --git a/cmd/cosign/cli/verify/verify_blob.go b/cmd/cosign/cli/verify/verify_blob.go index 0f5b5538c67..05b4649ea71 100644 --- a/cmd/cosign/cli/verify/verify_blob.go +++ b/cmd/cosign/cli/verify/verify_blob.go @@ -112,27 +112,7 @@ func VerifyBlobCmd(ctx context.Context, ko sign.KeyOpts, certRef, sigRef, blobRe return errors.Wrap(err, "loading public key from token") } case certRef != "": - pems, err := os.ReadFile(certRef) - if err != nil { - return err - } - - var out []byte - out, err = base64.StdEncoding.DecodeString(string(pems)) - if err != nil { - // not a base64 - out = pems - } - - certs, err := cryptoutils.UnmarshalCertificatesFromPEM(out) - if err != nil { - return err - } - if len(certs) == 0 { - return errors.New("no certs found in pem file") - } - cert = certs[0] - pubKey, err = sigstoresigs.LoadECDSAVerifier(cert.PublicKey.(*ecdsa.PublicKey), crypto.SHA256) + pubKey, err = loadCertFromFile(certRef) if err != nil { return err } diff --git a/doc/cosign_dockerfile_verify.md b/doc/cosign_dockerfile_verify.md index f3d4be77b23..c172e982529 100644 --- a/doc/cosign_dockerfile_verify.md +++ b/doc/cosign_dockerfile_verify.md @@ -57,6 +57,7 @@ cosign dockerfile verify [flags] --attachment string related image attachment to sign (sbom), default none --attachment-tag-prefix [AttachmentTagPrefix]sha256-[TargetImageDigest].[AttachmentName] optional custom prefix to use for attached image tags. Attachment images are tagged as: [AttachmentTagPrefix]sha256-[TargetImageDigest].[AttachmentName] --base-image-only only verify the base image (the last FROM image in the Dockerfile) + --cert string path to the public certificate --cert-email string the email expected in a valid fulcio cert --check-claims whether to check the claims found (default true) -h, --help help for verify diff --git a/doc/cosign_manifest_verify.md b/doc/cosign_manifest_verify.md index a15d0b761f2..f6eb4810cc0 100644 --- a/doc/cosign_manifest_verify.md +++ b/doc/cosign_manifest_verify.md @@ -51,6 +51,7 @@ cosign manifest verify [flags] -a, --annotations strings extra key=value pairs to sign --attachment string related image attachment to sign (sbom), default none --attachment-tag-prefix [AttachmentTagPrefix]sha256-[TargetImageDigest].[AttachmentName] optional custom prefix to use for attached image tags. Attachment images are tagged as: [AttachmentTagPrefix]sha256-[TargetImageDigest].[AttachmentName] + --cert string path to the public certificate --cert-email string the email expected in a valid fulcio cert --check-claims whether to check the claims found (default true) -h, --help help for verify diff --git a/doc/cosign_sign.md b/doc/cosign_sign.md index 2692cb29c97..580bff5c22e 100644 --- a/doc/cosign_sign.md +++ b/doc/cosign_sign.md @@ -65,6 +65,8 @@ cosign sign [flags] --oidc-client-secret string [EXPERIMENTAL] OIDC client secret for application --oidc-issuer string [EXPERIMENTAL] OIDC provider to be used to issue ID token (default "https://oauth2.sigstore.dev/auth") --output string write the signature to FILE + --output-certificate string write the certificate to FILE + --output-signature string write the signature to FILE --payload string path to a payload file to use rather than generating one -r, --recursive if a multi-arch image is specified, additionally sign each discrete image --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") diff --git a/doc/cosign_verify.md b/doc/cosign_verify.md index b24748a77f8..70fa6a893cd 100644 --- a/doc/cosign_verify.md +++ b/doc/cosign_verify.md @@ -61,6 +61,7 @@ cosign verify [flags] -a, --annotations strings extra key=value pairs to sign --attachment string related image attachment to sign (sbom), default none --attachment-tag-prefix [AttachmentTagPrefix]sha256-[TargetImageDigest].[AttachmentName] optional custom prefix to use for attached image tags. Attachment images are tagged as: [AttachmentTagPrefix]sha256-[TargetImageDigest].[AttachmentName] + --cert string path to the public certificate --cert-email string the email expected in a valid fulcio cert --check-claims whether to check the claims found (default true) -h, --help help for verify diff --git a/test/e2e_test.go b/test/e2e_test.go index da3db133ee1..e03cc499b3e 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -108,7 +108,7 @@ func TestSignVerify(t *testing.T) { // Now sign the image ko := sign.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) // Now verify and download should work! must(verify(pubKeyPath, imgName, true, nil, ""), t) @@ -119,7 +119,7 @@ func TestSignVerify(t *testing.T) { // Sign the image with an annotation annotations := map[string]interface{}{"foo": "bar"} - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, annotations, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, annotations, []string{imgName}, "", true, "", "", "", false, false, ""), t) // It should match this time. must(verify(pubKeyPath, imgName, true, map[string]interface{}{"foo": "bar"}, ""), t) @@ -143,7 +143,7 @@ func TestSignVerifyClean(t *testing.T) { // Now sign the image ko := sign.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) // Now verify and download should work! must(verify(pubKeyPath, imgName, true, nil, ""), t) @@ -235,7 +235,7 @@ func TestBundle(t *testing.T) { } // Sign the image - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) // Make sure verify works must(verify(pubKeyPath, imgName, true, nil, ""), t) @@ -265,14 +265,14 @@ func TestDuplicateSign(t *testing.T) { // Now sign the image ko := sign.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) // Now verify and download should work! must(verify(pubKeyPath, imgName, true, nil, ""), t) must(download.SignatureCmd(ctx, options.RegistryOptions{}, imgName), t) // Signing again should work just fine... - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) se, err := ociremote.SignedEntity(ref, ociremote.WithRemoteOptions(registryClientOpts(ctx)...)) must(err, t) @@ -364,14 +364,14 @@ func TestMultipleSignatures(t *testing.T) { // Now sign the image with one key ko := sign.KeyOpts{KeyRef: priv1, PassFunc: passFunc} - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) // Now verify should work with that one, but not the other must(verify(pub1, imgName, true, nil, ""), t) mustErr(verify(pub2, imgName, true, nil, ""), t) // Now sign with the other key too ko.KeyRef = priv2 - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) // Now verify should work with both must(verify(pub1, imgName, true, nil, ""), t) @@ -626,7 +626,7 @@ func TestSaveLoad(t *testing.T) { ctx := context.Background() // Now sign the image and verify it ko := sign.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) must(verify(pubKeyPath, imgName, true, nil, ""), t) // save the image to a temp dir @@ -654,7 +654,7 @@ func TestSaveLoadAttestation(t *testing.T) { ctx := context.Background() // Now sign the image and verify it ko := sign.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) must(verify(pubKeyPath, imgName, true, nil, ""), t) // now, append an attestation to the image @@ -740,7 +740,7 @@ func TestAttachSBOM(t *testing.T) { // Now sign the sbom with one key ko1 := sign.KeyOpts{KeyRef: privKeyPath1, PassFunc: passFunc} - must(sign.SignCmd(ctx, ko1, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, "sbom"), t) + must(sign.SignCmd(ctx, ko1, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, "sbom"), t) // Now verify should work with that one, but not the other must(verify(pubKeyPath1, imgName, true, nil, "sbom"), t) @@ -778,7 +778,7 @@ func TestTlog(t *testing.T) { PassFunc: passFunc, RekorURL: rekorURL, } - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) // Now verify should work! must(verify(pubKeyPath, imgName, true, nil, ""), t) @@ -790,7 +790,7 @@ func TestTlog(t *testing.T) { mustErr(verify(pubKeyPath, imgName, true, nil, ""), t) // Sign again with the tlog env var on - must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", false, false, ""), t) + must(sign.SignCmd(ctx, ko, options.RegistryOptions{}, nil, []string{imgName}, "", true, "", "", "", false, false, ""), t) // And now verify works! must(verify(pubKeyPath, imgName, true, nil, ""), t) } From 53646d709ad8b7d2ed4cc63a8ca2572e70f77b26 Mon Sep 17 00:00:00 2001 From: Carlos A Becker Date: Wed, 1 Dec 2021 21:31:27 -0300 Subject: [PATCH 2/2] fix: merge conflict Signed-off-by: Carlos A Becker --- cmd/cosign/cli/sign/sign.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/cosign/cli/sign/sign.go b/cmd/cosign/cli/sign/sign.go index 27b54e4ef68..1729183ea2d 100644 --- a/cmd/cosign/cli/sign/sign.go +++ b/cmd/cosign/cli/sign/sign.go @@ -226,9 +226,8 @@ func signDigest(ctx context.Context, digest name.Digest, payload []byte, ko KeyO return err } - out := os.Stdout if outputSignature != "" { - out, err = os.Create(outputSignature) + out, err := os.Create(outputSignature) if err != nil { return errors.Wrap(err, "create signature file") }