mirror of
https://github.com/slsa-framework/slsa-verifier.git
synced 2026-05-21 16:02:54 +00:00
✨ Allow main branch only for trusted builder and e2e tests repos (#63)
* updates * updates * updates * updates * updates * updates * updates * updates * updates * updates * Fix unit tests * unit tests * updates * updates * updates * updates * updates
This commit is contained in:
13
.github/config-release.yml
vendored
Normal file
13
.github/config-release.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Used for pre-submit tests.
|
||||
version: 1
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
- CGO_ENABLED=0
|
||||
|
||||
flags:
|
||||
- -trimpath
|
||||
- -tags=netgo
|
||||
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
binary: slsa-verifier-{{ .Os }}-{{ .Arch }}
|
||||
21
.github/workflows/release.yml
vendored
Normal file
21
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: Verifier releaser
|
||||
|
||||
on:
|
||||
# For manual tests.
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- "*" # triggers only if push new tag version, like `0.8.4`.
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
builder:
|
||||
permissions:
|
||||
id-token: write # For signing.
|
||||
contents: write # For asset uploads.
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/builder_go_slsa3.yml@v0.0.1
|
||||
with:
|
||||
go-version: 1.18
|
||||
config-file: .github/config-release.yml
|
||||
compile-builder: true
|
||||
80
main_test.go
80
main_test.go
@@ -4,9 +4,10 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/slsa-framework/slsa-verifier/pkg"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
pkg "github.com/slsa-framework/slsa-verifier/pkg"
|
||||
)
|
||||
|
||||
func errCmp(e1, e2 error) bool {
|
||||
@@ -31,71 +32,71 @@ func Test_runVerify(t *testing.T) {
|
||||
{
|
||||
name: "valid main branch default",
|
||||
artifact: "./testdata/binary-linux-amd64-workflow_dispatch",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
},
|
||||
{
|
||||
name: "valid main branch set",
|
||||
artifact: "./testdata/binary-linux-amd64-workflow_dispatch",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
branch: "main",
|
||||
},
|
||||
{
|
||||
name: "wrong branch master",
|
||||
artifact: "./testdata/binary-linux-amd64-workflow_dispatch",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
branch: "master",
|
||||
err: pkg.ErrorMismatchBranch,
|
||||
},
|
||||
{
|
||||
name: "wrong source append A",
|
||||
artifact: "./testdata/binary-linux-amd64-workflow_dispatch",
|
||||
source: "github.com/asraa/slsa-on-github-testA",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-genA",
|
||||
err: pkg.ErrorMismatchRepository,
|
||||
},
|
||||
{
|
||||
name: "wrong source prepend A",
|
||||
artifact: "./testdata/binary-linux-amd64-workflow_dispatch",
|
||||
source: "Agithub.com/asraa/slsa-on-github-test",
|
||||
source: "Agithub.com/laurentsimon/slsa-verifier-test-gen",
|
||||
err: pkg.ErrorMismatchRepository,
|
||||
},
|
||||
{
|
||||
name: "wrong source middle A",
|
||||
artifact: "./testdata/binary-linux-amd64-workflow_dispatch",
|
||||
source: "github.com/Aasraa/slsa-on-github-test",
|
||||
source: "github.com/Alaurentsimon/slsa-verifier-test-gen",
|
||||
err: pkg.ErrorMismatchRepository,
|
||||
},
|
||||
{
|
||||
name: "tag no match empty tag workflow_dispatch",
|
||||
artifact: "./testdata/binary-linux-amd64-workflow_dispatch",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
ptag: pString("v1.2.3"),
|
||||
err: pkg.ErrorMismatchTag,
|
||||
},
|
||||
{
|
||||
name: "versioned tag no match empty tag workflow_dispatch",
|
||||
artifact: "./testdata/binary-linux-amd64-workflow_dispatch",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1"),
|
||||
err: pkg.ErrorInvalidSemver,
|
||||
},
|
||||
{
|
||||
name: "tag v1.2.3 no match v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
ptag: pString("v1.2.3"),
|
||||
err: pkg.ErrorMismatchTag,
|
||||
},
|
||||
{
|
||||
name: "tag v1.2 no match v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
ptag: pString("v1.2"),
|
||||
err: pkg.ErrorMismatchTag,
|
||||
},
|
||||
{
|
||||
name: "tag v1 no match v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
ptag: pString("v1"),
|
||||
err: pkg.ErrorMismatchTag,
|
||||
},
|
||||
@@ -103,60 +104,60 @@ func Test_runVerify(t *testing.T) {
|
||||
{
|
||||
name: "versioned v1.2.4 match push-v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1.2.4"),
|
||||
},
|
||||
{
|
||||
name: "versioned v1.2 match push-v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1.2"),
|
||||
},
|
||||
{
|
||||
name: "versioned v1 match push-v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1"),
|
||||
},
|
||||
{
|
||||
name: "versioned v2 no match push-v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v0 no match push-v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v0"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v1.3 no match push-v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1.3"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v1.1 no match push-v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1.1"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v1.2.3 no match push-v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1.2.3"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v1.2.5 no match push-v1.2.4",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v1.2.4",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1.2.5"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
@@ -164,54 +165,54 @@ func Test_runVerify(t *testing.T) {
|
||||
{
|
||||
name: "versioned v2 match push-v2",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2"),
|
||||
},
|
||||
{
|
||||
name: "versioned v2.0 match push-v2",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2.0"),
|
||||
},
|
||||
{
|
||||
name: "versioned v2.1 no match push-v2",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2.1"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v1 no match push-v2",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v3 no match push-v2",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v3"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v1.2 no match push-v2",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1.2"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v3 no match push-v2",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v3"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v0 no match push-v2",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v0"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
@@ -219,71 +220,72 @@ func Test_runVerify(t *testing.T) {
|
||||
{
|
||||
name: "versioned v2.5 match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2.5"),
|
||||
},
|
||||
{
|
||||
name: "versioned v2.5.1 match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2.5.1"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v2.5.3 match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2.5.3"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v2 match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2"),
|
||||
},
|
||||
{
|
||||
name: "versioned v2.4 no match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2.4"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v2.4.1 no match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2.4.1"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v2.4.5 no match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v2.4.5"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v1 no match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v1"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v3 no match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v3"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
{
|
||||
name: "versioned v3.1 no match push-v2.5",
|
||||
artifact: "./testdata/binary-linux-amd64-push-v2.5",
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
source: "github.com/laurentsimon/slsa-verifier-test-gen",
|
||||
pversiontag: pString("v3.1"),
|
||||
err: pkg.ErrorMismatchVersionedTag,
|
||||
},
|
||||
// TODO(laurent): add tests for special cases of buidlers' ref.
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||
|
||||
@@ -44,24 +44,32 @@ const (
|
||||
certOidcIssuer = "https://token.actions.githubusercontent.com"
|
||||
)
|
||||
|
||||
// TODO: remove builder.yml
|
||||
var (
|
||||
trustedBuilderRepository = "slsa-framework/slsa-github-generator"
|
||||
e2eTestRepository = "slsa-framework/example-package"
|
||||
)
|
||||
|
||||
// TODO: remove old builders.
|
||||
var trustedReusableWorkflows = map[string]bool{
|
||||
"slsa-framework/slsa-github-generator/.github/workflows/slsa2_provenance.yml": true,
|
||||
trustedBuilderRepository + "/.github/workflows/slsa2_provenance.yml": true,
|
||||
"slsa-framework/slsa-github-generator-go/.github/workflows/slsa3_builder.yml": true,
|
||||
"slsa-framework/slsa-github-generator-go/.github/workflows/builder.yml": true,
|
||||
"slsa-framework/slsa-github-generator/.github/workflows/builder_go_slsa3.yml": true,
|
||||
trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml": true,
|
||||
}
|
||||
|
||||
var (
|
||||
ErrorInvalidDssePayload = errors.New("invalid DSSE envelope payload")
|
||||
errorRekorSearch = errors.New("error searching rekor entries")
|
||||
errorMismatchHash = errors.New("binary artifact hash does not match provenance subject")
|
||||
ErrorMismatchBranch = errors.New("branch used to generate the binary does not match provenance")
|
||||
ErrorMismatchRepository = errors.New("repository used to generate the binary does not match provenance")
|
||||
ErrorMismatchTag = errors.New("tag used to generate the binary does not match provenance")
|
||||
ErrorMismatchVersionedTag = errors.New("tag used to generate the binary does not match provenance")
|
||||
ErrorInvalidSemver = errors.New("invalid semantic version")
|
||||
errorInvalidVersion = errors.New("invalid version")
|
||||
ErrorInvalidDssePayload = errors.New("invalid DSSE envelope payload")
|
||||
ErrorMismatchBranch = errors.New("branch used to generate the binary does not match provenance")
|
||||
ErrorMismatchRepository = errors.New("repository used to generate the binary does not match provenance")
|
||||
ErrorMismatchTag = errors.New("tag used to generate the binary does not match provenance")
|
||||
ErrorMismatchVersionedTag = errors.New("tag used to generate the binary does not match provenance")
|
||||
ErrorInvalidSemver = errors.New("invalid semantic version")
|
||||
errorRekorSearch = errors.New("error searching rekor entries")
|
||||
errorMismatchHash = errors.New("binary artifact hash does not match provenance subject")
|
||||
errorInvalidVersion = errors.New("invalid version")
|
||||
errorInvalidRef = errors.New("invalid ref")
|
||||
errorMalformedWorkflowURI = errors.New("malformed URI for workflow")
|
||||
errorUntrustedReusableWorkflow = errors.New("untrusted reusable workflow")
|
||||
)
|
||||
|
||||
func EnvelopeFromBytes(payload []byte) (env *dsselib.Envelope, err error) {
|
||||
@@ -380,15 +388,23 @@ func VerifyWorkflowIdentity(id *WorkflowIdentity, source string) error {
|
||||
// cert URI path is /org/repo/path/to/workflow@ref
|
||||
workflowPath := strings.SplitN(id.JobWobWorkflowRef, "@", 2)
|
||||
if len(workflowPath) < 2 {
|
||||
return errors.New("malformed URI for workflow")
|
||||
return fmt.Errorf("%w: %s", errorMalformedWorkflowURI, id.JobWobWorkflowRef)
|
||||
}
|
||||
|
||||
if _, ok := trustedReusableWorkflows[strings.Trim(workflowPath[0], "/")]; !ok {
|
||||
return errors.New("untrusted reuseable workflow")
|
||||
// Trusted workflow verification by name.
|
||||
reusableWorkflowName := strings.Trim(workflowPath[0], "/")
|
||||
if _, ok := trustedReusableWorkflows[reusableWorkflowName]; !ok {
|
||||
return fmt.Errorf("%w: %s", errorUntrustedReusableWorkflow, reusableWorkflowName)
|
||||
}
|
||||
|
||||
// Verify the ref.
|
||||
if err := verifyTrustedBuilderRef(id, strings.Trim(workflowPath[1], "/")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Issue verification.
|
||||
if !strings.EqualFold(id.Issuer, certOidcIssuer) {
|
||||
return errors.New("untrusted token issuer")
|
||||
return fmt.Errorf("untrusted token issuer: %s", id.Issuer)
|
||||
}
|
||||
|
||||
// The caller repository in the x509 extension is not fully qualified. It only contains
|
||||
@@ -402,6 +418,31 @@ func VerifyWorkflowIdentity(id *WorkflowIdentity, source string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Only allow `@refs/heads/main` for the builder and the e2e tests that need to work at HEAD.
|
||||
// This lets us use the pre-build builder binary generated during release (release happen at main).
|
||||
// For other projects, we only allow semantic versions that map to a release.
|
||||
func verifyTrustedBuilderRef(id *WorkflowIdentity, ref string) error {
|
||||
if (id.CallerRepository == trustedBuilderRepository ||
|
||||
id.CallerRepository == e2eTestRepository) &&
|
||||
strings.EqualFold("refs/heads/main", ref) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(ref, "refs/tags/") {
|
||||
return fmt.Errorf("%w: %s: not of the form 'refs/tags/name'", errorInvalidRef, ref)
|
||||
}
|
||||
|
||||
// Valid semver of the form vX.Y.Z with no metadata.
|
||||
pin := strings.TrimPrefix(ref, "refs/tags/")
|
||||
if !(semver.IsValid(pin) &&
|
||||
len(strings.Split(pin, ".")) == 3 &&
|
||||
semver.Prerelease(pin) == "" &&
|
||||
semver.Build(pin) == "") {
|
||||
return fmt.Errorf("%w: %s: not of the form vX.Y.Z", errorInvalidRef, pin)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func VerifyProvenance(env *dsselib.Envelope, expectedHash string) error {
|
||||
hash, err := getSha256Digest(env)
|
||||
if err != nil {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
dsselib "github.com/secure-systems-lab/go-securesystemslib/dsse"
|
||||
"github.com/sigstore/rekor/pkg/generated/client"
|
||||
"github.com/sigstore/rekor/pkg/generated/client/index"
|
||||
@@ -162,7 +163,7 @@ func Test_VerifyWorkflowIdentity(t *testing.T) {
|
||||
name string
|
||||
workflow *WorkflowIdentity
|
||||
source string
|
||||
res bool
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "invalid job workflow ref",
|
||||
@@ -174,7 +175,7 @@ func Test_VerifyWorkflowIdentity(t *testing.T) {
|
||||
Issuer: "https://token.actions.githubusercontent.com",
|
||||
},
|
||||
source: "asraa/slsa-on-github-test",
|
||||
res: false,
|
||||
err: errorMalformedWorkflowURI,
|
||||
},
|
||||
{
|
||||
name: "untrusted job workflow ref",
|
||||
@@ -186,55 +187,134 @@ func Test_VerifyWorkflowIdentity(t *testing.T) {
|
||||
Issuer: "https://token.actions.githubusercontent.com",
|
||||
},
|
||||
source: "asraa/slsa-on-github-test",
|
||||
res: false,
|
||||
err: errorUntrustedReusableWorkflow,
|
||||
},
|
||||
{
|
||||
name: "untrusted job workflow ref",
|
||||
name: "untrusted job workflow ref for general repos",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: "asraa/slsa-on-github-test",
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: "/slsa-framework/slsa-github-generator-go/.github/workflows/builder.yml@refs/heads/main",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/heads/main",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: "https://bad.issuer.com",
|
||||
},
|
||||
source: "asraa/slsa-on-github-test",
|
||||
res: false,
|
||||
err: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "valid main ref for trusted builder",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: trustedBuilderRepository,
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/heads/main",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: "https://token.actions.githubusercontent.com",
|
||||
},
|
||||
source: trustedBuilderRepository,
|
||||
},
|
||||
{
|
||||
name: "valid main ref for e2e test",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: e2eTestRepository,
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/heads/main",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: certOidcIssuer,
|
||||
},
|
||||
source: e2eTestRepository,
|
||||
},
|
||||
{
|
||||
name: "unexpected source for e2e test",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: e2eTestRepository,
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/heads/main",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: certOidcIssuer,
|
||||
},
|
||||
source: "malicious/source",
|
||||
err: ErrorMismatchRepository,
|
||||
},
|
||||
{
|
||||
name: "valid main ref for builder",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: trustedBuilderRepository,
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/heads/main",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: certOidcIssuer,
|
||||
},
|
||||
source: "malicious/source",
|
||||
err: ErrorMismatchRepository,
|
||||
},
|
||||
{
|
||||
name: "unexpected source",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: "malicious/slsa-on-github-test",
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: "/slsa-framework/slsa-github-generator-go/.github/workflows/builder.yml@refs/heads/main",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: "https://token.actions.githubusercontent.com",
|
||||
Issuer: certOidcIssuer,
|
||||
},
|
||||
source: "asraa/slsa-on-github-test",
|
||||
res: false,
|
||||
err: ErrorMismatchRepository,
|
||||
},
|
||||
{
|
||||
name: "valid workflow identity",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: "asraa/slsa-on-github-test",
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: "/slsa-framework/slsa-github-generator-go/.github/workflows/builder.yml@refs/heads/main",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: "https://token.actions.githubusercontent.com",
|
||||
Issuer: certOidcIssuer,
|
||||
},
|
||||
source: "asraa/slsa-on-github-test",
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
name: "invalid workflow identity with prerelease",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: "asraa/slsa-on-github-test",
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3-alpha",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: certOidcIssuer,
|
||||
},
|
||||
source: "asraa/slsa-on-github-test",
|
||||
err: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "invalid workflow identity with build",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: "asraa/slsa-on-github-test",
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3+123",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: certOidcIssuer,
|
||||
},
|
||||
source: "asraa/slsa-on-github-test",
|
||||
err: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "invalid workflow identity with metadata",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: "asraa/slsa-on-github-test",
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3-alpha+123",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: certOidcIssuer,
|
||||
},
|
||||
source: "asraa/slsa-on-github-test",
|
||||
err: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "valid workflow identity with fully qualified source",
|
||||
workflow: &WorkflowIdentity{
|
||||
CallerRepository: "asraa/slsa-on-github-test",
|
||||
CallerHash: "0dfcd24824432c4ce587f79c918eef8fc2c44d7b",
|
||||
JobWobWorkflowRef: "/slsa-framework/slsa-github-generator-go/.github/workflows/builder.yml@refs/heads/main",
|
||||
JobWobWorkflowRef: trustedBuilderRepository + "/.github/workflows/builder_go_slsa3.yml@refs/tags/v1.2.3",
|
||||
Trigger: "workflow_dispatch",
|
||||
Issuer: "https://token.actions.githubusercontent.com",
|
||||
Issuer: certOidcIssuer,
|
||||
},
|
||||
source: "github.com/asraa/slsa-on-github-test",
|
||||
res: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@@ -242,8 +322,8 @@ func Test_VerifyWorkflowIdentity(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := VerifyWorkflowIdentity(tt.workflow, tt.source)
|
||||
if (err == nil) != tt.res {
|
||||
t.Errorf("unexpected result, expected verfication %t", tt.res)
|
||||
if !errCmp(err, tt.err) {
|
||||
t.Errorf(cmp.Diff(err, tt.err, cmpopts.EquateErrors()))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -351,6 +431,156 @@ func Test_VerifyTag(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_verifyTrustedBuilderRef(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
callerRepo string
|
||||
builderRef string
|
||||
expected error
|
||||
}{
|
||||
// Trusted repo.
|
||||
{
|
||||
name: "main allowed for builder",
|
||||
callerRepo: trustedBuilderRepository,
|
||||
builderRef: "refs/heads/main",
|
||||
},
|
||||
{
|
||||
name: "full semver for builder",
|
||||
callerRepo: trustedBuilderRepository,
|
||||
builderRef: "refs/tags/v1.2.3",
|
||||
},
|
||||
{
|
||||
name: "no patch semver for other builder",
|
||||
callerRepo: trustedBuilderRepository,
|
||||
builderRef: "refs/tags/v1.2",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "no min semver for builder",
|
||||
callerRepo: trustedBuilderRepository,
|
||||
builderRef: "refs/tags/v1",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver with prerelease for builder",
|
||||
callerRepo: trustedBuilderRepository,
|
||||
builderRef: "refs/tags/v1.2.3-alpha",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver with build for builder",
|
||||
callerRepo: trustedBuilderRepository,
|
||||
builderRef: "refs/tags/v1.2.3+123",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver with build/prerelease for builder",
|
||||
callerRepo: trustedBuilderRepository,
|
||||
builderRef: "refs/tags/v1.2.3-alpha+123",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
// E2e tests repo.
|
||||
{
|
||||
name: "main allowed for test repo",
|
||||
callerRepo: e2eTestRepository,
|
||||
builderRef: "refs/heads/main",
|
||||
},
|
||||
{
|
||||
name: "full semver for test repo",
|
||||
callerRepo: e2eTestRepository,
|
||||
builderRef: "refs/tags/v1.2.3",
|
||||
},
|
||||
{
|
||||
name: "no patch semver for test repo",
|
||||
callerRepo: e2eTestRepository,
|
||||
builderRef: "refs/tags/v1.2",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "no min semver for test repo",
|
||||
callerRepo: e2eTestRepository,
|
||||
builderRef: "refs/tags/v1",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver with prerelease for test repo",
|
||||
callerRepo: e2eTestRepository,
|
||||
builderRef: "refs/tags/v1.2.3-alpha",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver with build for test repo",
|
||||
callerRepo: e2eTestRepository,
|
||||
builderRef: "refs/tags/v1.2.3+123",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver with build/prerelease for test repo",
|
||||
callerRepo: e2eTestRepository,
|
||||
builderRef: "refs/tags/v1.2.3-alpha+123",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
// Other repos.
|
||||
{
|
||||
name: "main not allowed for other repos",
|
||||
callerRepo: "some/repo",
|
||||
builderRef: "refs/heads/main",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver for other repos",
|
||||
callerRepo: "some/repo",
|
||||
builderRef: "refs/tags/v1.2.3",
|
||||
},
|
||||
{
|
||||
name: "no patch semver for other repos",
|
||||
callerRepo: "some/repo",
|
||||
builderRef: "refs/tags/v1.2",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "no min semver for other repos",
|
||||
callerRepo: "some/repo",
|
||||
builderRef: "refs/tags/v1",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver with prerelease for other repos",
|
||||
callerRepo: "some/repo",
|
||||
builderRef: "refs/tags/v1.2.3-alpha",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver with build for other repos",
|
||||
callerRepo: "some/repo",
|
||||
builderRef: "refs/tags/v1.2.3+123",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
{
|
||||
name: "full semver with build/prerelease for other repos",
|
||||
callerRepo: "some/repo",
|
||||
builderRef: "refs/tags/v1.2.3-alpha+123",
|
||||
expected: errorInvalidRef,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
wf := WorkflowIdentity{
|
||||
CallerRepository: tt.callerRepo,
|
||||
}
|
||||
|
||||
err := verifyTrustedBuilderRef(&wf, tt.builderRef)
|
||||
if !errCmp(err, tt.expected) {
|
||||
t.Errorf(cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_VerifyVersionedTag(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
|
||||
BIN
testdata/binary-linux-amd64-push-v1.2.4
vendored
BIN
testdata/binary-linux-amd64-push-v1.2.4
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
testdata/binary-linux-amd64-push-v2
vendored
BIN
testdata/binary-linux-amd64-push-v2
vendored
Binary file not shown.
BIN
testdata/binary-linux-amd64-push-v2.5
vendored
BIN
testdata/binary-linux-amd64-push-v2.5
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
testdata/binary-linux-amd64-workflow_dispatch
vendored
BIN
testdata/binary-linux-amd64-workflow_dispatch
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user