Skip to content

Commit

Permalink
Add tests and fix a few verifier options
Browse files Browse the repository at this point in the history
Signed-off-by: Cody Soyland <[email protected]>
  • Loading branch information
codysoyland committed Nov 5, 2024
1 parent b17dfd8 commit 5ae6109
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 47 deletions.
44 changes: 23 additions & 21 deletions pkg/cosign/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand All @@ -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}

Expand All @@ -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())
}

Expand Down
68 changes: 42 additions & 26 deletions test/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,54 +277,66 @@ 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) {
attestationBytes, err := os.ReadFile("./testdata/bom-go-mod.spdx.json")
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) {
attestationBytes, err := os.ReadFile("./testdata/bom-go-mod.cyclonedx.json")
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) {
attestationBytes, err := os.ReadFile("./testdata/test-result.json")
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()
Expand Down Expand Up @@ -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)

Expand All @@ -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,
Expand Down

0 comments on commit 5ae6109

Please sign in to comment.