diff --git a/cmd/cosign/cli/attest.go b/cmd/cosign/cli/attest.go index ffb20be7059..40a5fef674e 100644 --- a/cmd/cosign/cli/attest.go +++ b/cmd/cosign/cli/attest.go @@ -22,10 +22,7 @@ import ( "github.com/sigstore/cosign/v3/cmd/cosign/cli/attest" "github.com/sigstore/cosign/v3/cmd/cosign/cli/generate" "github.com/sigstore/cosign/v3/cmd/cosign/cli/options" - "github.com/sigstore/cosign/v3/internal/ui" - "github.com/sigstore/cosign/v3/pkg/cosign" - "github.com/sigstore/cosign/v3/pkg/cosign/env" - "github.com/sigstore/sigstore-go/pkg/root" + "github.com/sigstore/cosign/v3/cmd/cosign/cli/signcommon" "github.com/spf13/cobra" ) @@ -103,45 +100,10 @@ func Attest() *cobra.Command { BundlePath: o.BundlePath, NewBundleFormat: o.NewBundleFormat, } - // If a signing config is used, then service URLs cannot be specified - if (o.UseSigningConfig || o.SigningConfigPath != "") && - ((o.Rekor.URL != "" && o.Rekor.URL != options.DefaultRekorURL) || - (o.Fulcio.URL != "" && o.Fulcio.URL != options.DefaultFulcioURL) || - (o.OIDC.Issuer != "" && o.OIDC.Issuer != options.DefaultOIDCIssuerURL) || - o.TSAServerURL != "") { - return fmt.Errorf("cannot specify service URLs and use signing config") - } - // Signing config requires a bundle as output for verification materials since sigstore-go is used - if (o.UseSigningConfig || o.SigningConfigPath != "") && !o.NewBundleFormat { - return fmt.Errorf("must provide --new-bundle-format with --signing-config or --use-signing-config") - } - // Fetch a trusted root when: - // * requesting a certificate and no CT log key is provided to verify an SCT - // * using a signing config and signing using sigstore-go - if (o.Key == "" && env.Getenv(env.VariableSigstoreCTLogPublicKeyFile) == "") || - (o.UseSigningConfig || o.SigningConfigPath != "") { - if o.TrustedRootPath != "" { - ko.TrustedMaterial, err = root.NewTrustedRootFromPath(o.TrustedRootPath) - if err != nil { - return fmt.Errorf("loading trusted root: %w", err) - } - } else { - ko.TrustedMaterial, err = cosign.TrustedRoot() - if err != nil { - ui.Warnf(context.Background(), "Could not fetch trusted_root.json from the TUF repository. Continuing with individual targets. Error from TUF: %v", err) - } - } - } - if o.SigningConfigPath != "" { - ko.SigningConfig, err = root.NewSigningConfigFromPath(o.SigningConfigPath) - if err != nil { - return fmt.Errorf("error reading signing config from file: %w", err) - } - } else if o.UseSigningConfig { - ko.SigningConfig, err = cosign.SigningConfig() - if err != nil { - return fmt.Errorf("error getting signing config from TUF: %w", err) - } + if err := signcommon.LoadTrustedMaterialAndSigningConfig(context.Background(), &ko, o.UseSigningConfig, o.SigningConfigPath, + o.Rekor.URL, o.Fulcio.URL, o.OIDC.Issuer, o.TSAServerURL, o.TrustedRootPath, + o.NewBundleFormat, "", o.Key, o.IssueCertificate); err != nil { + return err } attestCommand := attest.AttestCommand{ diff --git a/cmd/cosign/cli/attest/attest.go b/cmd/cosign/cli/attest/attest.go index 861a2b7716c..3856621bca4 100644 --- a/cmd/cosign/cli/attest/attest.go +++ b/cmd/cosign/cli/attest/attest.go @@ -128,6 +128,7 @@ func (c *AttestCommand) Exec(ctx context.Context, imageRef string) error { BundlePath: c.BundlePath, Upload: !c.NoUpload, OCIRemoteOpts: ociremoteOpts, + TlogUpload: c.TlogUpload, } if c.SigningConfig != nil { diff --git a/cmd/cosign/cli/attest/attest_blob.go b/cmd/cosign/cli/attest/attest_blob.go index 9e611f663aa..545a7aea427 100644 --- a/cmd/cosign/cli/attest/attest_blob.go +++ b/cmd/cosign/cli/attest/attest_blob.go @@ -144,6 +144,7 @@ func (c *AttestBlobCommand) Exec(ctx context.Context, artifactPath string) error bundleOpts := signcommon.CommonBundleOpts{ Payload: payload, BundlePath: c.BundlePath, + TlogUpload: c.TlogUpload, } if c.SigningConfig != nil { diff --git a/cmd/cosign/cli/attest_blob.go b/cmd/cosign/cli/attest_blob.go index 454a02b9523..ba8d7e799a5 100644 --- a/cmd/cosign/cli/attest_blob.go +++ b/cmd/cosign/cli/attest_blob.go @@ -16,15 +16,11 @@ package cli import ( "context" - "fmt" "github.com/sigstore/cosign/v3/cmd/cosign/cli/attest" "github.com/sigstore/cosign/v3/cmd/cosign/cli/generate" "github.com/sigstore/cosign/v3/cmd/cosign/cli/options" - "github.com/sigstore/cosign/v3/internal/ui" - "github.com/sigstore/cosign/v3/pkg/cosign" - "github.com/sigstore/cosign/v3/pkg/cosign/env" - "github.com/sigstore/sigstore-go/pkg/root" + "github.com/sigstore/cosign/v3/cmd/cosign/cli/signcommon" "github.com/spf13/cobra" ) @@ -90,45 +86,10 @@ func AttestBlob() *cobra.Command { BundlePath: o.BundlePath, NewBundleFormat: o.NewBundleFormat, } - // If a signing config is used, then service URLs cannot be specified - if (o.UseSigningConfig || o.SigningConfigPath != "") && - ((o.Rekor.URL != "" && o.Rekor.URL != options.DefaultRekorURL) || - (o.Fulcio.URL != "" && o.Fulcio.URL != options.DefaultFulcioURL) || - (o.OIDC.Issuer != "" && o.OIDC.Issuer != options.DefaultOIDCIssuerURL) || - o.TSAServerURL != "") { - return fmt.Errorf("cannot specify service URLs and use signing config") - } - // Signing config requires a bundle as output for verification materials since sigstore-go is used - if (o.UseSigningConfig || o.SigningConfigPath != "") && o.BundlePath == "" { - return fmt.Errorf("must provide --bundle with --signing-config or --use-signing-config") - } - // Fetch a trusted root when: - // * requesting a certificate and no CT log key is provided to verify an SCT - // * using a signing config and signing using sigstore-go - if (o.Key == "" && env.Getenv(env.VariableSigstoreCTLogPublicKeyFile) == "") || - (o.UseSigningConfig || o.SigningConfigPath != "") { - if o.TrustedRootPath != "" { - ko.TrustedMaterial, err = root.NewTrustedRootFromPath(o.TrustedRootPath) - if err != nil { - return fmt.Errorf("loading trusted root: %w", err) - } - } else { - ko.TrustedMaterial, err = cosign.TrustedRoot() - if err != nil { - ui.Warnf(context.Background(), "Could not fetch trusted_root.json from the TUF repository. Continuing with individual targets. Error from TUF: %v", err) - } - } - } - if o.SigningConfigPath != "" { - ko.SigningConfig, err = root.NewSigningConfigFromPath(o.SigningConfigPath) - if err != nil { - return fmt.Errorf("error reading signing config from file: %w", err) - } - } else if o.UseSigningConfig { - ko.SigningConfig, err = cosign.SigningConfig() - if err != nil { - return fmt.Errorf("error getting signing config from TUF: %w", err) - } + if err := signcommon.LoadTrustedMaterialAndSigningConfig(context.Background(), &ko, o.UseSigningConfig, o.SigningConfigPath, + o.Rekor.URL, o.Fulcio.URL, o.OIDC.Issuer, o.TSAServerURL, o.TrustedRootPath, + o.NewBundleFormat, o.BundlePath, o.Key, o.IssueCertificate); err != nil { + return err } v := attest.AttestBlobCommand{ diff --git a/cmd/cosign/cli/options/attest.go b/cmd/cosign/cli/options/attest.go index d1791889730..bf55898251e 100644 --- a/cmd/cosign/cli/options/attest.go +++ b/cmd/cosign/cli/options/attest.go @@ -88,6 +88,7 @@ func (o *AttestOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&o.TlogUpload, "tlog-upload", true, "whether or not to upload to the tlog") + _ = cmd.Flags().MarkDeprecated("tlog-upload", "prefer using a --signing-config file with no transparency log services") cmd.Flags().StringVar(&o.RekorEntryType, "rekor-entry-type", rekorEntryTypes[0], "specifies the type to be used for a rekor entry upload ("+strings.Join(rekorEntryTypes, "|")+")") diff --git a/cmd/cosign/cli/options/attest_blob.go b/cmd/cosign/cli/options/attest_blob.go index 4d906605c2e..3ddef763460 100644 --- a/cmd/cosign/cli/options/attest_blob.go +++ b/cmd/cosign/cli/options/attest_blob.go @@ -121,6 +121,7 @@ func (o *AttestBlobOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&o.TlogUpload, "tlog-upload", true, "whether or not to upload to the tlog") + _ = cmd.Flags().MarkDeprecated("tlog-upload", "prefer using a --signing-config file with no transparency log services") cmd.Flags().StringVar(&o.RekorEntryType, "rekor-entry-type", rekorEntryTypes[0], "specifies the type to be used for a rekor entry upload ("+strings.Join(rekorEntryTypes, "|")+")") diff --git a/cmd/cosign/cli/options/sign.go b/cmd/cosign/cli/options/sign.go index 23eb93cab49..c0d6bdef3a2 100644 --- a/cmd/cosign/cli/options/sign.go +++ b/cmd/cosign/cli/options/sign.go @@ -118,6 +118,7 @@ func (o *SignOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&o.TlogUpload, "tlog-upload", true, "whether or not to upload to the tlog") + _ = cmd.Flags().MarkDeprecated("tlog-upload", "prefer using a --signing-config file with no transparency log services") cmd.Flags().StringVar(&o.TSAClientCACert, "timestamp-client-cacert", "", "path to the X.509 CA certificate file in PEM format to be used for the connection to the TSA Server") diff --git a/cmd/cosign/cli/options/signblob.go b/cmd/cosign/cli/options/signblob.go index 4d4b505cfb2..3ece0b84832 100644 --- a/cmd/cosign/cli/options/signblob.go +++ b/cmd/cosign/cli/options/signblob.go @@ -100,6 +100,7 @@ func (o *SignBlobOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().BoolVar(&o.TlogUpload, "tlog-upload", true, "whether or not to upload to the tlog") + _ = cmd.Flags().MarkDeprecated("tlog-upload", "prefer using a --signing-config file with no transparency log services") cmd.Flags().StringVar(&o.TSAClientCACert, "timestamp-client-cacert", "", "path to the X.509 CA certificate file in PEM format to be used for the connection to the TSA Server") diff --git a/cmd/cosign/cli/sign.go b/cmd/cosign/cli/sign.go index b10034cbb09..5c6efa6fa07 100644 --- a/cmd/cosign/cli/sign.go +++ b/cmd/cosign/cli/sign.go @@ -23,10 +23,7 @@ import ( "github.com/sigstore/cosign/v3/cmd/cosign/cli/generate" "github.com/sigstore/cosign/v3/cmd/cosign/cli/options" "github.com/sigstore/cosign/v3/cmd/cosign/cli/sign" - "github.com/sigstore/cosign/v3/internal/ui" - "github.com/sigstore/cosign/v3/pkg/cosign" - "github.com/sigstore/cosign/v3/pkg/cosign/env" - "github.com/sigstore/sigstore-go/pkg/root" + "github.com/sigstore/cosign/v3/cmd/cosign/cli/signcommon" "github.com/spf13/cobra" ) @@ -132,45 +129,10 @@ race conditions or (worse) malicious tampering. TSAServerURL: o.TSAServerURL, IssueCertificateForExistingKey: o.IssueCertificate, } - // If a signing config is used, then service URLs cannot be specified - if (o.UseSigningConfig || o.SigningConfigPath != "") && - ((o.Rekor.URL != "" && o.Rekor.URL != options.DefaultRekorURL) || - (o.Fulcio.URL != "" && o.Fulcio.URL != options.DefaultFulcioURL) || - (o.OIDC.Issuer != "" && o.OIDC.Issuer != options.DefaultOIDCIssuerURL) || - o.TSAServerURL != "") { - return fmt.Errorf("cannot specify service URLs and use signing config") - } - // Signing config requires a bundle as output for verification materials since sigstore-go is used - if (o.UseSigningConfig || o.SigningConfigPath != "") && !o.NewBundleFormat { - return fmt.Errorf("must provide --new-bundle-format with --signing-config or --use-signing-config") - } - // Fetch a trusted root when: - // * requesting a certificate and no CT log key is provided to verify an SCT - // * using a signing config and signing using sigstore-go - if ((o.Key == "" || o.IssueCertificate) && env.Getenv(env.VariableSigstoreCTLogPublicKeyFile) == "") || - (o.UseSigningConfig || o.SigningConfigPath != "") { - if o.TrustedRootPath != "" { - ko.TrustedMaterial, err = root.NewTrustedRootFromPath(o.TrustedRootPath) - if err != nil { - return fmt.Errorf("loading trusted root: %w", err) - } - } else { - ko.TrustedMaterial, err = cosign.TrustedRoot() - if err != nil { - ui.Warnf(context.Background(), "Could not fetch trusted_root.json from the TUF repository. Continuing with individual targets. Error from TUF: %v", err) - } - } - } - if o.SigningConfigPath != "" { - ko.SigningConfig, err = root.NewSigningConfigFromPath(o.SigningConfigPath) - if err != nil { - return fmt.Errorf("error reading signing config from file: %w", err) - } - } else if o.UseSigningConfig { - ko.SigningConfig, err = cosign.SigningConfig() - if err != nil { - return fmt.Errorf("error getting signing config from TUF: %w", err) - } + if err := signcommon.LoadTrustedMaterialAndSigningConfig(context.Background(), &ko, o.UseSigningConfig, o.SigningConfigPath, + o.Rekor.URL, o.Fulcio.URL, o.OIDC.Issuer, o.TSAServerURL, o.TrustedRootPath, + o.NewBundleFormat, "", o.Key, o.IssueCertificate); err != nil { + return err } if err := sign.SignCmd(ro, ko, *o, args); err != nil { diff --git a/cmd/cosign/cli/sign/sign.go b/cmd/cosign/cli/sign/sign.go index 5ad44b746f5..ad4afcc7c2c 100644 --- a/cmd/cosign/cli/sign/sign.go +++ b/cmd/cosign/cli/sign/sign.go @@ -190,6 +190,7 @@ func signDigestBundle(ctx context.Context, digest name.Digest, ko options.KeyOpt BundlePath: signOpts.BundlePath, Upload: signOpts.Upload, OCIRemoteOpts: ociremoteOpts, + TlogUpload: signOpts.TlogUpload, } if ko.SigningConfig != nil { diff --git a/cmd/cosign/cli/sign/sign_blob.go b/cmd/cosign/cli/sign/sign_blob.go index a3e462a1bae..28c9122726b 100644 --- a/cmd/cosign/cli/sign/sign_blob.go +++ b/cmd/cosign/cli/sign/sign_blob.go @@ -95,6 +95,12 @@ func SignBlobCmd(ro *options.RootOptions, ko options.KeyOpts, payloadPath string Data: data, } + // This will be removed in a later release in favor of users providing a signing configuration + // without transparency log services + if !shouldUpload { + _ = ko.SigningConfig.WithRekorLogURLs() + } + bundle, err := cbundle.SignData(ctx, content, keypair, idToken, ko.SigningConfig, ko.TrustedMaterial) if err != nil { return nil, fmt.Errorf("signing bundle: %w", err) diff --git a/cmd/cosign/cli/signblob.go b/cmd/cosign/cli/signblob.go index 5ad293030c1..1483d3f6e12 100644 --- a/cmd/cosign/cli/signblob.go +++ b/cmd/cosign/cli/signblob.go @@ -23,10 +23,7 @@ import ( "github.com/sigstore/cosign/v3/cmd/cosign/cli/generate" "github.com/sigstore/cosign/v3/cmd/cosign/cli/options" "github.com/sigstore/cosign/v3/cmd/cosign/cli/sign" - "github.com/sigstore/cosign/v3/internal/ui" - "github.com/sigstore/cosign/v3/pkg/cosign" - "github.com/sigstore/cosign/v3/pkg/cosign/env" - "github.com/sigstore/sigstore-go/pkg/root" + "github.com/sigstore/cosign/v3/cmd/cosign/cli/signcommon" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -100,45 +97,10 @@ func SignBlob() *cobra.Command { RFC3161TimestampPath: o.RFC3161TimestampPath, IssueCertificateForExistingKey: o.IssueCertificate, } - // If a signing config is used, then service URLs cannot be specified - if (o.UseSigningConfig || o.SigningConfigPath != "") && - ((o.Rekor.URL != "" && o.Rekor.URL != options.DefaultRekorURL) || - (o.Fulcio.URL != "" && o.Fulcio.URL != options.DefaultFulcioURL) || - (o.OIDC.Issuer != "" && o.OIDC.Issuer != options.DefaultOIDCIssuerURL) || - o.TSAServerURL != "") { - return fmt.Errorf("cannot specify service URLs and use signing config") - } - // Signing config requires a bundle as output for verification materials since sigstore-go is used - if (o.UseSigningConfig || o.SigningConfigPath != "") && o.BundlePath == "" { - return fmt.Errorf("must provide --bundle with --signing-config or --use-signing-config") - } - // Fetch a trusted root when: - // * requesting a certificate and no CT log key is provided to verify an SCT - // * using a signing config and signing using sigstore-go - if ((o.Key == "" || o.IssueCertificate) && env.Getenv(env.VariableSigstoreCTLogPublicKeyFile) == "") || - (o.UseSigningConfig || o.SigningConfigPath != "") { - if o.TrustedRootPath != "" { - ko.TrustedMaterial, err = root.NewTrustedRootFromPath(o.TrustedRootPath) - if err != nil { - return fmt.Errorf("loading trusted root: %w", err) - } - } else { - ko.TrustedMaterial, err = cosign.TrustedRoot() - if err != nil { - ui.Warnf(context.Background(), "Could not fetch trusted_root.json from the TUF repository. Continuing with individual targets. Error from TUF: %v", err) - } - } - } - if o.SigningConfigPath != "" { - ko.SigningConfig, err = root.NewSigningConfigFromPath(o.SigningConfigPath) - if err != nil { - return fmt.Errorf("error reading signing config from file: %w", err) - } - } else if o.UseSigningConfig { - ko.SigningConfig, err = cosign.SigningConfig() - if err != nil { - return fmt.Errorf("error getting signing config from TUF: %w", err) - } + if err := signcommon.LoadTrustedMaterialAndSigningConfig(context.Background(), &ko, o.UseSigningConfig, o.SigningConfigPath, + o.Rekor.URL, o.Fulcio.URL, o.OIDC.Issuer, o.TSAServerURL, o.TrustedRootPath, + o.NewBundleFormat, o.BundlePath, o.Key, o.IssueCertificate); err != nil { + return err } for _, blob := range args { diff --git a/cmd/cosign/cli/signcommon/common.go b/cmd/cosign/cli/signcommon/common.go index 9e70b17695a..3bf394a5b5c 100644 --- a/cmd/cosign/cli/signcommon/common.go +++ b/cmd/cosign/cli/signcommon/common.go @@ -39,6 +39,7 @@ import ( "github.com/sigstore/cosign/v3/internal/ui" "github.com/sigstore/cosign/v3/pkg/cosign" cbundle "github.com/sigstore/cosign/v3/pkg/cosign/bundle" + "github.com/sigstore/cosign/v3/pkg/cosign/env" "github.com/sigstore/cosign/v3/pkg/cosign/pivkey" "github.com/sigstore/cosign/v3/pkg/cosign/pkcs11key" ociremote "github.com/sigstore/cosign/v3/pkg/oci/remote" @@ -473,6 +474,7 @@ type CommonBundleOpts struct { BundlePath string Upload bool OCIRemoteOpts []ociremote.Option + TlogUpload bool } // WriteBundle compiles a protobuf bundle from components and writes the bundle to the OCI remote layer. @@ -508,6 +510,13 @@ func WriteNewBundleWithSigningConfig(ctx context.Context, ko options.KeyOpts, ce Data: bundleOpts.Payload, PayloadType: "application/vnd.in-toto+json", } + + // This will be removed in a later release in favor of users providing a signing configuration + // without transparency log services + if !bundleOpts.TlogUpload { + _ = ko.SigningConfig.WithRekorLogURLs() + } + bundle, err := cbundle.SignData(ctx, content, keypair, idToken, signingConfig, trustedMaterial) if err != nil { return fmt.Errorf("signing bundle: %w", err) @@ -602,3 +611,51 @@ func ParseOCIReference(ctx context.Context, refStr string, opts ...name.Option) } return ref, nil } + +// LoadTrustedMaterialAndSigningConfig loads the trusted material and signing config from the given options. +func LoadTrustedMaterialAndSigningConfig(ctx context.Context, ko *options.KeyOpts, useSigningConfig bool, signingConfigPath string, + rekorURL, fulcioURL, oidcIssuer, tsaServerURL, trustedRootPath string, + newBundleFormat bool, bundlePath string, keyRef string, issueCertificate bool) error { + var err error + // If a signing config is used, then service URLs cannot be specified + if (useSigningConfig || signingConfigPath != "") && + ((rekorURL != "" && rekorURL != options.DefaultRekorURL) || + (fulcioURL != "" && fulcioURL != options.DefaultFulcioURL) || + (oidcIssuer != "" && oidcIssuer != options.DefaultOIDCIssuerURL) || + tsaServerURL != "") { + return fmt.Errorf("cannot specify service URLs and use signing config") + } + // Signing config requires a bundle as output for verification materials since sigstore-go is used + if (useSigningConfig || signingConfigPath != "") && !newBundleFormat && bundlePath == "" { + return fmt.Errorf("must provide --new-bundle-format or --bundle where applicable with --signing-config or --use-signing-config") + } + // Fetch a trusted root when: + // * requesting a certificate and no CT log key is provided to verify an SCT + // * using a signing config and signing using sigstore-go + if ((keyRef == "" || issueCertificate) && env.Getenv(env.VariableSigstoreCTLogPublicKeyFile) == "") || + (useSigningConfig || signingConfigPath != "") { + if trustedRootPath != "" { + ko.TrustedMaterial, err = root.NewTrustedRootFromPath(trustedRootPath) + if err != nil { + return fmt.Errorf("loading trusted root: %w", err) + } + } else { + ko.TrustedMaterial, err = cosign.TrustedRoot() + if err != nil { + ui.Warnf(ctx, "Could not fetch trusted_root.json from the TUF repository. Continuing with individual targets. Error from TUF: %v", err) + } + } + } + if signingConfigPath != "" { + ko.SigningConfig, err = root.NewSigningConfigFromPath(signingConfigPath) + if err != nil { + return fmt.Errorf("error reading signing config from file: %w", err) + } + } else if useSigningConfig { + ko.SigningConfig, err = cosign.SigningConfig() + if err != nil { + return fmt.Errorf("error getting signing config from TUF: %w", err) + } + } + return nil +} diff --git a/doc/cosign_attest-blob.md b/doc/cosign_attest-blob.md index 126f3f1444d..30cb9c10f73 100644 --- a/doc/cosign_attest-blob.md +++ b/doc/cosign_attest-blob.md @@ -67,7 +67,6 @@ cosign attest-blob [flags] --timestamp-client-key string path to the X.509 private key file in PEM format to be used, together with the 'timestamp-client-cert' value, for the connection to the TSA Server --timestamp-server-name string SAN name to use as the 'ServerName' tls.Config field to verify the mTLS connection to the TSA Server --timestamp-server-url string url to the Timestamp RFC3161 server, default none. Must be the path to the API to request timestamp responses, e.g. https://freetsa.org/tsr - --tlog-upload whether or not to upload to the tlog (default true) --trusted-root string optional path to a TrustedRoot JSON file to verify a signature after signing --type string specify a predicate type (slsaprovenance|slsaprovenance02|slsaprovenance1|link|spdx|spdxjson|cyclonedx|vuln|openvex|custom) or an URI (default "custom") --use-signing-config whether to use a TUF-provided signing config for the service URLs. Must provide --bundle, which will output verification material in the new format (default true) diff --git a/doc/cosign_attest.md b/doc/cosign_attest.md index 57601462a3a..7beb3dbdf0b 100644 --- a/doc/cosign_attest.md +++ b/doc/cosign_attest.md @@ -91,7 +91,6 @@ cosign attest [flags] --timestamp-client-key string path to the X.509 private key file in PEM format to be used, together with the 'timestamp-client-cert' value, for the connection to the TSA Server --timestamp-server-name string SAN name to use as the 'ServerName' tls.Config field to verify the mTLS connection to the TSA Server --timestamp-server-url string url to the Timestamp RFC3161 server, default none. Must be the path to the API to request timestamp responses, e.g. https://freetsa.org/tsr - --tlog-upload whether or not to upload to the tlog (default true) --trusted-root string optional path to a TrustedRoot JSON file to verify a signature after signing --type string specify a predicate type (slsaprovenance|slsaprovenance02|slsaprovenance1|link|spdx|spdxjson|cyclonedx|vuln|openvex|custom) or an URI (default "custom") --use-signing-config whether to use a TUF-provided signing config for the service URLs. Must set --new-bundle-format, which will store verification material in the new format (default true) diff --git a/doc/cosign_sign-blob.md b/doc/cosign_sign-blob.md index 4135f3aac22..361059db275 100644 --- a/doc/cosign_sign-blob.md +++ b/doc/cosign_sign-blob.md @@ -65,7 +65,6 @@ cosign sign-blob [flags] --timestamp-client-key string path to the X.509 private key file in PEM format to be used, together with the 'timestamp-client-cert' value, for the connection to the TSA Server --timestamp-server-name string SAN name to use as the 'ServerName' tls.Config field to verify the mTLS connection to the TSA Server --timestamp-server-url string url to the Timestamp RFC3161 server, default none. Must be the path to the API to request timestamp responses, e.g. https://freetsa.org/tsr - --tlog-upload whether or not to upload to the tlog (default true) --trusted-root string optional path to a TrustedRoot JSON file to verify a signature after signing --use-signing-config whether to use a TUF-provided signing config for the service URLs. Must provide --bundle, which will output verification material in the new format (default true) -y, --yes skip confirmation prompts for non-destructive operations diff --git a/doc/cosign_sign.md b/doc/cosign_sign.md index 8973b53aee8..bb5049c760e 100644 --- a/doc/cosign_sign.md +++ b/doc/cosign_sign.md @@ -119,7 +119,6 @@ cosign sign [flags] --timestamp-client-key string path to the X.509 private key file in PEM format to be used, together with the 'timestamp-client-cert' value, for the connection to the TSA Server --timestamp-server-name string SAN name to use as the 'ServerName' tls.Config field to verify the mTLS connection to the TSA Server --timestamp-server-url string url to the Timestamp RFC3161 server, default none. Must be the path to the API to request timestamp responses, e.g. https://freetsa.org/tsr - --tlog-upload whether or not to upload to the tlog (default true) --trusted-root string optional path to a TrustedRoot JSON file to verify a signature after signing --upload whether to upload the signature (default true) --use-signing-config whether to use a TUF-provided signing config for the service URLs. Must set --new-bundle-format, which will store verification material in the new format (default true) diff --git a/test/e2e_test.go b/test/e2e_test.go index 95714bc34d7..bce20bdc1c0 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -78,6 +78,7 @@ import ( "github.com/sigstore/cosign/v3/pkg/oci/mutate" ociremote "github.com/sigstore/cosign/v3/pkg/oci/remote" v1 "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1" + sgbundle "github.com/sigstore/sigstore-go/pkg/bundle" "github.com/sigstore/sigstore-go/pkg/root" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/signature" @@ -851,7 +852,7 @@ func TestSignVerifyWithTUFMirror(t *testing.T) { } } -func prepareSigningConfig(t *testing.T, fulcioURL, rekorURL, oidcURL, tsaURL string) string { +func prepareSigningConfig(t *testing.T, fulcioURL, rekorURL, oidcURL, tsaURL string) string { //nolint: unparam startTime := "2024-01-01T00:00:00Z" fulcioSpec := fmt.Sprintf("url=%s,api-version=1,operator=fulcio-op,start-time=%s", fulcioURL, startTime) rekorSpec := fmt.Sprintf("url=%s,api-version=1,operator=rekor-op,start-time=%s", rekorURL, startTime) @@ -964,6 +965,7 @@ func TestSignAttestVerifyBlobWithSigningConfig(t *testing.T) { KeyOpts: ko, RekorEntryType: "dsse", StatementPath: statementPath, + TlogUpload: true, } must(attestBlobCmd.Exec(ctx, bp), t) @@ -1072,6 +1074,7 @@ func TestSignAttestVerifyContainerWithSigningConfig(t *testing.T) { PredicateType: "slsaprovenance", Timeout: 30 * time.Second, RekorEntryType: "dsse", + TlogUpload: true, } must(attestCmd.Exec(ctx, imgName), t) @@ -1176,6 +1179,7 @@ func TestSignVerifyWithSigningConfigWithKey(t *testing.T) { KeyOpts: ko, RekorEntryType: "dsse", StatementPath: statementPath, + TlogUpload: true, } must(attestBlobCmd.Exec(ctx, bp), t) @@ -1191,6 +1195,90 @@ func TestSignVerifyWithSigningConfigWithKey(t *testing.T) { must(err, t) } +func TestSignVerifyBlobWithSigningConfigWithoutTlogUpload(t *testing.T) { + tufLocalCache := t.TempDir() + t.Setenv("TUF_ROOT", tufLocalCache) + tufMirror := t.TempDir() + viper.Set("timestamp-signer", "memory") + viper.Set("timestamp-signer-hash", "sha256") + tsaAPIServer := server.NewRestAPIServer("localhost", 0, []string{"http"}, false, 10*time.Second, 10*time.Second) + tsaServer := httptest.NewServer(tsaAPIServer.GetHandler()) + t.Cleanup(tsaServer.Close) + tufServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.FileServer(http.Dir(tufMirror)).ServeHTTP(w, r) + })) + mirror := tufServer.URL + trustedRoot := prepareTrustedRoot(t, tsaServer.URL) + signingConfigStr := prepareSigningConfig(t, fulcioURL, rekorURL, "unused", tsaServer.URL+"/api/v1/timestamp") + + _, err := newTUF(tufMirror, []targetInfo{ + { + name: "trusted_root.json", + source: trustedRoot, + }, + { + name: "signing_config.v0.2.json", + source: signingConfigStr, + }, + }) + must(err, t) + + ctx := context.Background() + + rootPath := filepath.Join(tufMirror, "1.root.json") + must(initialize.DoInitialize(ctx, rootPath, mirror), t) + + identityToken, err := getOIDCToken() + if err != nil { + t.Fatal(err) + } + + ko := options.KeyOpts{ + IDToken: identityToken, + SkipConfirmation: true, + } + trustedMaterial, err := cosign.TrustedRoot() + must(err, t) + ko.TrustedMaterial = trustedMaterial + signingConfig, err := cosign.SigningConfig() + must(err, t) + ko.SigningConfig = signingConfig + + // Sign a blob + blob := "someblob" + blobDir := t.TempDir() + bp := filepath.Join(blobDir, blob) + if err := os.WriteFile(bp, []byte(blob), 0644); err != nil { + t.Fatal(err) + } + bundlePath := filepath.Join(blobDir, "bundle.json") + ko.NewBundleFormat = true + ko.BundlePath = bundlePath + + tlogUpload := false + _, err = sign.SignBlobCmd(ro, ko, bp, false, "", "", tlogUpload) + must(err, t) + + // Verify bundle does not contain a transparency log proof + b, err := sgbundle.LoadJSONFromPath(bundlePath) + must(err, t) + assert.Empty(t, b.GetVerificationMaterial().GetTlogEntries()) + + // Verify a blob without transparency log proof + issuer := os.Getenv("OIDC_URL") + verifyBlobCmd := cliverify.VerifyBlobCmd{ + KeyOpts: ko, + CertVerifyOptions: options.CertVerifyOptions{ + CertOidcIssuer: issuer, + CertIdentity: certID, + }, + UseSignedTimestamps: true, + IgnoreTlog: true, + } + err = verifyBlobCmd.Exec(ctx, bp) + must(err, t) +} + func TestSignVerifyBundle(t *testing.T) { td := t.TempDir() repo, stop := reg(t) diff --git a/test/e2e_test.ps1 b/test/e2e_test.ps1 index dd6736f6321..4228d769a29 100644 --- a/test/e2e_test.ps1 +++ b/test/e2e_test.ps1 @@ -35,7 +35,7 @@ $signing_key = "cosign.key" $verification_key = "cosign.pub" Write-Output "hello world" | Out-File -FilePath "hello_world.txt" -Write-Output $pass | .\cosign.exe sign-blob --key $signing_key --bundle test.sigstore.json --tlog-upload=false hello_world.txt +Write-Output $pass | .\cosign.exe sign-blob --key $signing_key --bundle test.sigstore.json --use-signing-config=false --tlog-upload=false hello_world.txt .\cosign.exe verify-blob --key $verification_key --bundle test.sigstore.json --insecure-ignore-tlog=true hello_world.txt Pop-Location