From d44259202830948517db361efd85fca6e87776ff Mon Sep 17 00:00:00 2001 From: Naveen <172697+naveensrinivasan@users.noreply.github.com> Date: Tue, 9 Nov 2021 11:34:21 -0600 Subject: [PATCH] Included timeout option for uploading to Rekor (#1001) Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com> --- cmd/cosign/cli/attest.go | 5 +++-- cmd/cosign/cli/attest/attest.go | 5 +++-- cmd/cosign/cli/options/attest.go | 6 ++++++ cmd/cosign/cli/options/policy.go | 7 +++++++ cmd/cosign/cli/options/signblob.go | 6 ++++++ cmd/cosign/cli/policy_init.go | 2 +- cmd/cosign/cli/sign/sign.go | 4 +++- cmd/cosign/cli/sign/sign_blob.go | 5 +++-- cmd/cosign/cli/signblob.go | 4 ++-- doc/cosign_attest.md | 3 ++- doc/cosign_policy_sign.md | 1 + doc/cosign_sign-blob.md | 3 ++- pkg/cosign/tlog.go | 18 ++++++++++++------ test/e2e_test.go | 9 ++++----- 14 files changed, 55 insertions(+), 23 deletions(-) diff --git a/cmd/cosign/cli/attest.go b/cmd/cosign/cli/attest.go index 72da4905703..dee92075b77 100644 --- a/cmd/cosign/cli/attest.go +++ b/cmd/cosign/cli/attest.go @@ -34,7 +34,7 @@ func Attest() *cobra.Command { Example: ` cosign attest --key | [--predicate ] [--a key=value] [--upload=true|false] [--f] [--r] # attach an attestation to a container image Google sign-in (experimental) - COSIGN_EXPERIMENTAL=1 cosign attest --predicate --type + COSIGN_EXPERIMENTAL=1 cosign attest --timeout 90s --predicate --type # attach an attestation to a container image with a local key pair file cosign attest --predicate --type --key cosign.key @@ -70,7 +70,8 @@ func Attest() *cobra.Command { OIDCClientSecret: o.OIDC.ClientSecret, } for _, img := range args { - if err := attest.AttestCmd(cmd.Context(), ko, o.Registry, img, o.Cert, o.NoUpload, o.Predicate.Path, o.Force, o.Predicate.Type); err != nil { + if err := attest.AttestCmd(cmd.Context(), ko, o.Registry, img, o.Cert, o.NoUpload, + o.Predicate.Path, o.Force, o.Predicate.Type, o.Timeout); err != nil { return errors.Wrapf(err, "signing %s", img) } } diff --git a/cmd/cosign/cli/attest/attest.go b/cmd/cosign/cli/attest/attest.go index edc8a63e96f..86efcefe1f3 100644 --- a/cmd/cosign/cli/attest/attest.go +++ b/cmd/cosign/cli/attest/attest.go @@ -22,6 +22,7 @@ import ( "encoding/json" "fmt" "os" + "time" "github.com/google/go-containerregistry/pkg/name" v1 "github.com/google/go-containerregistry/pkg/v1" @@ -44,7 +45,7 @@ import ( //nolint func AttestCmd(ctx context.Context, ko sign.KeyOpts, regOpts options.RegistryOptions, imageRef string, certPath string, - noUpload bool, predicatePath string, force bool, predicateType string) error { + noUpload bool, predicatePath string, force bool, predicateType string, timeout time.Duration) error { // A key file or token is required unless we're in experimental mode! if options.EnableExperimental() { if options.NOf(ko.KeyRef, ko.Sk) > 1 { @@ -129,7 +130,7 @@ func AttestCmd(ctx context.Context, ko sign.KeyOpts, regOpts options.RegistryOpt return err } else if uploadTLog { bundle, err := sign.UploadToTlog(ctx, sv, ko.RekorURL, func(r *client.Rekor, b []byte) (*models.LogEntryAnon, error) { - return cosign.TLogUploadInTotoAttestation(r, signedPayload, b) + return cosign.TLogUploadInTotoAttestation(r, signedPayload, b, timeout) }) if err != nil { return err diff --git a/cmd/cosign/cli/options/attest.go b/cmd/cosign/cli/options/attest.go index f9a1fad6fd3..251a73afaca 100644 --- a/cmd/cosign/cli/options/attest.go +++ b/cmd/cosign/cli/options/attest.go @@ -16,6 +16,8 @@ package options import ( + "time" + "github.com/spf13/cobra" ) @@ -26,6 +28,7 @@ type AttestOptions struct { NoUpload bool Force bool Recursive bool + Timeout time.Duration Rekor RekorOptions Fulcio FulcioOptions @@ -60,4 +63,7 @@ func (o *AttestOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().BoolVarP(&o.Recursive, "recursive", "r", false, "if a multi-arch image is specified, additionally sign each discrete image") + + cmd.Flags().DurationVar(&o.Timeout, "timeout", time.Second*30, + "HTTP Timeout defaults to 30 seconds") } diff --git a/cmd/cosign/cli/options/policy.go b/cmd/cosign/cli/options/policy.go index d7e54a746c9..7f2f0b35c00 100644 --- a/cmd/cosign/cli/options/policy.go +++ b/cmd/cosign/cli/options/policy.go @@ -16,6 +16,8 @@ package options import ( + "time" + "github.com/spf13/cobra" ) @@ -61,6 +63,7 @@ type PolicySignOptions struct { Registry RegistryOptions Fulcio FulcioOptions Rekor RekorOptions + Timeout time.Duration OIDC OIDCOptions } @@ -74,6 +77,10 @@ func (o *PolicySignOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.OutFile, "out", "o", "output policy locally") + + cmd.Flags().DurationVar(&o.Timeout, "timeout", time.Second*30, + "HTTP Timeout defaults to 30 seconds") + o.Registry.AddFlags(cmd) o.Fulcio.AddFlags(cmd) o.Rekor.AddFlags(cmd) diff --git a/cmd/cosign/cli/options/signblob.go b/cmd/cosign/cli/options/signblob.go index 600993d4a79..8086da15e37 100644 --- a/cmd/cosign/cli/options/signblob.go +++ b/cmd/cosign/cli/options/signblob.go @@ -16,6 +16,8 @@ package options import ( + "time" + "github.com/spf13/cobra" ) @@ -29,6 +31,7 @@ type SignBlobOptions struct { Rekor RekorOptions OIDC OIDCOptions Registry RegistryOptions + Timeout time.Duration } var _ Interface = (*SignBlobOptions)(nil) @@ -49,4 +52,7 @@ func (o *SignBlobOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.Output, "output", "", "write the signature to FILE") + + cmd.Flags().DurationVar(&o.Timeout, "timeout", time.Second*30, + "HTTP Timeout defaults to 30 seconds") } diff --git a/cmd/cosign/cli/policy_init.go b/cmd/cosign/cli/policy_init.go index 8f377798822..8848a35a972 100644 --- a/cmd/cosign/cli/policy_init.go +++ b/cmd/cosign/cli/policy_init.go @@ -248,7 +248,7 @@ func signPolicy() *cobra.Command { if err != nil { return err } - entry, err := cosign.TLogUpload(rekorClient, sig, signed.Signed, rekorBytes) + entry, err := cosign.TLogUpload(rekorClient, sig, signed.Signed, rekorBytes, o.Timeout) if err != nil { return err } diff --git a/cmd/cosign/cli/sign/sign.go b/cmd/cosign/cli/sign/sign.go index 7adb5f1d81e..cd04d3b58d3 100644 --- a/cmd/cosign/cli/sign/sign.go +++ b/cmd/cosign/cli/sign/sign.go @@ -29,6 +29,7 @@ import ( "os" "path/filepath" "strings" + "time" "github.com/google/go-containerregistry/pkg/name" v1 "github.com/google/go-containerregistry/pkg/v1" @@ -245,7 +246,8 @@ func signDigest(ctx context.Context, digest name.Digest, payload []byte, ko KeyO return err } else if uploadTLog { bundle, err := UploadToTlog(ctx, sv, ko.RekorURL, func(r *client.Rekor, b []byte) (*models.LogEntryAnon, error) { - return cosign.TLogUpload(r, signature, payload, b) + // TODO - Defaulting the timeout to zero as the CLI doesn't accept timeout. + return cosign.TLogUpload(r, signature, payload, b, time.Duration(0)) }) if err != nil { return err diff --git a/cmd/cosign/cli/sign/sign_blob.go b/cmd/cosign/cli/sign/sign_blob.go index 2c441bba6ef..aa3a1f41a77 100644 --- a/cmd/cosign/cli/sign/sign_blob.go +++ b/cmd/cosign/cli/sign/sign_blob.go @@ -23,6 +23,7 @@ import ( "io" "os" "path/filepath" + "time" "github.com/pkg/errors" @@ -51,7 +52,7 @@ type KeyOpts struct { } // nolint -func SignBlobCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOptions, payloadPath string, b64 bool, output string) ([]byte, error) { +func SignBlobCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOptions, payloadPath string, b64 bool, output string, timeout time.Duration) ([]byte, error) { var payload []byte var err error @@ -93,7 +94,7 @@ func SignBlobCmd(ctx context.Context, ko KeyOpts, regOpts options.RegistryOption if err != nil { return nil, err } - entry, err := cosign.TLogUpload(rekorClient, sig, payload, rekorBytes) + entry, err := cosign.TLogUpload(rekorClient, sig, payload, rekorBytes, timeout) if err != nil { return nil, err } diff --git a/cmd/cosign/cli/signblob.go b/cmd/cosign/cli/signblob.go index 628aa115a23..c46239d2285 100644 --- a/cmd/cosign/cli/signblob.go +++ b/cmd/cosign/cli/signblob.go @@ -33,7 +33,7 @@ func SignBlob() *cobra.Command { Example: ` cosign sign-blob --key | # sign a blob with Google sign-in (experimental) - COSIGN_EXPERIMENTAL=1 cosign sign-blob + COSIGN_EXPERIMENTAL=1 cosign --timeout 90s sign-blob # sign a blob with a local key pair file cosign sign-blob --key cosign.key @@ -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); err != nil { + if _, err := sign.SignBlobCmd(cmd.Context(), ko, o.Registry, blob, o.Base64Output, o.Output, o.Timeout); err != nil { return errors.Wrapf(err, "signing %s", blob) } } diff --git a/doc/cosign_attest.md b/doc/cosign_attest.md index 469184e7b1c..a879c83ca0d 100644 --- a/doc/cosign_attest.md +++ b/doc/cosign_attest.md @@ -12,7 +12,7 @@ cosign attest [flags] cosign attest --key | [--predicate ] [--a key=value] [--upload=true|false] [--f] [--r] # attach an attestation to a container image Google sign-in (experimental) - COSIGN_EXPERIMENTAL=1 cosign attest --predicate --type + COSIGN_EXPERIMENTAL=1 cosign attest --timeout 90s --predicate --type # attach an attestation to a container image with a local key pair file cosign attest --predicate --type --key cosign.key @@ -55,6 +55,7 @@ cosign attest [flags] --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --sk whether to use a hardware security key --slot string security key slot to use for generated key (default: signature) (authentication|signature|card-authentication|key-management) + --timeout duration HTTP Timeout defaults to 30 seconds (default 30s) --type string specify a predicate type (slsaprovenance|link|spdx|custom) or an URI (default "custom") ``` diff --git a/doc/cosign_policy_sign.md b/doc/cosign_policy_sign.md index d5f73e84116..5d10a71033e 100644 --- a/doc/cosign_policy_sign.md +++ b/doc/cosign_policy_sign.md @@ -28,6 +28,7 @@ cosign policy sign [flags] --oidc-issuer string [EXPERIMENTAL] OIDC provider to be used to issue ID token (default "https://oauth2.sigstore.dev/auth") --out string output policy locally (default "o") --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") + --timeout duration HTTP Timeout defaults to 30 seconds (default 30s) ``` ### Options inherited from parent commands diff --git a/doc/cosign_sign-blob.md b/doc/cosign_sign-blob.md index 4b84369a639..d6cf17c7f4e 100644 --- a/doc/cosign_sign-blob.md +++ b/doc/cosign_sign-blob.md @@ -12,7 +12,7 @@ cosign sign-blob [flags] cosign sign-blob --key | # sign a blob with Google sign-in (experimental) - COSIGN_EXPERIMENTAL=1 cosign sign-blob + COSIGN_EXPERIMENTAL=1 cosign --timeout 90s sign-blob # sign a blob with a local key pair file cosign sign-blob --key cosign.key @@ -49,6 +49,7 @@ cosign sign-blob [flags] --rekor-url string [EXPERIMENTAL] address of rekor STL server (default "https://rekor.sigstore.dev") --sk whether to use a hardware security key --slot string security key slot to use for generated key (default: signature) (authentication|signature|card-authentication|key-management) + --timeout duration HTTP Timeout defaults to 30 seconds (default 30s) ``` ### Options inherited from parent commands diff --git a/pkg/cosign/tlog.go b/pkg/cosign/tlog.go index 133cd8edb84..b3f60db980c 100644 --- a/pkg/cosign/tlog.go +++ b/pkg/cosign/tlog.go @@ -22,6 +22,7 @@ import ( "encoding/hex" "fmt" "strings" + "time" "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" @@ -55,27 +56,32 @@ func GetRekorPub() string { } // TLogUpload will upload the signature, public key and payload to the transparency log. -func TLogUpload(rekorClient *client.Rekor, signature, payload []byte, pemBytes []byte) (*models.LogEntryAnon, error) { +func TLogUpload(rekorClient *client.Rekor, signature, payload []byte, pemBytes []byte, timeout time.Duration) (*models.LogEntryAnon, error) { re := rekorEntry(payload, signature, pemBytes) returnVal := models.Rekord{ APIVersion: swag.String(re.APIVersion()), Spec: re.RekordObj, } - return doUpload(rekorClient, &returnVal) + return doUpload(rekorClient, &returnVal, timeout) } // TLogUploadInTotoAttestation will upload and in-toto entry for the signature and public key to the transparency log. -func TLogUploadInTotoAttestation(rekorClient *client.Rekor, signature, pemBytes []byte) (*models.LogEntryAnon, error) { +func TLogUploadInTotoAttestation(rekorClient *client.Rekor, signature, pemBytes []byte, timeout time.Duration) (*models.LogEntryAnon, error) { e := intotoEntry(signature, pemBytes) returnVal := models.Intoto{ APIVersion: swag.String(e.APIVersion()), Spec: e.IntotoObj, } - return doUpload(rekorClient, &returnVal) + return doUpload(rekorClient, &returnVal, timeout) } -func doUpload(rekorClient *client.Rekor, pe models.ProposedEntry) (*models.LogEntryAnon, error) { - params := entries.NewCreateLogEntryParams() +func doUpload(rekorClient *client.Rekor, pe models.ProposedEntry, timeout time.Duration) (*models.LogEntryAnon, error) { + var params *entries.CreateLogEntryParams + if timeout != time.Duration(0) { + params = entries.NewCreateLogEntryParamsWithTimeout(timeout) + } else { + params = entries.NewCreateLogEntryParams() + } params.SetProposedEntry(pe) resp, err := rekorClient.Entries.CreateLogEntry(params) if err != nil { diff --git a/test/e2e_test.go b/test/e2e_test.go index 777e183bef5..38ec1917dc2 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -31,6 +31,7 @@ import ( "path" "path/filepath" "testing" + "time" "github.com/google/go-cmp/cmp" "github.com/google/go-containerregistry/pkg/authn" @@ -183,7 +184,7 @@ func TestAttestVerify(t *testing.T) { // Now attest the image ko := sign.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} must(attest.AttestCmd(ctx, ko, options.RegistryOptions{}, imgName, "", false, slsaAttestationPath, false, - "custom"), t) + "custom", time.Duration(30*time.Second)), t) // Use cue to verify attestation policyPath := filepath.Join(td, "policy.cue") @@ -375,8 +376,7 @@ func TestMultipleSignatures(t *testing.T) { } func TestSignBlob(t *testing.T) { - - var blob = "someblob" + blob := "someblob" td1 := t.TempDir() td2 := t.TempDir() t.Cleanup(func() { @@ -409,7 +409,7 @@ func TestSignBlob(t *testing.T) { KeyRef: privKeyPath1, PassFunc: passFunc, } - sig, err := sign.SignBlobCmd(ctx, ko, options.RegistryOptions{}, bp, true, "") + sig, err := sign.SignBlobCmd(ctx, ko, options.RegistryOptions{}, bp, true, "", time.Duration(30*time.Second)) if err != nil { t.Fatal(err) } @@ -557,7 +557,6 @@ func TestUploadDownload(t *testing.T) { cleanup() }) } - } func TestUploadBlob(t *testing.T) {