mirror of
https://github.com/slsa-framework/slsa-verifier.git
synced 2026-02-14 09:39:54 +00:00
feat: verify provenance for bcr modules produced by trusted reusable workflows (#840)
@fweikert these are the changes I think might be needed to get this to work (it's somewhat hacky, I'm not sure I've fully covered what's needed). @ramonpetgrave64 is this kinda what's needed? This now adds the `verify-github-attestation` sub command. Use this instead of `verify-artifact`. --------- Signed-off-by: Appu Goundan <appu@google.com> Signed-off-by: Appu <appu@google.com> Co-authored-by: Ramon Petgrave <32398091+ramonpetgrave64@users.noreply.github.com>
This commit is contained in:
@@ -35,6 +35,7 @@ For more information on SLSA, visit https://slsa.dev`,
|
||||
}
|
||||
c.AddCommand(version.Version())
|
||||
c.AddCommand(verifyArtifactCmd())
|
||||
c.AddCommand(verifyGithubAttestation())
|
||||
c.AddCommand(verifyImageCmd())
|
||||
c.AddCommand(verifyNpmPackageCmd())
|
||||
c.AddCommand(verifyVSACmd())
|
||||
|
||||
@@ -1510,6 +1510,75 @@ func Test_runVerifyGHAContainerBased(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_runVerifyGithubAttestation(t *testing.T) {
|
||||
t.Parallel()
|
||||
os.Setenv("SLSA_VERIFIER_EXPERIMENTAL", "1")
|
||||
|
||||
bcrReleaserBuilderID := "https://github.com/bazel-contrib/.github/.github/workflows/release_ruleset.yaml"
|
||||
bcrPublisherBuilderID := "https://github.com/bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
artifact string
|
||||
source string
|
||||
builderID string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "module.bazel using publishing builder",
|
||||
artifact: "MODULE.bazel",
|
||||
source: "github.com/aspect-build/rules_lint",
|
||||
builderID: bcrPublisherBuilderID,
|
||||
},
|
||||
{
|
||||
name: "source archive using release builder",
|
||||
artifact: "rules_lint-v1.3.1.tar.gz",
|
||||
source: "github.com/aspect-build/rules_lint",
|
||||
builderID: bcrReleaserBuilderID,
|
||||
},
|
||||
{
|
||||
name: "module.bazel wrong signer",
|
||||
artifact: "MODULE-wrong-signer.bazel",
|
||||
source: "github.com/aspect-build/rules_lint",
|
||||
builderID: bcrPublisherBuilderID,
|
||||
err: serrors.ErrorUntrustedReusableWorkflow,
|
||||
},
|
||||
{
|
||||
name: "module.bazel no builder id",
|
||||
artifact: "MODULE.bazel",
|
||||
source: "github.com/aspect-build/rules_lint",
|
||||
err: serrors.ErrorUntrustedReusableWorkflow,
|
||||
},
|
||||
{
|
||||
name: "source archive no builder id",
|
||||
artifact: "rules_lint-v1.3.1.tar.gz",
|
||||
source: "github.com/aspect-build/rules_lint",
|
||||
err: serrors.ErrorUntrustedReusableWorkflow,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
artifactPath := filepath.Clean(filepath.Join(TEST_DIR, "bcr", tt.artifact))
|
||||
// we treat these single entry *.intoto.jsonl bundles as single attestations
|
||||
attestationPath := fmt.Sprintf("%s.intoto.jsonl", artifactPath)
|
||||
cmd := verify.VerifyGithubAttestationCommand{
|
||||
AttestationPath: attestationPath,
|
||||
BuilderID: &tt.builderID,
|
||||
SourceURI: tt.source,
|
||||
}
|
||||
|
||||
_, err := cmd.Exec(context.Background(), artifactPath)
|
||||
if !errCmp(tt.err, err) {
|
||||
t.Errorf("unexpected error (-want +got):\n%s", cmp.Diff(err, tt.err, cmpopts.EquateErrors()))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_runVerifyNpmPackage(t *testing.T) {
|
||||
// We cannot use t.Setenv due to parallelized tests.
|
||||
os.Setenv("SLSA_VERIFIER_EXPERIMENTAL", "1")
|
||||
@@ -2063,3 +2132,15 @@ func Test_runVerifyVSA(t *testing.T) {
|
||||
func pointerTo[K any](object K) *K {
|
||||
return &object
|
||||
}
|
||||
|
||||
func unwrapFull(t *testing.T, err error) error {
|
||||
for err != nil {
|
||||
t.Logf("%v", err)
|
||||
unwrapped := errors.Unwrap(err)
|
||||
if unwrapped == nil {
|
||||
return err
|
||||
}
|
||||
err = unwrapped
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
34
cli/slsa-verifier/testdata/bcr/MODULE-wrong-signer.bazel
vendored
Normal file
34
cli/slsa-verifier/testdata/bcr/MODULE-wrong-signer.bazel
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
"Bazel dependencies"
|
||||
|
||||
module(
|
||||
name = "aspect_rules_lint",
|
||||
version = "1.3.1",
|
||||
compatibility_level = 1,
|
||||
)
|
||||
|
||||
bazel_dep(name = "aspect_bazel_lib", version = "2.7.7")
|
||||
|
||||
# Needed in the root because we use js_lib_helpers in our aspect impl
|
||||
# Minimum version needs 'chore: bump bazel-lib to 2.0 by @alexeagle in #1311'
|
||||
# to allow users on bazel-lib 2.0
|
||||
bazel_dep(name = "aspect_rules_js", version = "1.40.0")
|
||||
bazel_dep(name = "bazel_features", version = "1.0.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.4.2")
|
||||
bazel_dep(name = "platforms", version = "0.0.7")
|
||||
bazel_dep(name = "rules_multirun", version = "0.9.0")
|
||||
bazel_dep(name = "rules_multitool", version = "0.4.0")
|
||||
bazel_dep(name = "rules_diff", version = "1.0.0")
|
||||
|
||||
# Needed in the root because we dereference ProtoInfo in our aspect impl
|
||||
bazel_dep(name = "rules_proto", version = "6.0.0")
|
||||
|
||||
# Needed in the root because we dereference the toolchain in our aspect impl
|
||||
bazel_dep(name = "rules_buf", version = "0.1.1")
|
||||
bazel_dep(name = "toolchains_protoc", version = "0.2.1")
|
||||
|
||||
multitool = use_extension("@rules_multitool//multitool:extension.bzl", "multitool")
|
||||
multitool.hub(lockfile = "//format:multitool.lock.json")
|
||||
multitool.hub(lockfile = "//lint:multitool.lock.json")
|
||||
use_repo(multitool, "multitool")
|
||||
|
||||
bazel_dep(name = "stardoc", version = "0.7.0", dev_dependency = True, repo_name = "io_bazel_stardoc")
|
||||
1
cli/slsa-verifier/testdata/bcr/MODULE-wrong-signer.bazel.intoto.jsonl
vendored
Normal file
1
cli/slsa-verifier/testdata/bcr/MODULE-wrong-signer.bazel.intoto.jsonl
vendored
Normal file
File diff suppressed because one or more lines are too long
34
cli/slsa-verifier/testdata/bcr/MODULE.bazel
vendored
Normal file
34
cli/slsa-verifier/testdata/bcr/MODULE.bazel
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
"Bazel dependencies"
|
||||
|
||||
module(
|
||||
name = "aspect_rules_lint",
|
||||
version = "1.3.1",
|
||||
compatibility_level = 1,
|
||||
)
|
||||
|
||||
bazel_dep(name = "aspect_bazel_lib", version = "2.7.7")
|
||||
|
||||
# Needed in the root because we use js_lib_helpers in our aspect impl
|
||||
# Minimum version needs 'chore: bump bazel-lib to 2.0 by @alexeagle in #1311'
|
||||
# to allow users on bazel-lib 2.0
|
||||
bazel_dep(name = "aspect_rules_js", version = "1.40.0")
|
||||
bazel_dep(name = "bazel_features", version = "1.0.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.4.2")
|
||||
bazel_dep(name = "platforms", version = "0.0.7")
|
||||
bazel_dep(name = "rules_multirun", version = "0.9.0")
|
||||
bazel_dep(name = "rules_multitool", version = "0.4.0")
|
||||
bazel_dep(name = "rules_diff", version = "1.0.0")
|
||||
|
||||
# Needed in the root because we dereference ProtoInfo in our aspect impl
|
||||
bazel_dep(name = "rules_proto", version = "6.0.0")
|
||||
|
||||
# Needed in the root because we dereference the toolchain in our aspect impl
|
||||
bazel_dep(name = "rules_buf", version = "0.1.1")
|
||||
bazel_dep(name = "toolchains_protoc", version = "0.2.1")
|
||||
|
||||
multitool = use_extension("@rules_multitool//multitool:extension.bzl", "multitool")
|
||||
multitool.hub(lockfile = "//format:multitool.lock.json")
|
||||
multitool.hub(lockfile = "//lint:multitool.lock.json")
|
||||
use_repo(multitool, "multitool")
|
||||
|
||||
bazel_dep(name = "stardoc", version = "0.7.0", dev_dependency = True, repo_name = "io_bazel_stardoc")
|
||||
1
cli/slsa-verifier/testdata/bcr/MODULE.bazel.intoto.jsonl
vendored
Normal file
1
cli/slsa-verifier/testdata/bcr/MODULE.bazel.intoto.jsonl
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
cli/slsa-verifier/testdata/bcr/rules_lint-v1.3.1.tar.gz
vendored
Normal file
BIN
cli/slsa-verifier/testdata/bcr/rules_lint-v1.3.1.tar.gz
vendored
Normal file
Binary file not shown.
1
cli/slsa-verifier/testdata/bcr/rules_lint-v1.3.1.tar.gz.intoto.jsonl
vendored
Normal file
1
cli/slsa-verifier/testdata/bcr/rules_lint-v1.3.1.tar.gz.intoto.jsonl
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -185,6 +185,38 @@ func verifyNpmPackageCmd() *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func verifyGithubAttestation() *cobra.Command {
|
||||
o := &verify.VerifyGithubAttestationOptions{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "verify-github-attestation [flags] module-file",
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 {
|
||||
return errors.New("expects a single path to an module file")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Short: "Verifies SLSA provenance for a github attestation [experimental]",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
v := verify.VerifyGithubAttestationCommand{
|
||||
AttestationPath: o.AttestationPath,
|
||||
SourceURI: o.SourceURI,
|
||||
PrintAttestation: o.PrintAttestation,
|
||||
BuilderID: &o.BuilderID,
|
||||
}
|
||||
if _, err := v.Exec(cmd.Context(), args[0]); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s: %v\n", FAILURE, err)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", SUCCESS)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
o.AddFlags(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func verifyVSACmd() *cobra.Command {
|
||||
o := &verify.VerifyVSAOptions{}
|
||||
|
||||
|
||||
@@ -127,6 +127,36 @@ func (o *VerifyNpmOptions) AddFlags(cmd *cobra.Command) {
|
||||
cmd.MarkFlagsMutuallyExclusive("source-versioned-tag", "source-tag")
|
||||
}
|
||||
|
||||
// VerifyGithubAttestationOptions is the top-level options for the `verify-github-attestation` command.
|
||||
type VerifyGithubAttestationOptions struct {
|
||||
SourceURI string
|
||||
BuilderID string
|
||||
AttestationPath string
|
||||
PrintAttestation bool
|
||||
}
|
||||
|
||||
var _ Interface = (*VerifyGithubAttestationOptions)(nil)
|
||||
|
||||
// AddFlags implements Interface.
|
||||
func (o *VerifyGithubAttestationOptions) AddFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().StringVar(&o.BuilderID, "builder-id", "", "the unique builder ID who created the provenance")
|
||||
|
||||
/* Source options */
|
||||
cmd.Flags().StringVar(&o.SourceURI, "source-uri", "",
|
||||
"expected source repository that should have produced the binary, e.g. github.com/some/repo")
|
||||
|
||||
/* Other options */
|
||||
cmd.Flags().StringVar(&o.AttestationPath, "attestation-path", "",
|
||||
"path to an attestation file")
|
||||
|
||||
cmd.Flags().BoolVar(&o.PrintAttestation, "print-attestation", false,
|
||||
"[optional] print the verified attestation to stdout")
|
||||
|
||||
cmd.MarkFlagRequired("source-uri")
|
||||
cmd.MarkFlagRequired("attestation-path")
|
||||
cmd.MarkFlagRequired("builder-id")
|
||||
}
|
||||
|
||||
// VerifyVSAOptions is the top-level options for the `verifyVSA` command.
|
||||
type VerifyVSAOptions struct {
|
||||
SubjectDigests []string
|
||||
|
||||
78
cli/slsa-verifier/verify/verify_github_attestation.go
Normal file
78
cli/slsa-verifier/verify/verify_github_attestation.go
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2025 SLSA Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package verify
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/slsa-framework/slsa-verifier/v2/options"
|
||||
"github.com/slsa-framework/slsa-verifier/v2/verifiers"
|
||||
"github.com/slsa-framework/slsa-verifier/v2/verifiers/utils"
|
||||
)
|
||||
|
||||
type VerifyGithubAttestationCommand struct {
|
||||
AttestationPath string
|
||||
BuilderID *string
|
||||
SourceURI string
|
||||
BuildWorkflowInputs map[string]string
|
||||
PrintAttestation bool
|
||||
}
|
||||
|
||||
func (c *VerifyGithubAttestationCommand) Exec(ctx context.Context, artifact string) (*utils.TrustedBuilderID, error) {
|
||||
if !options.ExperimentalEnabled() {
|
||||
err := errors.New("feature support is only provided in SLSA_VERIFIER_EXPERIMENTAL mode")
|
||||
fmt.Fprintf(os.Stderr, "Verifying github attestation: FAILED: %v\n\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
artifactHash, err := computeFileHash(artifact, sha256.New())
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Verifying artifact %s: FAILED: %v\n\n", artifact, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
provenanceOpts := &options.ProvenanceOpts{
|
||||
ExpectedSourceURI: c.SourceURI,
|
||||
ExpectedDigest: artifactHash,
|
||||
ExpectedWorkflowInputs: c.BuildWorkflowInputs,
|
||||
}
|
||||
|
||||
builderOpts := &options.BuilderOpts{
|
||||
ExpectedID: c.BuilderID,
|
||||
}
|
||||
|
||||
attestation, err := os.ReadFile(c.AttestationPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Verifying artifact %s: FAILED: %v\n\n", artifact, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
verifiedAttestation, outBuilderID, err := verifiers.VerifyGithubAttestation(ctx, attestation, provenanceOpts, builderOpts)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Verifying artifact %s: FAILED: %v\n\n", artifact, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.PrintAttestation {
|
||||
fmt.Fprintf(os.Stdout, "%s\n", string(verifiedAttestation))
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "Verifying artifact %s: PASSED\n\n", artifact)
|
||||
return outBuilderID, nil
|
||||
}
|
||||
@@ -29,6 +29,13 @@ type SLSAVerifier interface {
|
||||
builderOpts *options.BuilderOpts,
|
||||
) ([]byte, *utils.TrustedBuilderID, error)
|
||||
|
||||
// VerifyGithubAttestation verifies provenance for a Github Attestations.
|
||||
VerifyGithubAttestation(ctx context.Context,
|
||||
attestation []byte,
|
||||
provenanceOpts *options.ProvenanceOpts,
|
||||
builderOpts *options.BuilderOpts,
|
||||
) ([]byte, *utils.TrustedBuilderID, error)
|
||||
|
||||
VerifyNpmPackage(ctx context.Context,
|
||||
attestations []byte, tarballHash string,
|
||||
provenanceOpts *options.ProvenanceOpts,
|
||||
|
||||
@@ -39,6 +39,15 @@ func (v *GCBVerifier) VerifyArtifact(ctx context.Context,
|
||||
return nil, nil, serrors.ErrorNotSupported
|
||||
}
|
||||
|
||||
// VerifyGithubAttestation verifies provenance for a Github Attestations.
|
||||
func (v *GCBVerifier) VerifyGithubAttestation(ctx context.Context,
|
||||
attestation []byte,
|
||||
provenanceOpts *options.ProvenanceOpts,
|
||||
builderOpts *options.BuilderOpts,
|
||||
) ([]byte, *utils.TrustedBuilderID, error) {
|
||||
return nil, nil, serrors.ErrorNotSupported
|
||||
}
|
||||
|
||||
// VerifyNpmPackage verifies an npm package tarball.
|
||||
func (v *GCBVerifier) VerifyNpmPackage(ctx context.Context,
|
||||
attestations []byte, tarballHash string,
|
||||
|
||||
@@ -23,4 +23,9 @@ var (
|
||||
GenericDelegatorBuilderID = trustedBuilderRepository + "/.github/workflows/delegator_generic_slsa3.yml"
|
||||
// GenericLowPermsDelegatorBuilderID is the SLSA builder ID for the BYOB Generic Low-Permissions Delegated Builder.
|
||||
GenericLowPermsDelegatorBuilderID = trustedBuilderRepository + "/.github/workflows/delegator_lowperms-generic_slsa3.yml"
|
||||
|
||||
// BCRReleaserBuilderID is the bcr reusable workflow that generates github attestations for a ruleset release.
|
||||
BCRReleaserBuilderID = "https://github.com/bazel-contrib/.github/.github/workflows/release_ruleset.yaml"
|
||||
// BCRPublisherBuilderID is the bcr reusable workflow that generates github attestations for BCR repository metadata.
|
||||
BCRPublisherBuilderID = "https://github.com/bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml"
|
||||
)
|
||||
|
||||
@@ -24,6 +24,8 @@ var (
|
||||
|
||||
// NpmCLIGithubActionsBuildTypeV1 is the buildType for provenance by the npm cli from GitHub Actions.
|
||||
NpmCLIGithubActionsBuildTypeV1 = "https://slsa-framework.github.io/github-actions-buildtypes/workflow/v1"
|
||||
|
||||
GithubActionsBuildTypeV1 = "https://actions.github.io/buildtypes/workflow/v1"
|
||||
)
|
||||
|
||||
// Legacy buildTypes.
|
||||
|
||||
36
verifiers/internal/gha/slsaprovenance/v1.0/github_attest.go
Normal file
36
verifiers/internal/gha/slsaprovenance/v1.0/github_attest.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
|
||||
)
|
||||
|
||||
// GithubAttestBuildType is the build type for the github attest based builder.
|
||||
var GithubAttestBuildType = "https://actions.github.io/buildtypes/workflow/v1"
|
||||
|
||||
// GithubAttestProvenance is provenance generated by an action using github's attest action.
|
||||
type GithubAttestProvenance struct {
|
||||
*provenanceV1
|
||||
}
|
||||
|
||||
func (p *GithubAttestProvenance) TriggerURI() (string, error) {
|
||||
externalParams, err := p.getExternalParameters()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
workflow, ok := externalParams["workflow"].(map[string]interface{})
|
||||
if !ok {
|
||||
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidFormat, "workflow parameters")
|
||||
}
|
||||
repository, ok := workflow["repository"].(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidFormat, "workflow parameters: repository")
|
||||
}
|
||||
ref, ok := workflow["ref"].(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidFormat, "workflow parameters: ref")
|
||||
}
|
||||
uri := fmt.Sprintf("git+%s@%s", repository, ref)
|
||||
return uri, nil
|
||||
}
|
||||
@@ -50,12 +50,22 @@ func newNpmCLIGithubActions(a *Attestation) iface.Provenance {
|
||||
}
|
||||
}
|
||||
|
||||
func newGithubAttest(a *Attestation) iface.Provenance {
|
||||
return &GithubAttestProvenance{
|
||||
provenanceV1: &provenanceV1{
|
||||
prov: a,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// buildTypeMap is a map of builder IDs to supported buildTypes.
|
||||
var buildTypeMap = map[string]map[string]provFunc{
|
||||
common.GenericDelegatorBuilderID: {common.BYOBBuildTypeV0: newBYOB},
|
||||
common.GenericLowPermsDelegatorBuilderID: {common.BYOBBuildTypeV0: newBYOB},
|
||||
common.ContainerBasedBuilderID: {common.ContainerBasedBuildTypeV01Draft: newContainerBased},
|
||||
common.NpmCLIHostedBuilderID: {common.NpmCLIGithubActionsBuildTypeV1: newNpmCLIGithubActions},
|
||||
common.BCRReleaserBuilderID: {common.GithubActionsBuildTypeV1: newGithubAttest},
|
||||
common.BCRPublisherBuilderID: {common.GithubActionsBuildTypeV1: newGithubAttest},
|
||||
}
|
||||
|
||||
// New returns a new Provenance object based on the payload.
|
||||
|
||||
@@ -242,6 +242,31 @@ func (v *GHAVerifier) VerifyArtifact(ctx context.Context,
|
||||
utils.MergeMaps(defaultArtifactTrustedReusableWorkflows, defaultBYOBReusableWorkflows))
|
||||
}
|
||||
|
||||
// VerifyGithubAttestation verifies provenance for a Github Attestations.
|
||||
func (v *GHAVerifier) VerifyGithubAttestation(ctx context.Context,
|
||||
attestation []byte,
|
||||
provenanceOpts *options.ProvenanceOpts,
|
||||
builderOpts *options.BuilderOpts,
|
||||
) ([]byte, *utils.TrustedBuilderID, error) {
|
||||
if !IsSigstoreBundle(attestation) {
|
||||
return nil, nil, errors.New("github attestations must be signed by Sigstore")
|
||||
}
|
||||
|
||||
trustedRoot, err := utils.GetSigstoreTrustedRoot()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
/* Verify signature on the intoto attestation. */
|
||||
signedAtt, err := VerifyProvenanceBundle(ctx, attestation, trustedRoot)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return verifyEnvAndCert(signedAtt.Envelope, signedAtt.SigningCert,
|
||||
provenanceOpts, builderOpts, map[string]bool{})
|
||||
}
|
||||
|
||||
// VerifyImage verifies provenance for an OCI image.
|
||||
func (v *GHAVerifier) VerifyImage(ctx context.Context,
|
||||
provenance []byte, artifactImage string, provenanceOpts *options.ProvenanceOpts,
|
||||
|
||||
@@ -62,6 +62,20 @@ func VerifyArtifact(ctx context.Context,
|
||||
provenanceOpts, builderOpts)
|
||||
}
|
||||
|
||||
func VerifyGithubAttestation(ctx context.Context,
|
||||
provenance []byte,
|
||||
provenanceOpts *options.ProvenanceOpts,
|
||||
builderOpts *options.BuilderOpts,
|
||||
) ([]byte, *utils.TrustedBuilderID, error) {
|
||||
verifier, err := getVerifier(builderOpts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return verifier.VerifyGithubAttestation(ctx, provenance,
|
||||
provenanceOpts, builderOpts)
|
||||
}
|
||||
|
||||
func VerifyNpmPackage(ctx context.Context,
|
||||
attestations []byte, tarballHash string,
|
||||
provenanceOpts *options.ProvenanceOpts,
|
||||
|
||||
Reference in New Issue
Block a user