Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Support pre-releases on trusted repos #552

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/pre-submit.cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ jobs:
path: ./event_name.txt

- name: Run tests for verifier
# TODO(#554): Don't set SLSA_VERIFIER_TESTING
env:
SLSA_VERIFIER_TESTING: "true"
run: |
set -euo pipefail
make regression-test
1 change: 1 addition & 0 deletions .github/workflows/pre-submit.e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ jobs:
- name: Run verification script with testdata and slsa-verifier HEAD
run: ./__THIS_REPO__/.github/workflows/scripts/e2e-cli.sh
env:
SLSA_VERIFIER_TESTING: "true"
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Necessary to use the gh CLI.
8 changes: 8 additions & 0 deletions cli/slsa-verifier/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"

"github.com/slsa-framework/slsa-verifier/v2/options"
"github.com/spf13/cobra"
"sigs.k8s.io/release-utils/version"
)
Expand All @@ -16,6 +17,12 @@ func check(err error) {
}
}

func envWarnings() {
if options.TestingEnabled() {
fmt.Fprintf(os.Stderr, "WARNING: Insecure SLSA_VERIFIER_TESTING is enabled.\n")
}
}

func rootCmd() *cobra.Command {
c := &cobra.Command{
Use: "slsa-verifier",
Expand All @@ -36,5 +43,6 @@ For more information on SLSA, visit https://slsa.dev`,
}

func main() {
envWarnings()
check(rootCmd().Execute())
}
21 changes: 19 additions & 2 deletions options/env.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
package options

import "os"
import (
"os"
"strconv"
)

// ExperimentalEnabled returns true if experimental features are currently
// enabled.
func ExperimentalEnabled() bool {
return os.Getenv("SLSA_VERIFIER_EXPERIMENTAL") == "1"
if b, err := strconv.ParseBool(os.Getenv("SLSA_VERIFIER_EXPERIMENTAL")); err == nil {
return b
}
return false
}

// TestingEnabled returns true if the SLSA_VERIFIER_TESTING environment
// variable is set.
func TestingEnabled() bool {
if b, err := strconv.ParseBool(os.Getenv("SLSA_VERIFIER_TESTING")); err == nil {
return b
}
return false
}
22 changes: 21 additions & 1 deletion verifiers/internal/gha/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,27 @@ func verifyTrustedBuilderID(certPath, certTag string, expectedBuilderID *string,
func verifyTrustedBuilderRef(id *WorkflowIdentity, ref string) error {
if (id.CallerRepository == trustedBuilderRepository ||
id.CallerRepository == e2eTestRepository) &&
strings.EqualFold("refs/heads/main", ref) {
options.TestingEnabled() {
// Allow verification on the main branch to support e2e tests.
if ref == "refs/heads/main" {
return nil
}

// Extract the tag.
pin, err := utils.TagFromGitHubRef(ref)
if err != nil {
return err
}

// Tags on trusted repositories should be a valid semver with version
// core including all three parts and no build identifier.
versionCore := strings.Split(pin, "-")[0]
if !semver.IsValid(pin) ||
len(strings.Split(versionCore, ".")) != 3 ||
semver.Build(pin) != "" {
return fmt.Errorf("%w: %s: version tag not valid", serrors.ErrorInvalidRef, pin)
}

return nil
}

Expand Down
64 changes: 55 additions & 9 deletions verifiers/internal/gha/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,18 +488,25 @@ func Test_verifyTrustedBuilderID(t *testing.T) {
}

func Test_verifyTrustedBuilderRef(t *testing.T) {
t.Parallel()
tests := []struct {
name string
callerRepo string
builderRef string
expected error
name string
callerRepo string
builderRef string
expected error
testingEnabled bool
}{
// Trusted repo.
{
name: "main allowed for builder",
name: "main not allowed for builder",
callerRepo: trustedBuilderRepository,
builderRef: "refs/heads/main",
expected: serrors.ErrorInvalidRef,
},
{
name: "main allowed for builder w/ testing enabled",
callerRepo: trustedBuilderRepository,
builderRef: "refs/heads/main",
testingEnabled: true,
},
{
name: "full semver for builder",
Expand Down Expand Up @@ -538,10 +545,18 @@ func Test_verifyTrustedBuilderRef(t *testing.T) {
},
// E2e tests repo.
{
name: "main allowed for test repo",
name: "main not allowed for test repo",
callerRepo: e2eTestRepository,
builderRef: "refs/heads/main",
expected: serrors.ErrorInvalidRef,
},
{
name: "main allowed for test repo w/ testing enabled",
callerRepo: e2eTestRepository,
builderRef: "refs/heads/main",
testingEnabled: true,
},

{
name: "full semver for test repo",
callerRepo: e2eTestRepository,
Expand Down Expand Up @@ -585,6 +600,14 @@ func Test_verifyTrustedBuilderRef(t *testing.T) {
expected: serrors.ErrorInvalidRef,
},
{
name: "main not allowed for other repos w/ testing enabled",
callerRepo: "some/repo",
builderRef: "refs/heads/main",
testingEnabled: true,
expected: serrors.ErrorInvalidRef,
},
{

name: "full semver for other repos",
callerRepo: "some/repo",
builderRef: "refs/tags/v1.2.3",
Expand All @@ -607,28 +630,51 @@ func Test_verifyTrustedBuilderRef(t *testing.T) {
builderRef: "refs/tags/v1.2.3-alpha",
expected: serrors.ErrorInvalidRef,
},
{
name: "full semver with prerelease for other repos w/ testing enabled",
callerRepo: "some/repo",
builderRef: "refs/tags/v1.2.3-alpha",
testingEnabled: true,
expected: serrors.ErrorInvalidRef,
},
{
name: "full semver with build for other repos",
callerRepo: "some/repo",
builderRef: "refs/tags/v1.2.3+123",
expected: serrors.ErrorInvalidRef,
},
{
name: "full semver with build for other repos w/ testing enabled",
callerRepo: "some/repo",
builderRef: "refs/tags/v1.2.3+123",
testingEnabled: true,
expected: serrors.ErrorInvalidRef,
},
{
name: "full semver with build/prerelease for other repos",
callerRepo: "some/repo",
builderRef: "refs/tags/v1.2.3-alpha+123",
expected: serrors.ErrorInvalidRef,
},
{
name: "full semver with build/prerelease for other repos w/ testing enabled",
callerRepo: "some/repo",
builderRef: "refs/tags/v1.2.3-alpha+123",
testingEnabled: true,
expected: serrors.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,
}

if tt.testingEnabled {
t.Setenv("SLSA_VERIFIER_TESTING", "1")
}

err := verifyTrustedBuilderRef(&wf, tt.builderRef)
if !errCmp(err, tt.expected) {
t.Errorf(cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
Expand Down
4 changes: 2 additions & 2 deletions verifiers/internal/gha/provenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ func VerifyBranch(prov slsaprovenance.Provenance, expectedBranch string) error {
}

expectedBranch = "refs/heads/" + expectedBranch
if !strings.EqualFold(branch, expectedBranch) {
if branch != expectedBranch {
return fmt.Errorf("expected branch '%s', got '%s': %w", expectedBranch, branch, serrors.ErrorMismatchBranch)
}

Expand All @@ -331,7 +331,7 @@ func VerifyTag(prov slsaprovenance.Provenance, expectedTag string) error {
}

expectedTag = "refs/tags/" + expectedTag
if !strings.EqualFold(tag, expectedTag) {
if tag != expectedTag {
return fmt.Errorf("expected tag '%s', got '%s': %w", expectedTag, tag, serrors.ErrorMismatchTag)
}

Expand Down
17 changes: 17 additions & 0 deletions verifiers/internal/gha/provenance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,12 @@ func Test_VerifyBranch(t *testing.T) {
path: "./testdata/dsse-branch3-ref-v1.intoto.jsonl",
branch: "branch3",
},
{
name: "ref main case-sensitive",
path: "./testdata/dsse-main-ref-v1.intoto.jsonl",
branch: "Main",
expected: serrors.ErrorMismatchBranch,
},

{
name: "invalid ref type",
Expand Down Expand Up @@ -868,11 +874,22 @@ func Test_VerifyTag(t *testing.T) {
path: "./testdata/dsse-invalid-ref-type-v1.intoto.jsonl",
expected: serrors.ErrorInvalidDssePayload,
},
{
name: "tag vSLSA1 case-sensitive",
path: "./testdata/dsse-vslsa1-tag.intoto.jsonl",
tag: "vSLSA1",
expected: serrors.ErrorMismatchTag,
},
{
name: "tag vslsa1",
path: "./testdata/dsse-vslsa1-tag-v1.intoto.jsonl",
tag: "vslsa1",
},
{
name: "case sensitive",
path: "./testdata/dsse-vslsa1-tag-v1.intoto.jsonl",
tag: "vslsa1",
},
}
for _, tt := range tests {
tt := tt // Re-initializing variable so it is not changed while executing the closure below
Expand Down