diff --git a/.github/workflows/scripts/pre-release/references.sh b/.github/workflows/scripts/pre-release/references.sh index e9ab23f..4789432 100755 --- a/.github/workflows/scripts/pre-release/references.sh +++ b/.github/workflows/scripts/pre-release/references.sh @@ -71,7 +71,7 @@ fi # Select all version numbers following a reference to slsa-verifier that are different # from the version defined in SHA256SUM.md results=$( - grep -Pon ".*?slsa-verifier.*?\d+\.\d+\.\d+" README.md | + grep -Pon ".*?slsa-verifier.*?v\d+\.\d+\.\d+" README.md actions/installer/README.md | grep -v "$RELEASE_TAG$" | sed -E 's/(.*)/ \1/' || true ) diff --git a/.slsa-goreleaser/windows-amd64.yml b/.slsa-goreleaser/windows-amd64.yml index d845b29..a44218d 100644 --- a/.slsa-goreleaser/windows-amd64.yml +++ b/.slsa-goreleaser/windows-amd64.yml @@ -10,7 +10,7 @@ flags: goos: windows goarch: amd64 -binary: slsa-verifier-{{ .Os }}-{{ .Arch }} +binary: slsa-verifier-{{ .Os }}-{{ .Arch }}.exe dir: ./cli/slsa-verifier ldflags: diff --git a/.slsa-goreleaser/windows-arm64.yml b/.slsa-goreleaser/windows-arm64.yml index 8fff8ea..e674a7a 100644 --- a/.slsa-goreleaser/windows-arm64.yml +++ b/.slsa-goreleaser/windows-arm64.yml @@ -10,7 +10,7 @@ flags: goos: windows goarch: arm64 -binary: slsa-verifier-{{ .Os }}-{{ .Arch }} +binary: slsa-verifier-{{ .Os }}-{{ .Arch }}.exe dir: ./cli/slsa-verifier ldflags: diff --git a/README.md b/README.md index 7afabaf..26827f2 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ We have no plan to maintain this repository actively. - [Compilation from source](#compilation-from-source) - [Option 1: Install via go](#option-1-install-via-go) - [Option 2: Compile manually](#option-2-compile-manually) + - [Option 3: Use the installer Action](#option-3-use-the-installer-action) - [Download the binary](#download-the-binary) - [Available options](#available-options) - [Option list](#option-list) @@ -136,19 +137,52 @@ You have two options to install the verifier. #### Option 1: Install via go -``` +If you want to install the verifier, you can run the following command: +```bash $ go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@v2.0.1 $ slsa-verifier ``` -#### Option 2: Compile manually +Tools like [dependabot](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates) or [renovate](https://github.com/renovatebot/renovate) use your project's go.mod to identify the version of your Go dependencies. +If you install the verifier binary in CI, we strongly recommend you create a placeholder `go.mod` containing slsa-verifier as a dependency to receive updates and keep the binary up-to-date. Use the following the steps: + +1. Create a tooling/tooling_test.go file containing the following: +```go +//go:build tools +// +build tools + +package main +import ( + _ "github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier" +) ``` + +1. Run the following commands in the tooling directory. (It will create a go.sum file.) +```bash +$ go mod init -tooling +$ go mod tidy +``` + +1. Commit the tooling folder (containing the 3 files tooling_test.go, go.mod and go.sum) to the repository. +1. To install the verifier in your CI, run the following commands: +```bash +$ cd tooling +$ grep _ tooling_test.go | cut -f2 -d '"' | xargs -n1 -t go install +``` + +#### Option 2: Compile manually + +```bash $ git clone git@github.com:slsa-framework/slsa-verifier.git $ cd slsa-verifier && git checkout v2.0.1 $ go run ./cli/slsa-verifier ``` +#### Option 3: Use the installer Action + +If you need to install the verifier to run in a GitHub workflow, use the installer Action as described in [actions/installer/README.md](./actions/installer/README.md). + ### Download the binary Download the binary from the latest release at [https://github.com/slsa-framework/slsa-verifier/releases/tag/v2.0.1](https://github.com/slsa-framework/slsa-verifier/releases/tag/v2.0.1) @@ -157,7 +191,7 @@ Download the [SHA256SUM.md](https://github.com/slsa-framework/slsa-verifier/blob Verify the checksum: -``` +```bash $ sha256sum -c --strict SHA256SUM.md slsa-verifier-linux-amd64: OK ``` diff --git a/RELEASE.md b/RELEASE.md index 4a923bf..5fe8331 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -110,10 +110,10 @@ $ sha256sum slsa-verifier-linux-amd64 slsa-verifier-linux-amd64 ``` -3. Update the latest version in the [README.md](./README.md): +3. Update the latest version in the main [README.md](./README.md) and the installer Action's [actions/installer/README.md](./actions/installer/README.md): ```shell -$ sed -i "s/v1.0.0/v1.1.1/g" ./README.md +$ sed -i "s/v1.0.0/v1.1.1/g" ./README.md ./actions/installer/README.md ``` 4. Send a pull request with the changes. In the description: diff --git a/actions/installer/README.md b/actions/installer/README.md index fda9680..8c4a5e7 100644 --- a/actions/installer/README.md +++ b/actions/installer/README.md @@ -11,11 +11,9 @@ For more information about SLSA in general, see [https://slsa.dev](https://slsa. To install a specific version of `slsa-verifier`, use: ```yaml -uses: slsa-framework/slsa-verifier-installer@v1.3.0 +uses: slsa-framework/slsa-verifier-installer@v2.0.1 ``` -See https://github.com/slsa-framework/slsa-verifier/releases for the list of available `slsa-verifier` releases. - -For a full example workflow, see [../../.github/workflows/pre-submit.actions.yml](https://github.com/slsa-framework/slsa-verifier/.github/workflows/pre-submit.actions.yml). +See https://github.com/slsa-framework/slsa-verifier/releases for the list of available `slsa-verifier` releases. Only versions greater or equal to 2.0.1 are supported. This action requires using GitHub-provided Linux runners. diff --git a/verifiers/internal/gcb/provenance.go b/verifiers/internal/gcb/provenance.go index a01264d..823524b 100644 --- a/verifiers/internal/gcb/provenance.go +++ b/verifiers/internal/gcb/provenance.go @@ -349,6 +349,9 @@ func (p *Provenance) VerifySourceURI(expectedSourceURI string, builderID utils.T return fmt.Errorf("%w: no materials", serrors.ErrorInvalidDssePayload) } uri := materials[0].URI + // NOTE: the material URI did not contain 'git+' for GCB versions <= v0.3. + // A change occurred sometimes in v0.3 witout version bump. + // Versions >= 0.3 contain the prefix (https://github.com/slsa-framework/slsa-verifier/pull/519). uri = strings.TrimPrefix(uri, "git+") // It is possible that GCS builds at level 2 use GCS sources, prefixed by gs://. diff --git a/verifiers/internal/gha/provenance.go b/verifiers/internal/gha/provenance.go index e4585e9..ebbe05a 100644 --- a/verifiers/internal/gha/provenance.go +++ b/verifiers/internal/gha/provenance.go @@ -71,7 +71,7 @@ func asURI(s string) string { } // Verify source URI in provenance statement. -func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string, verifyMaterials bool) error { +func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string, allowNoMaterialRef bool) error { source := asURI(expectedSourceURI) // We expect github.com URIs only. @@ -85,7 +85,7 @@ func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string, v if err != nil { return err } - configURI, err := sourceFromURI(fullConfigURI) + configURI, err := sourceFromURI(fullConfigURI, false) if err != nil { return err } @@ -95,15 +95,11 @@ func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string, v } // Verify source from material section. - // TODO(#492): disable this option. - if !verifyMaterials { - return nil - } materialSourceURI, err := prov.SourceURI() if err != nil { return err } - materialURI, err := sourceFromURI(materialSourceURI) + materialURI, err := sourceFromURI(materialSourceURI, allowNoMaterialRef) if err != nil { return err } @@ -114,6 +110,12 @@ func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string, v // Last, verify that both fields match. // We use the full URI to match on the tag as well. + if allowNoMaterialRef && len(strings.Split(materialSourceURI, "@")) == 1 { + // NOTE: this is an exception for npm packages built before GA, + // see https://github.com/slsa-framework/slsa-verifier/issues/492. + // We don't need to compare the ref since materialSourceURI does not contain it. + return nil + } if fullConfigURI != materialSourceURI { return fmt.Errorf("%w: material and config URIs do not match: '%s' != '%s'", serrors.ErrorInvalidDssePayload, @@ -123,13 +125,19 @@ func verifySourceURI(prov slsaprovenance.Provenance, expectedSourceURI string, v return nil } -func sourceFromURI(uri string) (string, error) { +// sourceFromURI retrieves the source repository given a repository URI with ref. +// +// NOTE: `allowNoRef` is to allow for verification of npm packages +// generated before GA. Their provenance did not have a ref, +// see https://github.com/slsa-framework/slsa-verifier/issues/492. +// `allowNoRef` should be set to `false` for all other cases. +func sourceFromURI(uri string, allowNoRef bool) (string, error) { if uri == "" { return "", fmt.Errorf("%w: empty uri", serrors.ErrorMalformedURI) } - r := strings.SplitN(uri, "@", 2) - if len(r) < 2 { + r := strings.Split(uri, "@") + if len(r) < 2 && !allowNoRef { return "", fmt.Errorf("%w: %s", serrors.ErrorMalformedURI, uri) } @@ -217,7 +225,7 @@ func VerifyNpmPackageProvenance(env *dsselib.Envelope, provenanceOpts *options.P } // NOTE: for the non trusted builders, the information may be forgeable. // Also, the GitHub context is not recorded for the default builder. - return VerifyProvenanceCommonOptions(prov, provenanceOpts, false) + return VerifyProvenanceCommonOptions(prov, provenanceOpts, true) } func VerifyProvenance(env *dsselib.Envelope, provenanceOpts *options.ProvenanceOpts, @@ -234,14 +242,14 @@ func VerifyProvenance(env *dsselib.Envelope, provenanceOpts *options.ProvenanceO return err } - return VerifyProvenanceCommonOptions(prov, provenanceOpts, true) + return VerifyProvenanceCommonOptions(prov, provenanceOpts, false) } func VerifyProvenanceCommonOptions(prov slsaprovenance.Provenance, provenanceOpts *options.ProvenanceOpts, - verifyMaterials bool, + allowNoMaterialRef bool, ) error { // Verify source. - if err := verifySourceURI(prov, provenanceOpts.ExpectedSourceURI, verifyMaterials); err != nil { + if err := verifySourceURI(prov, provenanceOpts.ExpectedSourceURI, allowNoMaterialRef); err != nil { return err } diff --git a/verifiers/internal/gha/provenance_test.go b/verifiers/internal/gha/provenance_test.go index 6057faa..a2d73b4 100644 --- a/verifiers/internal/gha/provenance_test.go +++ b/verifiers/internal/gha/provenance_test.go @@ -160,10 +160,11 @@ func Test_VerifyDigest(t *testing.T) { func Test_verifySourceURI(t *testing.T) { t.Parallel() tests := []struct { - name string - prov *intoto.ProvenanceStatement - sourceURI string - expected error + name string + prov *intoto.ProvenanceStatement + sourceURI string + allowNoMaterialRef bool + expected error // v1 provenance does not include materials skipv1 bool }{ @@ -288,6 +289,45 @@ func Test_verifySourceURI(t *testing.T) { }, sourceURI: "https://github.com/some/repo", }, + { + name: "match source no git no material ref", + prov: &intoto.ProvenanceStatement{ + Predicate: slsa02.ProvenancePredicate{ + Invocation: slsa02.ProvenanceInvocation{ + ConfigSource: slsa02.ConfigSource{ + URI: "git+https://github.com/some/repo@v1.2.3", + }, + }, + Materials: []slsacommon.ProvenanceMaterial{ + { + URI: "git+https://github.com/some/repo", + }, + }, + }, + }, + allowNoMaterialRef: true, + sourceURI: "https://github.com/some/repo", + }, + { + name: "match source no git no material ref ref not allowed", + prov: &intoto.ProvenanceStatement{ + Predicate: slsa02.ProvenancePredicate{ + Invocation: slsa02.ProvenanceInvocation{ + ConfigSource: slsa02.ConfigSource{ + URI: "git+https://github.com/some/repo@v1.2.3", + }, + }, + Materials: []slsacommon.ProvenanceMaterial{ + { + URI: "git+https://github.com/some/repo", + }, + }, + }, + }, + sourceURI: "https://github.com/some/repo", + expected: serrors.ErrorMalformedURI, + skipv1: true, + }, { name: "match source no git+https", prov: &intoto.ProvenanceStatement{ @@ -412,7 +452,7 @@ func Test_verifySourceURI(t *testing.T) { ProvenanceStatement: tt.prov, } - err := verifySourceURI(prov02, tt.sourceURI, true) + err := verifySourceURI(prov02, tt.sourceURI, tt.allowNoMaterialRef) if !errCmp(err, tt.expected) { t.Errorf(cmp.Diff(err, tt.expected)) } @@ -433,7 +473,7 @@ func Test_verifySourceURI(t *testing.T) { }, }, } - err = verifySourceURI(prov1, tt.sourceURI, true) + err = verifySourceURI(prov1, tt.sourceURI, tt.allowNoMaterialRef) if !errCmp(err, tt.expected) { t.Errorf(cmp.Diff(err, tt.expected)) }