From e4a316f4714700f80ba7bb7d31b7d14ab3e4edfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Batuhan=20Apayd=C4=B1n?= Date: Wed, 10 Nov 2021 14:24:32 +0300 Subject: [PATCH] feat: add output cert for keyless MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Batuhan Apaydın Co-authored-by: Furkan Türkal --- cmd/cosign/cli/options/signblob.go | 24 ++++++++++-------- cmd/cosign/cli/sign/sign_blob.go | 40 +++++++++++++++++++----------- cmd/cosign/cli/signblob.go | 2 +- pkg/version/version.go | 2 +- test/e2e_test.go | 2 +- 5 files changed, 43 insertions(+), 27 deletions(-) diff --git a/cmd/cosign/cli/options/signblob.go b/cmd/cosign/cli/options/signblob.go index 8086da15e370..e523d7b7d786 100644 --- a/cmd/cosign/cli/options/signblob.go +++ b/cmd/cosign/cli/options/signblob.go @@ -23,15 +23,16 @@ import ( // SignBlobOptions is the top level wrapper for the sign-blob command. type SignBlobOptions struct { - Key string - Base64Output bool - Output string // TODO: this should be the root output file arg. - SecurityKey SecurityKeyOptions - Fulcio FulcioOptions - Rekor RekorOptions - OIDC OIDCOptions - Registry RegistryOptions - Timeout time.Duration + Key string + Base64Output bool + OutputSignature string // TODO: this should be the root output file arg. + OutputCert string // TODO: this should be the root output file arg. + SecurityKey SecurityKeyOptions + Fulcio FulcioOptions + Rekor RekorOptions + OIDC OIDCOptions + Registry RegistryOptions + Timeout time.Duration } var _ Interface = (*SignBlobOptions)(nil) @@ -50,9 +51,12 @@ func (o *SignBlobOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&o.Base64Output, "b64", true, "whether to base64 encode the output") - cmd.Flags().StringVar(&o.Output, "output", "", + cmd.Flags().StringVar(&o.OutputSignature, "output-sig", "", "write the signature to FILE") + cmd.Flags().StringVar(&o.OutputCert, "output-cert", "", + "write the certificate to FILE") + cmd.Flags().DurationVar(&o.Timeout, "timeout", time.Second*30, "HTTP Timeout defaults to 30 seconds") } diff --git a/cmd/cosign/cli/sign/sign_blob.go b/cmd/cosign/cli/sign/sign_blob.go index aa3a1f41a771..0042e75ba99b 100644 --- a/cmd/cosign/cli/sign/sign_blob.go +++ b/cmd/cosign/cli/sign/sign_blob.go @@ -52,7 +52,7 @@ type KeyOpts struct { } // nolint -func SignBlobCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOptions, payloadPath string, b64 bool, output string, timeout time.Duration) ([]byte, error) { +func SignBlobCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOptions, payloadPath string, b64 bool, outputSig string, outputCert string, timeout time.Duration) ([]byte, error) { var payload []byte var err error @@ -99,37 +99,49 @@ func SignBlobCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOption return nil, err } fmt.Fprintln(os.Stderr, "tlog entry created with index:", *entry.LogIndex) + + fmt.Fprintln(os.Stderr, "writing certificate to disk:", outputCert) + err = writeToDiskOrStdout(outputCert, b64, rekorBytes) + if err != nil { + return nil, err + } } + err = writeToDiskOrStdout(outputSig, b64, sig) + if err != nil { + return nil, err + } + + return sig, nil +} + +func writeToDiskOrStdout(output string, b64 bool, content []byte) error { if output != "" { f, err := os.Create(output) if err != nil { - return nil, err + return err } defer f.Close() if b64 { - _, err = f.Write([]byte(base64.StdEncoding.EncodeToString(sig))) + _, err = f.Write([]byte(base64.StdEncoding.EncodeToString(content))) if err != nil { - return nil, err + return err } } else { - _, err = f.Write(sig) + _, err = f.Write(content) if err != nil { - return nil, err + return err } } - - fmt.Printf("Signature wrote in the file %s\n", f.Name()) } else { if b64 { - sig = []byte(base64.StdEncoding.EncodeToString(sig)) - fmt.Println(string(sig)) - } else if _, err := os.Stdout.Write(sig); err != nil { + content = []byte(base64.StdEncoding.EncodeToString(content)) + fmt.Println(string(content)) + } else if _, err := os.Stdout.Write(content); err != nil { // No newline if using the raw signature - return nil, err + return err } } - - return sig, nil + return nil } diff --git a/cmd/cosign/cli/signblob.go b/cmd/cosign/cli/signblob.go index c46239d22855..704cae165dae 100644 --- a/cmd/cosign/cli/signblob.go +++ b/cmd/cosign/cli/signblob.go @@ -74,7 +74,7 @@ func SignBlob() *cobra.Command { OIDCClientSecret: o.OIDC.ClientSecret, } for _, blob := range args { - if _, err := sign.SignBlobCmd(cmd.Context(), ko, o.Registry, blob, o.Base64Output, o.Output, o.Timeout); err != nil { + if _, err := sign.SignBlobCmd(cmd.Context(), ko, o.Registry, blob, o.Base64Output, o.OutputSignature, o.OutputCert, o.Timeout); err != nil { return errors.Wrapf(err, "signing %s", blob) } } diff --git a/pkg/version/version.go b/pkg/version/version.go index 43fe8e7aa492..97205cf537e0 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -28,7 +28,7 @@ import ( // This is the fallback data used when version information from git is not // provided via go ldflags (e.g. via Makefile). var ( - // Output of "git describe". The prerequisite is that the branch should be + // OutputSignature of "git describe". The prerequisite is that the branch should be // tagged using the correct versioning strategy. GitVersion = "devel" // SHA1 from git, output of $(git rev-parse HEAD) diff --git a/test/e2e_test.go b/test/e2e_test.go index 38ec1917dc28..254e3a1d41e4 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -409,7 +409,7 @@ func TestSignBlob(t *testing.T) { KeyRef: privKeyPath1, PassFunc: passFunc, } - sig, err := sign.SignBlobCmd(ctx, ko, options.RegistryOptions{}, bp, true, "", time.Duration(30*time.Second)) + sig, err := sign.SignBlobCmd(ctx, ko, options.RegistryOptions{}, bp, true, "", "", time.Duration(30*time.Second)) if err != nil { t.Fatal(err) }