Skip to content

Commit 9bfbc91

Browse files
author
Ian Lewis
authored
refactor: Provenance tests (#628)
Refactors GHA provenance tests to use `testProvenance` which makes it clearer what is actually being tested. This will also make it easier to support `buildType` as a way to have different verification logic as the tests no longer rely on testdata with the `"https://github.com/Attestations/GitHubActionsWorkflow@v1"` build type, which isn't used by any supported builders. A couple of updates to utilities: - `VerifyTag` will now validate the ref returned by the `Provenance` instance. - `VerifyBranch` will now validate the ref returned by the `Provenance` instance. - `VerifyDigest` now supports the 160 bit `"sha1"` algo (FWIW) and will now search all subject entries even if one subject entry's algorithm does not match the expected algorithm. --------- Signed-off-by: Ian Lewis <[email protected]>
1 parent 8fe8ee9 commit 9bfbc91

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+598
-760
lines changed

cli/slsa-verifier/main_regression_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,14 @@ func Test_runVerifyGHAArtifactPath(t *testing.T) {
156156
artifacts: []string{"binary-linux-amd64-workflow_dispatch"},
157157
source: "github.com/slsa-framework/example-package",
158158
ptag: pString("v1.2.3"),
159-
err: serrors.ErrorMismatchTag,
159+
err: serrors.ErrorInvalidRef,
160160
},
161161
{
162162
name: "versioned tag no match empty tag workflow_dispatch",
163163
artifacts: []string{"binary-linux-amd64-workflow_dispatch"},
164164
source: "github.com/slsa-framework/example-package",
165165
pversiontag: pString("v1"),
166-
err: serrors.ErrorInvalidSemver,
166+
err: serrors.ErrorInvalidRef,
167167
},
168168
// Provenance contains tag = v13.0.30.
169169
{
@@ -477,7 +477,7 @@ func Test_runVerifyGHAArtifactPath(t *testing.T) {
477477
source: "github.com/asraa/slsa-on-github-test",
478478
pversiontag: pString("v1.5.0"),
479479
pbranch: pString("main"),
480-
err: serrors.ErrorMismatchBranch,
480+
err: serrors.ErrorInvalidRef,
481481
noversion: true,
482482
},
483483
// Workflow inputs.
@@ -746,14 +746,14 @@ func Test_runVerifyGHAArtifactImage(t *testing.T) {
746746
artifact: "container_workflow_dispatch",
747747
source: "github.com/slsa-framework/example-package",
748748
ptag: pString("v1.2.3"),
749-
err: serrors.ErrorMismatchTag,
749+
err: serrors.ErrorInvalidRef,
750750
},
751751
{
752752
name: "versioned tag no match empty tag workflow_dispatch",
753753
artifact: "container_workflow_dispatch",
754754
source: "github.com/slsa-framework/example-package",
755755
pversiontag: pString("v1"),
756-
err: serrors.ErrorInvalidSemver,
756+
err: serrors.ErrorInvalidRef,
757757
},
758758
}
759759
for _, tt := range tests {
@@ -1327,14 +1327,14 @@ func Test_runVerifyGHAContainerBased(t *testing.T) {
13271327
artifacts: []string{"workflow_dispatch.main.default"},
13281328
source: "github.com/slsa-framework/example-package",
13291329
pversiontag: pString("v1"),
1330-
err: serrors.ErrorInvalidSemver,
1330+
err: serrors.ErrorInvalidRef,
13311331
},
13321332
{
13331333
name: "tag no match empty tag workflow_dispatch",
13341334
artifacts: []string{"workflow_dispatch.main.default"},
13351335
source: "github.com/slsa-framework/example-package",
13361336
ptag: pString("v1.2.3"),
1337-
err: serrors.ErrorMismatchTag,
1337+
err: serrors.ErrorInvalidRef,
13381338
},
13391339
{
13401340
name: "wrong branch master",

verifiers/internal/gha/provenance.go

+36-9
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,19 @@ func verifyDigest(prov slsaprovenance.Provenance, expectedHash string) error {
179179
}
180180

181181
// 8 bit represented in hex, so 8/2=4.
182-
l := len(expectedHash) * 4
182+
bitLength := len(expectedHash) * 4
183+
expectedAlgo := fmt.Sprintf("sha%v", bitLength)
184+
// TODO(#630): Add subject digest minimum bit length check.
185+
// sha1 is 160 bit (FWIW).
186+
if bitLength == 160 {
187+
expectedAlgo = "sha1"
188+
}
189+
183190
for _, subject := range subjects {
184191
digestSet := subject.Digest
185-
hash, exists := digestSet[fmt.Sprintf("sha%v", l)]
192+
hash, exists := digestSet[expectedAlgo]
186193
if !exists {
187-
return fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, fmt.Sprintf("no sha%v subject digest", l))
194+
continue
188195
}
189196
if hash == expectedHash {
190197
return nil
@@ -383,44 +390,64 @@ func VerifyWorkflowInputs(prov slsaprovenance.Provenance, inputs map[string]stri
383390
return nil
384391
}
385392

393+
// VerifyBranch verifies that the source branch in the provenance matches the
394+
// expected value.
386395
func VerifyBranch(prov slsaprovenance.Provenance, expectedBranch string) error {
387-
branch, err := prov.GetBranch()
396+
ref, err := prov.GetBranch()
388397
if err != nil {
389398
return err
390399
}
391400

392-
expectedBranch = "refs/heads/" + expectedBranch
401+
branch, err := utils.BranchFromGitRef(ref)
402+
if err != nil {
403+
return fmt.Errorf("verifying branch: %w", err)
404+
}
405+
393406
if branch != expectedBranch {
394407
return fmt.Errorf("expected branch '%s', got '%s': %w", expectedBranch, branch, serrors.ErrorMismatchBranch)
395408
}
396409

397410
return nil
398411
}
399412

413+
// VerifyTag verifies that the source tag in the provenance matches the
414+
// expected value.
400415
func VerifyTag(prov slsaprovenance.Provenance, expectedTag string) error {
401-
tag, err := prov.GetTag()
416+
ref, err := prov.GetTag()
402417
if err != nil {
403418
return err
404419
}
405420

406-
expectedTag = "refs/tags/" + expectedTag
421+
tag, err := utils.TagFromGitRef(ref)
422+
if err != nil {
423+
return fmt.Errorf("verifying tag: %w", err)
424+
}
425+
407426
if tag != expectedTag {
408427
return fmt.Errorf("expected tag '%s', got '%s': %w", expectedTag, tag, serrors.ErrorMismatchTag)
409428
}
410429

411430
return nil
412431
}
413432

433+
// VerifyVersionedTag verifies that the source tag in the provenance matches the
434+
// expected semver value.
414435
func VerifyVersionedTag(prov slsaprovenance.Provenance, expectedTag string) error {
415436
// Retrieve, validate and canonicalize the provenance tag.
416437
// Note: prerelease is validated as part of patch validation
417438
// and must be equal. Build is discarded as per https://semver.org/:
418439
// "Build metadata MUST be ignored when determining version precedence",
419-
tag, err := prov.GetTag()
440+
ref, err := prov.GetTag()
420441
if err != nil {
421442
return err
422443
}
423-
return utils.VerifyVersionedTag(strings.TrimPrefix(tag, "refs/tags/"), expectedTag)
444+
445+
tag, err := utils.TagFromGitRef(ref)
446+
if err != nil {
447+
return fmt.Errorf("verifying tag: %w", err)
448+
}
449+
450+
return utils.VerifyVersionedTag(tag, expectedTag)
424451
}
425452

426453
// hasCertInEnvelope checks if a valid x509 certificate is present in the

0 commit comments

Comments
 (0)