diff --git a/pkg/cosign/verify.go b/pkg/cosign/verify.go index 993281ce737..53faa04ea47 100644 --- a/pkg/cosign/verify.go +++ b/pkg/cosign/verify.go @@ -201,10 +201,11 @@ func (v *verifyTrustedMaterial) PublicKeyVerifier(hint string) (root.TimeConstra // SigstoreGoOptions returns the verification options for verifying with sigstore-go. func (co *CheckOpts) SigstoreGoOptions() (trustedMaterial root.TrustedMaterial, verifierOptions []verify.VerifierOption, policyOptions []verify.PolicyOption, err error) { - var sanMatcher verify.SubjectAlternativeNameMatcher - var issuerMatcher verify.IssuerMatcher + policyOptions = make([]sgverify.PolicyOption, 0) if len(co.Identities) > 0 { + var sanMatcher verify.SubjectAlternativeNameMatcher + var issuerMatcher verify.IssuerMatcher if len(co.Identities) > 1 { return nil, nil, nil, fmt.Errorf("unsupported: multiple identities are not supported at this time") } @@ -217,23 +218,22 @@ func (co *CheckOpts) SigstoreGoOptions() (trustedMaterial root.TrustedMaterial, if err != nil { return nil, nil, nil, err } - } - extensions := certificate.Extensions{ - GithubWorkflowTrigger: co.CertGithubWorkflowTrigger, - GithubWorkflowSHA: co.CertGithubWorkflowSha, - GithubWorkflowName: co.CertGithubWorkflowName, - GithubWorkflowRepository: co.CertGithubWorkflowRepository, - GithubWorkflowRef: co.CertGithubWorkflowRef, - } + extensions := certificate.Extensions{ + GithubWorkflowTrigger: co.CertGithubWorkflowTrigger, + GithubWorkflowSHA: co.CertGithubWorkflowSha, + GithubWorkflowName: co.CertGithubWorkflowName, + GithubWorkflowRepository: co.CertGithubWorkflowRepository, + GithubWorkflowRef: co.CertGithubWorkflowRef, + } - certificateIdentities, err := verify.NewCertificateIdentity(sanMatcher, issuerMatcher, extensions) - if err != nil { - return nil, nil, nil, err + certificateIdentities, err := verify.NewCertificateIdentity(sanMatcher, issuerMatcher, extensions) + if err != nil { + return nil, nil, nil, err + } + policyOptions = []sgverify.PolicyOption{verify.WithCertificateIdentity(certificateIdentities)} } - policyOptions = []sgverify.PolicyOption{verify.WithCertificateIdentity(certificateIdentities)} - // Wrap TrustedMaterial vTrustedMaterial := &verifyTrustedMaterial{TrustedMaterial: co.TrustedMaterial} @@ -245,26 +245,28 @@ func (co *CheckOpts) SigstoreGoOptions() (trustedMaterial root.TrustedMaterial, } } + verifierOptions = make([]sgverify.VerifierOption, 0) + if co.SigVerifier != nil { + // We are verifying with a public key policyOptions = append(policyOptions, verify.WithKey()) newExpiringKey := root.NewExpiringKey(co.SigVerifier, time.Time{}, time.Time{}) vTrustedMaterial.keyTrustedMaterial = root.NewTrustedPublicKeyMaterial(func(_ string) (root.TimeConstrainedVerifier, error) { return newExpiringKey, nil }) + } else { + if !co.IgnoreSCT { + verifierOptions = append(verifierOptions, verify.WithSignedCertificateTimestamps(1)) + } } - // Make some educated guesses about verification policy - verifierOptions = make([]sgverify.VerifierOption, 0) if !co.IgnoreTlog { verifierOptions = append(verifierOptions, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1)) } if co.UseSignedTimestamps { verifierOptions = append(verifierOptions, verify.WithSignedTimestamps(1)) } - if !co.IgnoreSCT { - verifierOptions = append(verifierOptions, verify.WithSignedCertificateTimestamps(1)) - } - if co.IgnoreSCT && !co.UseSignedTimestamps { + if co.IgnoreTlog && !co.UseSignedTimestamps { verifierOptions = append(verifierOptions, verify.WithoutAnyObserverTimestampsUnsafe()) } diff --git a/test/e2e_test.go b/test/e2e_test.go index 598d7faa5c0..9b0a54bec63 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -277,12 +277,15 @@ func TestImportSignVerifyClean(t *testing.T) { } func TestAttestVerify(t *testing.T) { - attestVerify(t, - "slsaprovenance", - `{ "buildType": "x", "builder": { "id": "2" }, "recipe": {} }`, - `predicate: builder: id: "2"`, - `predicate: builder: id: "1"`, - ) + for _, newBundleFormat := range []bool{false, true} { + attestVerify(t, + newBundleFormat, + "slsaprovenance", + `{ "buildType": "x", "builder": { "id": "2" }, "recipe": {} }`, + `predicate: builder: id: "2"`, + `predicate: builder: id: "1"`, + ) + } } func TestAttestVerifySPDXJSON(t *testing.T) { @@ -290,12 +293,15 @@ func TestAttestVerifySPDXJSON(t *testing.T) { if err != nil { t.Fatal(err) } - attestVerify(t, - "spdxjson", - string(attestationBytes), - `predicate: spdxVersion: "SPDX-2.2"`, - `predicate: spdxVersion: "SPDX-9.9"`, - ) + for _, newBundleFormat := range []bool{false, true} { + attestVerify(t, + newBundleFormat, + "spdxjson", + string(attestationBytes), + `predicate: spdxVersion: "SPDX-2.2"`, + `predicate: spdxVersion: "SPDX-9.9"`, + ) + } } func TestAttestVerifyCycloneDXJSON(t *testing.T) { @@ -303,12 +309,15 @@ func TestAttestVerifyCycloneDXJSON(t *testing.T) { if err != nil { t.Fatal(err) } - attestVerify(t, - "cyclonedx", - string(attestationBytes), - `predicate: specVersion: "1.4"`, - `predicate: specVersion: "7.7"`, - ) + for _, newBundleFormat := range []bool{false, true} { + attestVerify(t, + newBundleFormat, + "cyclonedx", + string(attestationBytes), + `predicate: specVersion: "1.4"`, + `predicate: specVersion: "7.7"`, + ) + } } func TestAttestVerifyURI(t *testing.T) { @@ -316,15 +325,18 @@ func TestAttestVerifyURI(t *testing.T) { if err != nil { t.Fatal(err) } - attestVerify(t, - "https://example.com/TestResult/v1", - string(attestationBytes), - `predicate: passed: true`, - `predicate: passed: false"`, - ) + for _, newBundleFormat := range []bool{false, true} { + attestVerify(t, + newBundleFormat, + "https://example.com/TestResult/v1", + string(attestationBytes), + `predicate: passed: true`, + `predicate: passed: false"`, + ) + } } -func attestVerify(t *testing.T, predicateType, attestation, goodCue, badCue string) { +func attestVerify(t *testing.T, newBundleFormat bool, predicateType, attestation, goodCue, badCue string) { repo, stop := reg(t) defer stop() td := t.TempDir() @@ -353,6 +365,10 @@ func attestVerify(t *testing.T, predicateType, attestation, goodCue, badCue stri MaxWorkers: 10, } + if newBundleFormat { + verifyAttestation.ExpectSigstoreBundle = true + } + // Fail case when using without type and policy flag mustErr(verifyAttestation.Exec(ctx, []string{imgName}), t) @@ -361,7 +377,7 @@ func attestVerify(t *testing.T, predicateType, attestation, goodCue, badCue stri } // Now attest the image - ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} + ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc, NewBundleFormat: newBundleFormat} attestCmd := attest.AttestCommand{ KeyOpts: ko, PredicatePath: attestationPath,