From accc80a840524890790c5c368fee26e22ec60bda Mon Sep 17 00:00:00 2001 From: Cody Soyland Date: Mon, 13 Jan 2025 14:41:02 -0600 Subject: [PATCH] Add UseSignedTimestamps to CheckOpts, refactor TSA options (#4006) Signed-off-by: Cody Soyland --- cmd/cosign/cli/verify.go | 2 ++ cmd/cosign/cli/verify/verify.go | 17 +++---------- cmd/cosign/cli/verify/verify_attestation.go | 17 +++---------- cmd/cosign/cli/verify/verify_blob.go | 25 +++++++------------ .../cli/verify/verify_blob_attestation.go | 13 +++++----- pkg/cosign/verify.go | 17 ++++++++----- 6 files changed, 37 insertions(+), 54 deletions(-) diff --git a/cmd/cosign/cli/verify.go b/cmd/cosign/cli/verify.go index 703898523b7..a2970d3227c 100644 --- a/cmd/cosign/cli/verify.go +++ b/cmd/cosign/cli/verify.go @@ -139,6 +139,7 @@ against the transparency log.`, IgnoreTlog: o.CommonVerifyOptions.IgnoreTlog, MaxWorkers: o.CommonVerifyOptions.MaxWorkers, ExperimentalOCI11: o.CommonVerifyOptions.ExperimentalOCI11, + UseSignedTimestamps: o.CommonVerifyOptions.UseSignedTimestamps, } if o.CommonVerifyOptions.MaxWorkers == 0 { @@ -245,6 +246,7 @@ against the transparency log.`, TSACertChainPath: o.CommonVerifyOptions.TSACertChainPath, IgnoreTlog: o.CommonVerifyOptions.IgnoreTlog, MaxWorkers: o.CommonVerifyOptions.MaxWorkers, + UseSignedTimestamps: o.CommonVerifyOptions.UseSignedTimestamps, } if o.CommonVerifyOptions.MaxWorkers == 0 { diff --git a/cmd/cosign/cli/verify/verify.go b/cmd/cosign/cli/verify/verify.go index 17fd63e8330..f5fc86bfddf 100644 --- a/cmd/cosign/cli/verify/verify.go +++ b/cmd/cosign/cli/verify/verify.go @@ -84,17 +84,6 @@ type VerifyCommand struct { ExperimentalOCI11 bool } -func (c *VerifyCommand) loadTSACertificates(ctx context.Context) (*cosign.TSACertificates, error) { - if c.TSACertChainPath == "" && !c.UseSignedTimestamps { - return nil, fmt.Errorf("TSA certificate chain path not provided and use-signed-timestamps not set") - } - tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets) - if err != nil { - return nil, fmt.Errorf("unable to load TSA certificates: %w", err) - } - return tsaCertificates, nil -} - // Exec runs the verification command func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) { if len(images) == 0 { @@ -144,13 +133,15 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) { IgnoreTlog: c.IgnoreTlog, MaxWorkers: c.MaxWorkers, ExperimentalOCI11: c.ExperimentalOCI11, + UseSignedTimestamps: c.TSACertChainPath != "" || c.UseSignedTimestamps, } if c.CheckClaims { co.ClaimVerifier = cosign.SimpleClaimVerifier } - if c.TSACertChainPath != "" || c.UseSignedTimestamps { - tsaCertificates, err := c.loadTSACertificates(ctx) + // If we are using signed timestamps, we need to load the TSA certificates + if co.UseSignedTimestamps { + tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets) if err != nil { return fmt.Errorf("unable to load TSA certificates: %w", err) } diff --git a/cmd/cosign/cli/verify/verify_attestation.go b/cmd/cosign/cli/verify/verify_attestation.go index 93c27690455..bf25cbb467a 100644 --- a/cmd/cosign/cli/verify/verify_attestation.go +++ b/cmd/cosign/cli/verify/verify_attestation.go @@ -72,17 +72,6 @@ type VerifyAttestationCommand struct { UseSignedTimestamps bool } -func (c *VerifyAttestationCommand) loadTSACertificates(ctx context.Context) (*cosign.TSACertificates, error) { - if c.TSACertChainPath == "" && !c.UseSignedTimestamps { - return nil, fmt.Errorf("TSA certificate chain path not provided and use-signed-timestamps not set") - } - tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets) - if err != nil { - return nil, fmt.Errorf("unable to load TSA certificates: %w", err) - } - return tsaCertificates, nil -} - // Exec runs the verification command func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (err error) { if len(images) == 0 { @@ -119,6 +108,7 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (e Offline: c.Offline, IgnoreTlog: c.IgnoreTlog, MaxWorkers: c.MaxWorkers, + UseSignedTimestamps: c.TSACertChainPath != "" || c.UseSignedTimestamps, } if c.CheckClaims { co.ClaimVerifier = cosign.IntotoSubjectClaimVerifier @@ -131,8 +121,9 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (e } } - if c.TSACertChainPath != "" || c.UseSignedTimestamps { - tsaCertificates, err := c.loadTSACertificates(ctx) + // If we are using signed timestamps, we need to load the TSA certificates + if co.UseSignedTimestamps { + tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets) if err != nil { return fmt.Errorf("unable to load TSA certificates: %w", err) } diff --git a/cmd/cosign/cli/verify/verify_blob.go b/cmd/cosign/cli/verify/verify_blob.go index 37e2d0282bf..bf97f9e2a86 100644 --- a/cmd/cosign/cli/verify/verify_blob.go +++ b/cmd/cosign/cli/verify/verify_blob.go @@ -69,17 +69,6 @@ type VerifyBlobCmd struct { IgnoreTlog bool } -func (c *VerifyBlobCmd) loadTSACertificates(ctx context.Context) (*cosign.TSACertificates, error) { - if c.TSACertChainPath == "" && !c.UseSignedTimestamps { - return nil, fmt.Errorf("either TSA certificate chain path must be provided or use-signed-timestamps must be set") - } - tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets) - if err != nil { - return nil, fmt.Errorf("unable to load TSA certificates: %w", err) - } - return tsaCertificates, nil -} - // nolint func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error { // Require a certificate/key OR a local bundle file that has the cert. @@ -137,14 +126,18 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error { Identities: identities, Offline: c.Offline, IgnoreTlog: c.IgnoreTlog, + UseSignedTimestamps: c.TSACertChainPath != "" || c.UseSignedTimestamps, } - if c.RFC3161TimestampPath != "" && !(c.TSACertChainPath != "" || c.UseSignedTimestamps) { - return fmt.Errorf("either TSA certificate chain path must be provided or use-signed-timestamps must be set when using RFC3161 timestamp path") + + if c.RFC3161TimestampPath != "" && !co.UseSignedTimestamps { + return fmt.Errorf("when specifying --rfc3161-timestamp-path, you must also specify --use-signed-timestamps or --timestamp-certificate-chain") + } else if c.RFC3161TimestampPath == "" && co.UseSignedTimestamps { + return fmt.Errorf("when specifying --use-signed-timestamps or --timestamp-certificate-chain, you must also specify --rfc3161-timestamp-path") } - if c.TSACertChainPath != "" || c.UseSignedTimestamps { - tsaCertificates, err := c.loadTSACertificates(ctx) + if co.UseSignedTimestamps { + tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets) if err != nil { - return err + return fmt.Errorf("unable to load TSA certificates: %w", err) } co.TSACertificate = tsaCertificates.LeafCert co.TSARootCertificates = tsaCertificates.RootCert diff --git a/cmd/cosign/cli/verify/verify_blob_attestation.go b/cmd/cosign/cli/verify/verify_blob_attestation.go index 3c420930dbb..9dd7629ade0 100644 --- a/cmd/cosign/cli/verify/verify_blob_attestation.go +++ b/cmd/cosign/cli/verify/verify_blob_attestation.go @@ -123,6 +123,7 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st IgnoreSCT: c.IgnoreSCT, Offline: c.Offline, IgnoreTlog: c.IgnoreTlog, + UseSignedTimestamps: c.TSACertChainPath != "" || c.UseSignedTimestamps, } var h v1.Hash if c.CheckClaims { @@ -154,15 +155,15 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st co.ClaimVerifier = cosign.IntotoSubjectClaimVerifier } - // Set up TSA, Fulcio roots and tlog public keys and clients. - if c.RFC3161TimestampPath != "" && !(c.TSACertChainPath != "" || c.UseSignedTimestamps) { - return fmt.Errorf("either TSA certificate chain path must be provided or use-signed-timestamps must be set when using RFC3161 timestamp path") + if c.RFC3161TimestampPath != "" && !co.UseSignedTimestamps { + return fmt.Errorf("when specifying --rfc3161-timestamp-path, you must also specify --use-signed-timestamps or --timestamp-certificate-chain") + } else if c.RFC3161TimestampPath == "" && co.UseSignedTimestamps { + return fmt.Errorf("when specifying --use-signed-timestamps or --timestamp-certificate-chain, you must also specify --rfc3161-timestamp-path") } - - if c.TSACertChainPath != "" || c.UseSignedTimestamps { + if co.UseSignedTimestamps { tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets) if err != nil { - return fmt.Errorf("unable to load or get TSA certificates: %w", err) + return fmt.Errorf("unable to load TSA certificates: %w", err) } co.TSACertificate = tsaCertificates.LeafCert co.TSARootCertificates = tsaCertificates.RootCert diff --git a/pkg/cosign/verify.go b/pkg/cosign/verify.go index d49ed2ddb52..3a6ee79b461 100644 --- a/pkg/cosign/verify.go +++ b/pkg/cosign/verify.go @@ -152,6 +152,8 @@ type CheckOpts struct { TSARootCertificates []*x509.Certificate // TSAIntermediateCertificates are the set of intermediates for chain building TSAIntermediateCertificates []*x509.Certificate + // UseSignedTimestamps enables timestamp verification using a TSA + UseSignedTimestamps bool // IgnoreTlog skip tlog verification IgnoreTlog bool @@ -666,12 +668,15 @@ func verifyInternal(ctx context.Context, sig oci.Signature, h v1.Hash, bundleVerified bool, err error) { var acceptableRFC3161Time, acceptableRekorBundleTime *time.Time // Timestamps for the signature we accept, or nil if not applicable. - acceptableRFC3161Timestamp, err := VerifyRFC3161Timestamp(sig, co) - if err != nil { - return false, fmt.Errorf("unable to verify RFC3161 timestamp bundle: %w", err) - } - if acceptableRFC3161Timestamp != nil { - acceptableRFC3161Time = &acceptableRFC3161Timestamp.Time + var acceptableRFC3161Timestamp *timestamp.Timestamp + if co.UseSignedTimestamps { + acceptableRFC3161Timestamp, err = VerifyRFC3161Timestamp(sig, co) + if err != nil { + return false, fmt.Errorf("unable to verify RFC3161 timestamp bundle: %w", err) + } + if acceptableRFC3161Timestamp != nil { + acceptableRFC3161Time = &acceptableRFC3161Timestamp.Time + } } if !co.IgnoreTlog {