From 08f5443157dacb6e3fb44daf8a894ab716e93733 Mon Sep 17 00:00:00 2001 From: naveen <172697+naveensrinivasan@users.noreply.github.com> Date: Fri, 5 Nov 2021 00:04:18 +0000 Subject: [PATCH] Included timeout option for uploading to Rekor 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.md | 2 -- 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 ++++----- 15 files changed, 55 insertions(+), 25 deletions(-) diff --git a/cmd/cosign/cli/attest.go b/cmd/cosign/cli/attest.go index 72da49057037..dee92075b779 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 edc8a63e96fc..86efcefe1f39 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 f9a1fad6fd3f..251a73afaca1 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 d7e54a746c92..7f2f0b35c009 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 600993d4a797..8086da15e370 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 8f3777988226..8848a35a972c 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 7adb5f1d81e8..cd04d3b58d39 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 2c441bba6ef3..aa3a1f41a771 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 628aa115a235..c46239d22855 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.md b/doc/cosign.md index 1d270624151f..c27dbbd34f4b 100644 --- a/doc/cosign.md +++ b/doc/cosign.md @@ -25,8 +25,6 @@ cosign clean * [cosign generate-key-pair](cosign_generate-key-pair.md) - Generates a key-pair. * [cosign initialize](cosign_initialize.md) - Initializes SigStore root to retrieve trusted certificate and key targets for verification. * [cosign manifest](cosign_manifest.md) - Provides utilities for discovering images in and performing operations on Kubernetes manifests -* [cosign piv-tool](cosign_piv-tool.md) - Provides utilities for managing a hardware token -* [cosign pkcs11-tool](cosign_pkcs11-tool.md) - Provides utilities for retrieving information from a PKCS11 token. * [cosign policy](cosign_policy.md) - subcommand to manage a keyless policy. * [cosign public-key](cosign_public-key.md) - Gets a public key from the key-pair. * [cosign sign](cosign_sign.md) - Sign the supplied container image. diff --git a/doc/cosign_attest.md b/doc/cosign_attest.md index 469184e7b1c5..a879c83ca0d5 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 d5f73e841166..5d10a71033ec 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 4b84369a6391..d6cf17c7f4e4 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 133cd8edb849..b3f60db980c5 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 777e183bef52..38ec1917dc28 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) {