feat: add slsa v1?draft provenance experimental support (#470)

* feat: add slsa v1?draft provenance support

Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
This commit is contained in:
asraa
2023-02-09 11:21:15 -06:00
committed by GitHub
parent 69da812e1c
commit 239c4489ce
19 changed files with 506 additions and 234 deletions

View File

@@ -16,7 +16,6 @@ func check(err error) {
}
}
//nolint:deadcode
func ExperimentalEnabled() bool {
return os.Getenv("SLSA_VERIFIER_EXPERIMENTAL") == "1"
}

View File

@@ -43,6 +43,7 @@ func verifyArtifactCmd() *cobra.Command {
Run: func(cmd *cobra.Command, args []string) {
v := verify.VerifyArtifactCommand{
ProvenancePath: o.ProvenancePath,
BundlePath: o.BundlePath,
SourceURI: o.SourceURI,
PrintProvenance: o.PrintProvenance,
BuildWorkflowInputs: o.BuildWorkflowInputs.AsMap(),
@@ -60,6 +61,21 @@ func verifyArtifactCmd() *cobra.Command {
v.BuilderID = &o.BuilderID
}
// In experimental mode, we allow either provenance or bundle path, but exactly
// one must be set. We already check to ensure that they are mutually exclusive.
if ExperimentalEnabled() {
if !(cmd.Flags().Changed("provenance-path") ||
cmd.Flags().Changed("bundle-path")) {
fmt.Fprintf(os.Stderr, "%s\n%s", cmd.UsageString(),
"exactly one of --provenance-path or --bundle-path must be supplied")
os.Exit(1)
}
} else if !cmd.Flags().Changed("provenance-path") {
// --provenance-path must be set.
fmt.Fprintf(os.Stderr, "%s\n%s\n", cmd.UsageString(), "--provenance-path must be supplied")
os.Exit(1)
}
if _, err := v.Exec(cmd.Context(), args); err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", FAILURE, err)
os.Exit(1)
@@ -70,7 +86,6 @@ func verifyArtifactCmd() *cobra.Command {
}
o.AddFlags(cmd)
cmd.MarkFlagRequired("provenance-path")
return cmd
}

View File

@@ -39,6 +39,7 @@ type VerifyOptions struct {
BuilderID string
/* Other */
ProvenancePath string
BundlePath string
PrintProvenance bool
}
@@ -67,11 +68,17 @@ func (o *VerifyOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.ProvenancePath, "provenance-path", "",
"path to a provenance file")
cmd.Flags().StringVar(&o.BundlePath, "bundle-path", "",
"path to a Sigstore provenance bundle file containing offline information.")
cmd.Flags().BoolVar(&o.PrintProvenance, "print-provenance", false,
"[optional] print the verified provenance to stdout")
cmd.MarkFlagRequired("source-uri")
cmd.MarkFlagsMutuallyExclusive("source-versioned-tag", "source-tag")
// Enforce exactly one of --provenance-path and --bundle-path.
cmd.MarkFlagsMutuallyExclusive("provenance-path", "bundle-path")
}
type workflowInputs struct {

View File

@@ -30,6 +30,7 @@ import (
// Note: nil branch, tag, version-tag and builder-id means we ignore them during verification.
type VerifyArtifactCommand struct {
ProvenancePath string
BundlePath string
BuilderID *string
SourceURI string
SourceBranch *string
@@ -62,10 +63,20 @@ func (c *VerifyArtifactCommand) Exec(ctx context.Context, artifacts []string) (*
ExpectedID: c.BuilderID,
}
provenance, err := os.ReadFile(c.ProvenancePath)
if err != nil {
fmt.Fprintf(os.Stderr, "Verifying artifact %s: FAILED: %v\n\n", artifact, err)
return nil, err
var provenance []byte
if c.ProvenancePath != "" {
provenance, err = os.ReadFile(c.ProvenancePath)
if err != nil {
fmt.Fprintf(os.Stderr, "Verifying artifact %s: FAILED: %v\n\n", artifact, err)
return nil, err
}
} else {
bundle, err := os.ReadFile(c.BundlePath)
if err != nil {
fmt.Fprintf(os.Stderr, "Verifying artifact %s: FAILED: %v\n\n", artifact, err)
return nil, err
}
provenanceOpts.ProvenanceBundle = bundle
}
verifiedProvenance, outBuilderID, err := verifiers.VerifyArtifact(ctx, provenance, artifactHash, provenanceOpts, builderOpts)

29
go.mod
View File

@@ -7,7 +7,7 @@ require (
github.com/go-openapi/runtime v0.25.0
github.com/google/go-cmp v0.5.9
github.com/google/trillian v1.5.1-0.20220819043421-0a389c4bb8d9 // indirect
github.com/in-toto/in-toto-golang v0.6.0
github.com/in-toto/in-toto-golang v0.6.1-0.20230207212643-96dcb8c596fb
github.com/secure-systems-lab/go-securesystemslib v0.4.0
github.com/sigstore/rekor v1.0.1
github.com/sigstore/sigstore v1.5.1
@@ -23,21 +23,24 @@ require (
github.com/slsa-framework/slsa-github-generator v1.4.0
github.com/spf13/cobra v1.6.1
github.com/transparency-dev/merkle v0.0.1
golang.org/x/mod v0.7.0
golang.org/x/mod v0.8.0
sigs.k8s.io/release-utils v0.7.3
)
require (
filippo.io/edwards25519 v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/digitorus/pkcs7 v0.0.0-20221212123742-001c36b64ec3 // indirect
github.com/digitorus/timestamp v0.0.0-20221019182153-ef3b63b79b31 // indirect
github.com/sigstore/timestamp-authority v0.2.1 // indirect
github.com/spiffe/go-spiffe/v2 v2.1.2 // indirect
github.com/zeebo/errs v1.3.0 // indirect
go.step.sm/crypto v0.23.1 // indirect
)
require (
bitbucket.org/creachadair/shell v0.0.7 // indirect
cloud.google.com/go/compute v1.14.0 // indirect
cloud.google.com/go/compute v1.15.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0 // indirect
github.com/Azure/azure-sdk-for-go v67.3.0+incompatible // indirect
@@ -82,12 +85,12 @@ require (
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chrismellard/docker-credential-acr-env v0.0.0-20220119192733-fe33c00cee21 // indirect
github.com/clbanning/mxj/v2 v2.5.6 // indirect
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 // indirect
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect
github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b // indirect
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
github.com/containerd/stargz-snapshotter/estargz v0.12.1 // indirect
github.com/coreos/go-oidc/v3 v3.5.0 // indirect
@@ -102,8 +105,8 @@ require (
github.com/docker/docker v20.10.21+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect
github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect
github.com/envoyproxy/go-control-plane v0.10.3 // indirect
github.com/envoyproxy/protoc-gen-validate v0.9.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/fullstorydev/grpcurl v1.8.7 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
@@ -144,7 +147,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b // indirect
github.com/jhump/protoreflect v1.14.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
@@ -234,14 +237,14 @@ require (
golang.org/x/net v0.5.0 // indirect
golang.org/x/oauth2 v0.4.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.5.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa // indirect
google.golang.org/grpc v1.52.3 // indirect
google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 // indirect
google.golang.org/grpc v1.53.0 // indirect
google.golang.org/protobuf v1.28.1
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect

41
go.sum
View File

@@ -56,6 +56,8 @@ cloud.google.com/go/compute v1.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWow
cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE=
cloud.google.com/go/compute v1.14.0 h1:hfm2+FfxVmnRlh6LpB7cg1ZNU+5edAHmW679JePztk0=
cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo=
cloud.google.com/go/compute v1.15.1 h1:7UGq3QknM33pw5xATlpzeoomNxsacIVvTqTTvbfajmE=
cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA=
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/compute/metadata v0.2.2 h1:aWKAjYaBaOSrpKl57+jnS/3fJRQnxL7TvR/u1VVbt6k=
cloud.google.com/go/compute/metadata v0.2.2/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
@@ -156,6 +158,8 @@ github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@@ -366,6 +370,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
@@ -373,6 +379,8 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chrismellard/docker-credential-acr-env v0.0.0-20220119192733-fe33c00cee21 h1:XlpL9EHrPOBJMLDDOf35/G4t5rGAFNNAZQ3cDcWavtc=
github.com/chrismellard/docker-credential-acr-env v0.0.0-20220119192733-fe33c00cee21/go.mod h1:Zlre/PVxuSI9y6/UV4NwGixQ48RHQDSPiUkofr6rbMU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -387,6 +395,8 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
@@ -394,6 +404,9 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 h1:KwaoQzs/WeUxxJqiJsZ4euOly1Az/IgZXXSxlD/UBNk=
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b h1:ACGZRIr7HsgBKHsueQ1yM4WaVaXh21ynwqsF8M8tXhA=
github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
@@ -492,10 +505,15 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/go-control-plane v0.10.3 h1:xdCVXxEe0Y3FQith+0cj2irwZudqGYvecuLB1HtdexY=
github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2 h1:JiO+kJTpmYGjEodY7O1Zk8oZcNz1+f30UtwtXoFUPzE=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo=
github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY=
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
@@ -899,9 +917,15 @@ github.com/in-toto/in-toto-golang v0.5.0 h1:hb8bgwr0M2hGdDsLjkJ3ZqJ8JFLL/tgYdAxF
github.com/in-toto/in-toto-golang v0.5.0/go.mod h1:/Rq0IZHLV7Ku5gielPT4wPHJfH1GdHMCq8+WPxw8/BE=
github.com/in-toto/in-toto-golang v0.6.0 h1:1s7cyzb5zGyzKPLgFsi4sC0o3EA24HLKlne8BrnOrSc=
github.com/in-toto/in-toto-golang v0.6.0/go.mod h1:NaFLcsxtvZgbwQpyHwK8MlDXN9b+NuOMXqeIqxzfBoA=
github.com/in-toto/in-toto-golang v0.6.1-0.20230207163334-3493691c6d9c h1:d50sx5hkklYL5PkZrxtg4TAM1yfjykNw5p0AgDW2cq8=
github.com/in-toto/in-toto-golang v0.6.1-0.20230207163334-3493691c6d9c/go.mod h1:AoOsIJkpD8RHrZIAQxXqhGPm7M38IzT4JAdgPpf4OZc=
github.com/in-toto/in-toto-golang v0.6.1-0.20230207212643-96dcb8c596fb h1:lUoNEu/QPf8P52025Pk46e5godp1uRUzSJ3CQknuFdE=
github.com/in-toto/in-toto-golang v0.6.1-0.20230207212643-96dcb8c596fb/go.mod h1:AoOsIJkpD8RHrZIAQxXqhGPm7M38IzT4JAdgPpf4OZc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
@@ -990,6 +1014,7 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/linkedin/goavro v2.1.0+incompatible/go.mod h1:bBCwI2eGYpUI/4820s67MElg9tdeLbINjLjiM2xZFYM=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -1235,6 +1260,7 @@ github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XF
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -1349,6 +1375,8 @@ github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
github.com/spiffe/go-spiffe/v2 v2.1.2 h1:nfNwopOP7q0qsWU6AUASqmbtYViwHA6vuHyAtqFJtNc=
github.com/spiffe/go-spiffe/v2 v2.1.2/go.mod h1:cbQmFrxsOpbm5tWURAYip9ZK0dOSFeoFG3/5Ub9Hvy0=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
@@ -1447,6 +1475,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zalando/go-keyring v0.1.0/go.mod h1:RaxNwUITJaHVdQ0VC7pELPZ3tOWn13nr0gZMZEhpVU0=
github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs=
github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
@@ -1548,6 +1578,7 @@ go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48
go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ=
go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.opentelemetry.io/proto/otlp v0.16.0 h1:WHzDWdXUvbc5bG2ObdrGfaNpQz7ft7QN9HHmJlbiB1E=
go.opentelemetry.io/proto/otlp v0.16.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.step.sm/crypto v0.23.1 h1:Yr9vlzjGqIKVi88KcpZtEcNTcpDkt1nVR7tumW4h+CU=
@@ -1665,6 +1696,8 @@ golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1911,6 +1944,8 @@ golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -2031,6 +2066,7 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4=
golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -2190,6 +2226,7 @@ google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
@@ -2210,6 +2247,8 @@ google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqd
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa h1:qQPhfbPO23fwm/9lQr91L1u62Zo6cm+zI+slZT+uf+o=
google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/genproto v0.0.0-20230202175211-008b39050e57 h1:vArvWooPH749rNHpBGgVl+U9B9dATjiEhJzcWGlovNs=
google.golang.org/genproto v0.0.0-20230202175211-008b39050e57/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -2258,6 +2297,8 @@ google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk=
google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ=
google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=

View File

@@ -23,6 +23,9 @@ type ProvenanceOpts struct {
// ExpectedWorkflowInputs is a map of key=value inputs.
ExpectedWorkflowInputs map[string]string
// Bundle containing information to verify the provenance offline.
ProvenanceBundle []byte
}
// BuildOpts are the options for checking the builder.

View File

@@ -18,9 +18,11 @@ import (
serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
"github.com/slsa-framework/slsa-verifier/v2/options"
"github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance"
"github.com/slsa-framework/slsa-verifier/v2/verifiers/utils"
// Load provenance types.
_ "github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance/v0.2"
_ "github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance/v1.0"
)
// SignedAttestation contains a signed DSSE envelope
@@ -240,25 +242,14 @@ func VerifyProvenance(env *dsselib.Envelope, provenanceOpts *options.ProvenanceO
}
func VerifyWorkflowInputs(prov slsaprovenance.Provenance, inputs map[string]string) error {
// Verify it's a workflow_dispatch trigger.
triggerName, err := prov.GetStringFromEnvironment("github_event_name")
if err != nil {
return err
}
if triggerName != "workflow_dispatch" {
return fmt.Errorf("%w: expected 'workflow_dispatch' trigger, got %s",
serrors.ErrorMismatchWorkflowInputs, triggerName)
}
// Assume no nested level.
pyldInputs, err := prov.GetInputs()
pyldInputs, err := prov.GetWorkflowInputs()
if err != nil {
return err
}
// Verify all inputs.
for k, v := range inputs {
value, err := getAsString(pyldInputs, k)
value, err := utils.GetAsString(pyldInputs, k)
if err != nil {
return fmt.Errorf("%w: cannot retrieve value of '%s'", serrors.ErrorMismatchWorkflowInputs, k)
}
@@ -273,7 +264,7 @@ func VerifyWorkflowInputs(prov slsaprovenance.Provenance, inputs map[string]stri
}
func VerifyBranch(prov slsaprovenance.Provenance, expectedBranch string) error {
branch, err := getBranch(prov)
branch, err := prov.GetBranch()
if err != nil {
return err
}
@@ -287,7 +278,7 @@ func VerifyBranch(prov slsaprovenance.Provenance, expectedBranch string) error {
}
func VerifyTag(prov slsaprovenance.Provenance, expectedTag string) error {
tag, err := getTag(prov)
tag, err := prov.GetTag()
if err != nil {
return err
}
@@ -310,7 +301,7 @@ func VerifyVersionedTag(prov slsaprovenance.Provenance, expectedTag string) erro
// Note: prerelease is validated as part of patch validation
// and must be equal. Build is discarded as per https://semver.org/:
// "Build metadata MUST be ignored when determining version precedence",
tag, err := getTag(prov)
tag, err := prov.GetTag()
if err != nil {
return err
}
@@ -379,166 +370,6 @@ func extractFromVersion(v string, i int) (string, error) {
return parts[i], nil
}
func getAsAny(payload map[string]any, field string) (any, error) {
value, ok := payload[field]
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload,
fmt.Sprintf("payload type for %s", field))
}
return value, nil
}
func getAsString(pyld map[string]interface{}, field string) (string, error) {
value, ok := pyld[field]
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload,
fmt.Sprintf("environment type for %s", field))
}
i, ok := value.(string)
if !ok {
return "", fmt.Errorf("%w: %s '%s'", serrors.ErrorInvalidDssePayload, "environment type string", field)
}
return i, nil
}
func getEventPayload(prov slsaprovenance.Provenance) (map[string]interface{}, error) {
eventPayload, err := prov.GetAnyFromEnvironment("github_event_payload")
if err != nil {
return nil, err
}
payload, ok := eventPayload.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type payload")
}
return payload, nil
}
func getBaseRef(prov slsaprovenance.Provenance) (string, error) {
baseRef, err := prov.GetStringFromEnvironment("github_base_ref")
if err != nil {
return "", err
}
// This `base_ref` seems to always be "".
if baseRef != "" {
return baseRef, nil
}
// Look at the event payload instead.
// We don't do that for all triggers because the payload
// is event-specific; and only the `push` event seems to have a `base_ref`.
eventName, err := prov.GetStringFromEnvironment("github_event_name")
if err != nil {
return "", err
}
if eventName != "push" {
return "", nil
}
payload, err := getEventPayload(prov)
if err != nil {
return "", err
}
value, err := getAsAny(payload, "base_ref")
if err != nil {
return "", err
}
// The `base_ref` field may be nil if the build was from
// a specific commit rather than a branch.
v, ok := value.(string)
if !ok {
return "", nil
}
return v, nil
}
func getTargetCommittish(prov slsaprovenance.Provenance) (string, error) {
eventName, err := prov.GetStringFromEnvironment("github_event_name")
if err != nil {
return "", err
}
if eventName != "release" {
return "", nil
}
payload, err := getEventPayload(prov)
if err != nil {
return "", err
}
// For a release event, we look for release.target_commitish.
releasePayload, ok := payload["release"]
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "release absent from payload")
}
release, ok := releasePayload.(map[string]interface{})
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type releasePayload")
}
branch, err := getAsString(release, "target_commitish")
if err != nil {
return "", fmt.Errorf("%w: %s", err, "target_commitish not present")
}
return "refs/heads/" + branch, nil
}
func getBranchForTag(prov slsaprovenance.Provenance) (string, error) {
// First try the base_ref.
branch, err := getBaseRef(prov)
if branch != "" || err != nil {
return branch, err
}
// Second try the target comittish.
return getTargetCommittish(prov)
}
// Get tag from the provenance invocation parameters.
func getTag(prov slsaprovenance.Provenance) (string, error) {
refType, err := prov.GetStringFromEnvironment("github_ref_type")
if err != nil {
return "", err
}
switch refType {
case "branch":
return "", nil
case "tag":
return prov.GetStringFromEnvironment("github_ref")
default:
return "", fmt.Errorf("%w: %s %s", serrors.ErrorInvalidDssePayload,
"unknown ref type", refType)
}
}
// Get branch from the provenance invocation parameters.
func getBranch(prov slsaprovenance.Provenance) (string, error) {
refType, err := prov.GetStringFromEnvironment("github_ref_type")
if err != nil {
return "", err
}
switch refType {
case "branch":
return prov.GetStringFromEnvironment("github_ref")
case "tag":
return getBranchForTag(prov)
default:
return "", fmt.Errorf("%w: %s %s", serrors.ErrorInvalidDssePayload,
"unknown ref type", refType)
}
}
// hasCertInEnvelope checks if a valid x509 certificate is present in the
// envelope.
func hasCertInEnvelope(provenance []byte) bool {

View File

@@ -9,10 +9,12 @@ import (
intoto "github.com/in-toto/in-toto-golang/in_toto"
slsacommon "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
slsa02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
slsa1 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1.0"
serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
"github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance"
v02 "github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance/v0.2"
"github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance/v1.0"
)
func provenanceFromBytes(payload []byte) (slsaprovenance.Provenance, error) {
@@ -79,6 +81,58 @@ func Test_VerifySha256Subject(t *testing.T) {
artifactHash: "04e7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
expected: serrors.ErrorMismatchHash,
},
{
name: "slsa 1.0 invalid dsse: not SLSA predicate",
path: "./testdata/dsse-not-slsa-v1.intoto.jsonl",
artifactHash: "0ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
expected: serrors.ErrorInvalidDssePayload,
},
{
name: "invalid dsse: nil subject",
path: "./testdata/dsse-no-subject-v1.intoto.jsonl",
artifactHash: "0ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
expected: serrors.ErrorInvalidDssePayload,
},
{
name: "invalid dsse: no sha256 subject digest",
path: "./testdata/dsse-no-subject-hash-v1.intoto.jsonl",
artifactHash: "0ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
expected: serrors.ErrorInvalidDssePayload,
},
{
name: "mismatched artifact hash with env",
path: "./testdata/dsse-valid-v1.intoto.jsonl",
artifactHash: "1ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
expected: serrors.ErrorMismatchHash,
},
{
name: "valid entry",
path: "./testdata/dsse-valid-v1.intoto.jsonl",
artifactHash: "0ae7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
expected: nil,
},
{
name: "valid entry multiple subjects last entry",
path: "./testdata/dsse-valid-multi-subjects-v1.intoto.jsonl",
artifactHash: "03e7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
expected: nil,
},
{
name: "valid multiple subjects second entry",
path: "./testdata/dsse-valid-multi-subjects-v1.intoto.jsonl",
artifactHash: "02e7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
expected: nil,
},
{
name: "multiple subjects invalid hash",
path: "./testdata/dsse-valid-multi-subjects-v1.intoto.jsonl",
artifactHash: "04e7e4fa71686538440012ee36a2634dbaa19df2dd16a466f52411fb348bbc4e",
expected: serrors.ErrorMismatchHash,
},
}
for _, tt := range tests {
tt := tt // Re-initializing variable so it is not changed while executing the closure below
@@ -109,6 +163,8 @@ func Test_verifySourceURI(t *testing.T) {
prov *intoto.ProvenanceStatement
sourceURI string
expected error
// v1 provenance does not include materials
skipv1 bool
}{
{
name: "source has no @",
@@ -137,6 +193,7 @@ func Test_verifySourceURI(t *testing.T) {
},
sourceURI: "git+https://github.com/some/repo",
expected: serrors.ErrorInvalidDssePayload,
skipv1: true,
},
{
name: "empty configSource",
@@ -284,6 +341,7 @@ func Test_verifySourceURI(t *testing.T) {
},
},
sourceURI: "git+https://github.com/some/repo",
skipv1: true,
expected: serrors.ErrorInvalidDssePayload,
},
{
@@ -349,11 +407,32 @@ func Test_verifySourceURI(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
prov := &v02.ProvenanceV02{
prov02 := &v02.ProvenanceV02{
ProvenanceStatement: tt.prov,
}
err := verifySourceURI(prov, tt.sourceURI)
err := verifySourceURI(prov02, tt.sourceURI)
if !errCmp(err, tt.expected) {
t.Errorf(cmp.Diff(err, tt.expected))
}
if tt.skipv1 {
return
}
// Update to v1 SLSA provenance.
prov1 := &v1.ProvenanceV1{
Predicate: slsa1.ProvenancePredicate{
BuildDefinition: slsa1.ProvenanceBuildDefinition{
ExternalParameters: map[string]interface{}{
"source": slsa1.ArtifactReference{
URI: tt.prov.Predicate.Invocation.ConfigSource.URI,
},
},
},
},
}
err = verifySourceURI(prov1, tt.sourceURI)
if !errCmp(err, tt.expected) {
t.Errorf(cmp.Diff(err, tt.expected))
}
@@ -448,6 +527,22 @@ func Test_verifyBuilderIDExactMatch(t *testing.T) {
if !errCmp(err, tt.expected) {
t.Errorf(cmp.Diff(err, tt.expected))
}
// Update to v1 SLSA provenance.
prov1 := &v1.ProvenanceV1{
Predicate: slsa1.ProvenancePredicate{
RunDetails: slsa1.ProvenanaceRunDetails{
Builder: slsa1.Builder{
ID: tt.prov.Predicate.Builder.ID,
},
},
},
}
err = verifyBuilderIDExactMatch(prov1, tt.id)
if !errCmp(err, tt.expected) {
t.Errorf(cmp.Diff(err, tt.expected))
}
})
}
}

View File

@@ -24,17 +24,15 @@ type Provenance interface {
// Subject is the list of intoto subjects in the provenance.
Subjects() ([]intoto.Subject, error)
// GetStringFromEnvironment retrieves a string parameter from the environment
// attested to in the provenance.
GetStringFromEnvironment(name string) (string, error)
// GetBranch retrieves the branch name of the source from the provenance.
GetBranch() (string, error)
// GetAnyFromEnvironment retrieves an object parameter from the environment
// attested to in the provenance.
GetAnyFromEnvironment(name string) (interface{}, error)
// GetTag retrieves the tag of the source from the provenance.
GetTag() (string, error)
// GetInputs retrieves the inputs from the provenance. Only succeeds for event
// GetWorkflowInputs retrieves the inputs from the provenance. Only succeeds for event
// relevant event types (workflow_inputs).
GetInputs() (map[string]interface{}, error)
GetWorkflowInputs() (map[string]interface{}, error)
}
// ProvenanceMap stores the different provenance version types.

View File

@@ -6,9 +6,10 @@ import (
intoto "github.com/in-toto/in-toto-golang/in_toto"
serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
"github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance"
"github.com/slsa-framework/slsa-verifier/v2/verifiers/utils"
)
// TODO(asraa): Use a static mapping.
// TODO(https://github.com/slsa-framework/slsa-verifier/issues/473): Use a static mapping.
//
//nolint:gochecknoinits
func init() {
@@ -49,49 +50,74 @@ func (prov *ProvenanceV02) Subjects() ([]intoto.Subject, error) {
return subj, nil
}
func (prov *ProvenanceV02) GetStringFromEnvironment(name string) (string, error) {
func (prov *ProvenanceV02) GetBranch() (string, error) {
// GetBranch gets the branch from the invocation parameters.
environment, ok := prov.Predicate.Invocation.Environment.(map[string]interface{})
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type")
}
val, ok := environment[name]
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload,
fmt.Sprintf("environment type for %s", name))
refType, err := utils.GetAsString(environment, "github_ref_type")
if err != nil {
return "", err
}
i, ok := val.(string)
if !ok {
return "", fmt.Errorf("%w: %s '%s'", serrors.ErrorInvalidDssePayload, "environment type string", name)
switch refType {
case "branch":
return utils.GetAsString(environment, "github_ref")
case "tag":
return getBranchForTag(prov)
default:
return "", fmt.Errorf("%w: %s %s", serrors.ErrorInvalidDssePayload,
"unknown ref type", refType)
}
return i, nil
}
func (prov *ProvenanceV02) GetAnyFromEnvironment(name string) (interface{}, error) {
func (prov *ProvenanceV02) GetTag() (string, error) {
environment, ok := prov.Predicate.Invocation.Environment.(map[string]interface{})
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type")
}
val, ok := environment[name]
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload,
fmt.Sprintf("environment type for %s", name))
refType, err := utils.GetAsString(environment, "github_ref_type")
if err != nil {
return "", err
}
switch refType {
case "branch":
return "", nil
case "tag":
return utils.GetAsString(environment, "github_ref")
default:
return "", fmt.Errorf("%w: %s %s", serrors.ErrorInvalidDssePayload,
"unknown ref type", refType)
}
return val, nil
}
func (prov *ProvenanceV02) GetInputs() (map[string]interface{}, error) {
eventPayload, err := prov.GetAnyFromEnvironment("github_event_payload")
func (prov *ProvenanceV02) GetWorkflowInputs() (map[string]interface{}, error) {
// Verify it's a workflow_dispatch trigger.
environment, ok := prov.Predicate.Invocation.Environment.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type")
}
triggerName, err := utils.GetAsString(environment, "github_event_name")
if err != nil {
return nil, err
}
if triggerName != "workflow_dispatch" {
return nil, fmt.Errorf("%w: expected 'workflow_dispatch' trigger, got %s",
serrors.ErrorMismatchWorkflowInputs, triggerName)
}
payload, err := getEventPayload(environment)
if err != nil {
return nil, err
}
payload, ok := eventPayload.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type payload")
}
payloadInputs, ok := payload["inputs"]
if !ok {
payloadInputs, err := getAsAny(payload, "inputs")
if err != nil {
return nil, fmt.Errorf("%w: error retrieving 'inputs': %v", serrors.ErrorInvalidDssePayload, err)
}
@@ -101,3 +127,94 @@ func (prov *ProvenanceV02) GetInputs() (map[string]interface{}, error) {
}
return pyldInputs, nil
}
func getBranchForTag(prov *ProvenanceV02) (string, error) {
// First try the base_ref.
environment, ok := prov.Predicate.Invocation.Environment.(map[string]interface{})
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type")
}
baseRef, err := utils.GetAsString(environment, "github_base_ref")
if err != nil {
return "", err
}
// This `base_ref` seems to always be "".
if baseRef != "" {
return baseRef, nil
}
// Look at the event payload instead.
eventName, err := utils.GetAsString(environment, "github_event_name")
if err != nil {
return "", err
}
payload, err := getEventPayload(environment)
if err != nil {
return "", err
}
// We don't do that for all triggers because the payload
// is event-specific. Only `push` events seem to have a `base_ref`, and
// `release` events specify a branch in `target_commitish`.
switch eventName {
case "push":
value, err := getAsAny(payload, "base_ref")
if err != nil {
return "", err
}
// The `base_ref` field may be nil if the build was from
// a specific commit rather than a branch.
v, ok := value.(string)
if !ok {
return "", nil
}
return v, nil
case "release":
// For a release event, we look for release.target_commitish.
releasePayload, ok := payload["release"]
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "release absent from payload")
}
release, ok := releasePayload.(map[string]interface{})
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type releasePayload")
}
branch, err := utils.GetAsString(release, "target_commitish")
if err != nil {
return "", fmt.Errorf("%w: %s", err, "target_commitish not present")
}
return "refs/heads/" + branch, nil
default:
return "", nil
}
}
func getAsAny(environment map[string]any, field string) (any, error) {
value, ok := environment[field]
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload,
fmt.Sprintf("environment type for %s", field))
}
return value, nil
}
func getEventPayload(environment map[string]any) (map[string]any, error) {
eventPayload, ok := environment["github_event_payload"]
if !ok {
return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type event payload")
}
payload, ok := eventPayload.(map[string]any)
if !ok {
return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "parameters type payload")
}
return payload, nil
}

View File

@@ -0,0 +1,77 @@
package v1
import (
"errors"
"fmt"
intoto "github.com/in-toto/in-toto-golang/in_toto"
slsa1 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1.0"
serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
"github.com/slsa-framework/slsa-verifier/v2/verifiers/internal/gha/slsaprovenance"
)
// TODO(https://github.com/slsa-framework/slsa-verifier/issues/473): Use a static mapping.
//
//nolint:gochecknoinits
func init() {
slsaprovenance.ProvenanceMap.Store(
"https://slsa.dev/provenance/v1.0?draft",
New)
}
type ProvenanceV1 struct {
intoto.StatementHeader
Predicate slsa1.ProvenancePredicate `json:"predicate"`
}
// This returns a new, empty instance of the v0.2 provenance.
func New() slsaprovenance.Provenance {
return &ProvenanceV1{}
}
func (prov *ProvenanceV1) BuilderID() (string, error) {
return prov.Predicate.RunDetails.Builder.ID, nil
}
func (prov *ProvenanceV1) SourceURI() (string, error) {
extParams, ok := prov.Predicate.BuildDefinition.ExternalParameters.(map[string]interface{})
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "external parameters type")
}
source, ok := extParams["source"]
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "external parameters source")
}
sourceRef, ok := source.(slsa1.ArtifactReference)
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "external parameters source type")
}
return sourceRef.URI, nil
}
func (prov *ProvenanceV1) ConfigURI() (string, error) {
// The source and config are the same for GHA provenance.
return prov.SourceURI()
}
func (prov *ProvenanceV1) Subjects() ([]intoto.Subject, error) {
subj := prov.Subject
if len(subj) == 0 {
return nil, fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload, "no subjects")
}
return subj, nil
}
func (prov *ProvenanceV1) GetBranch() (string, error) {
// TODO(https://github.com/slsa-framework/slsa-verifier/issues/472): Add GetBranch() support.
return "", errors.New("unimplemented")
}
func (prov *ProvenanceV1) GetTag() (string, error) {
// TODO(https://github.com/slsa-framework/slsa-verifier/issues/472): Add GetTag() support.
return "", errors.New("unimplemented")
}
func (prov *ProvenanceV1) GetWorkflowInputs() (map[string]interface{}, error) {
return nil, errors.New("unimplemented")
}

View File

@@ -0,0 +1,10 @@
{
"payloadType": "application/vnd.in-toto+json",
"payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAiZGlnZXN0IjogewogICAgICAgICJzaGExIjogIjQ1MDYyOTBlMmU4ZmViMWYzNGIyN2EwNDRmN2NjODYzYzgzMGVmNmIiCiAgICAgIH0sCiAgICAgICJuYW1lIjogImJpbmFyeS1saW51eC1hbWQ2NCIKICAgIH0KICBdLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MS4wP2RyYWZ0IiwKICAicHJlZGljYXRlIjogewogICAgImJ1aWxkRGVmaW5pdGlvbiI6IHsKICAgICAgImJ1aWxkTm90U0xTQSI6ICJodHRwczovL2dpdGh1Yi5jb20vQXR0ZXN0YXRpb25zL0dpdEh1YkFjdGlvbnNXb3JrZmxvd0B2MSIsCiAgICAgICJleHRlcm5hbFBhcmFtYXRlcnMiOiB7CiAgICAgICAgInNvdXJjZSI6IHsKICAgICAgICAgICJ1cmkiOiAiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9zbHNhLWZyYW1ld29yay9leGFtcGxlLXBhY2thZ2UiLAogICAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICAgInNoYTEiOiAiNGU2YzVmNmQwYjRhMTI2ZmEyMzczZDdlNTdiN2EwYWYwNTEwODc5MSIKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICAicnVuRGV0YWlscyI6IHsKICAgICAgImJ1aWxkZXIiOiB7CiAgICAgICAgImlkIjogImh0dHBzOi8vZ2l0aHViLmNvbS9BdHRlc3RhdGlvbnMvR2l0SHViSG9zdGVkQWN0aW9uc0B2MSIKICAgICAgfSwKICAgICAgIm1ldGFkYXRhIjogewogICAgICAgICJpbnZvY2F0aW9uSWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL3Nsc2EtZnJhbWV3b3JrL2V4YW1wbGUtcGFja2FnZS9hY3Rpb25zL3J1bnMvNDEzNTQ2Mzc0MS9hdHRlbXB0cy8xIgogICAgICB9CiAgICB9CiAgfQp9Cg==",
"signatures": [
{
"keyid": "",
"sig": "MEUCIGIitQ1z1kUQEEaYdGLUtremEsfBzJyGm+Wp2t3PtzSSAiEAiibeJkqt6tTWcxbHNQqUKmtcteyH49NO8U7KiWtu+yc="
}
]
}

View File

@@ -0,0 +1,10 @@
{
"payloadType": "application/vnd.in-toto+json",
"payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogW10sCiAgInByZWRpY2F0ZVR5cGUiOiAiaHR0cHM6Ly9zbHNhLmRldi9wcm92ZW5hbmNlL3YxLjA/ZHJhZnQiLAogICJwcmVkaWNhdGUiOiB7CiAgICAiYnVpbGREZWZpbml0aW9uIjogewogICAgICAiYnVpbGROb3RTTFNBIjogImh0dHBzOi8vZ2l0aHViLmNvbS9BdHRlc3RhdGlvbnMvR2l0SHViQWN0aW9uc1dvcmtmbG93QHYxIiwKICAgICAgImV4dGVybmFsUGFyYW1hdGVycyI6IHsKICAgICAgICAic291cmNlIjogewogICAgICAgICAgInVyaSI6ICJnaXQraHR0cHM6Ly9naXRodWIuY29tL3Nsc2EtZnJhbWV3b3JrL2V4YW1wbGUtcGFja2FnZSIsCiAgICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgICAic2hhMSI6ICI0ZTZjNWY2ZDBiNGExMjZmYTIzNzNkN2U1N2I3YTBhZjA1MTA4NzkxIgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSwKICAgICJydW5EZXRhaWxzIjogewogICAgICAiYnVpbGRlciI6IHsKICAgICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL0F0dGVzdGF0aW9ucy9HaXRIdWJIb3N0ZWRBY3Rpb25zQHYxIgogICAgICB9LAogICAgICAibWV0YWRhdGEiOiB7CiAgICAgICAgImludm9jYXRpb25JZCI6ICJodHRwczovL2dpdGh1Yi5jb20vc2xzYS1mcmFtZXdvcmsvZXhhbXBsZS1wYWNrYWdlL2FjdGlvbnMvcnVucy80MTM1NDYzNzQxL2F0dGVtcHRzLzEiCiAgICAgIH0KICAgIH0KICB9Cn0K",
"signatures": [
{
"keyid": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGUiOiB7CiAgICAiYnVpbGRUeXBlIjogImh0dHBzOi8vZ2l0aHViLmNvbS9BdHRlc3RhdGlvbnMvR2l0SHViQWN0aW9uc1dvcmtmbG93QHYxIiwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL0F0dGVzdGF0aW9ucy9HaXRIdWJIb3N0ZWRBY3Rpb25zQHYxIgogICAgfSwKICAgICJpbnZvY2F0aW9uIjogewogICAgICAiY29uZmlnU291cmNlIjogewogICAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgICAiU0hBMSI6ICI0NTA2MjkwZTJlOGZlYjFmMzRiMjdhMDQ0ZjdjYzg2M2M4MzBlZjZiIgogICAgICAgIH0sCiAgICAgICAgImVudHJ5UG9pbnQiOiAiVGVzdCBTTFNBIiwKICAgICAgICAidXJpIjogImdpdCthc3JhYS9zbHNhLW9uLWdpdGh1Yi10ZXN0LmdpdCIKICAgICAgfSwKICAgICAgImVudmlyb25tZW50IjogewogICAgICAgICJhcmNoIjogImFtZDY0IiwKICAgICAgICAiZW52IjogewogICAgICAgICAgIkdJVEhVQl9FVkVOVF9OQU1FIjogIndvcmtmbG93X2Rpc3BhdGNoIiwKICAgICAgICAgICJHSVRIVUJfUlVOX0lEIjogIjE4OTM3OTkyMjAiLAogICAgICAgICAgIkdJVEhVQl9SVU5fTlVNQkVSIjogIjc2IgogICAgICAgIH0KICAgICAgfQogICAgfSwKICAgICJtYXRlcmlhbHMiOiBbCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgIlNIQTEiOiAiNDUwNjI5MGUyZThmZWIxZjM0YjI3YTA0NGY3Y2M4NjNjODMwZWY2YiIKICAgICAgICB9LAogICAgICAgICJ1cmkiOiAiZ2l0K2FzcmFhL3Nsc2Etb24tZ2l0aHViLXRlc3QuZ2l0IgogICAgICB9CiAgICBdCiAgfSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjAuMiIsCn0K",
"sig": "MEUCIGIitQ1z1kUQEEaYdGLUtremEsfBzJyGm+Wp2t3PtzSSAiEAiibeJkqt6tTWcxbHNQqUKmtcteyH49NO8U7KiWtu+yc="
}
]
}

View File

@@ -0,0 +1,10 @@
{
"payloadType": "application/vnd.in-toto+json",
"payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAiZGlnZXN0IjogewogICAgICAgICJzaGExIjogIjQ1MDYyOTBlMmU4ZmViMWYzNGIyN2EwNDRmN2NjODYzYzgzMGVmNmIiCiAgICAgIH0sCiAgICAgICJuYW1lIjogImJpbmFyeS1saW51eC1hbWQ2NCIKICAgIH0KICBdLAogICJwcmVkaWNhdGVUeXBlIjogImh0dHBzOi8vc2xzYS5kZXYvcHJvdmVuYW5jZS92MS4wP2RyYWZ0IiwKICAicHJlZGljYXRlIjogewogICAgImJ1aWxkRGVmaW5pdGlvbiI6IHsKICAgICAgImJ1aWxkTm90U0xTQSI6ICJodHRwczovL2dpdGh1Yi5jb20vQXR0ZXN0YXRpb25zL0dpdEh1YkFjdGlvbnNXb3JrZmxvd0B2MSIsCiAgICAgICJleHRlcm5hbFBhcmFtYXRlcnMiOiB7CiAgICAgICAgInNvdXJjZSI6IHsKICAgICAgICAgICJ1cmkiOiAiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9zbHNhLWZyYW1ld29yay9leGFtcGxlLXBhY2thZ2UiLAogICAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICAgInNoYTEiOiAiNGU2YzVmNmQwYjRhMTI2ZmEyMzczZDdlNTdiN2EwYWYwNTEwODc5MSIKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0sCiAgICAicnVuRGV0YWlscyI6IHsKICAgICAgImJ1aWxkZXIiOiB7CiAgICAgICAgImlkIjogImh0dHBzOi8vZ2l0aHViLmNvbS9BdHRlc3RhdGlvbnMvR2l0SHViSG9zdGVkQWN0aW9uc0B2MSIKICAgICAgfSwKICAgICAgIm1ldGFkYXRhIjogewogICAgICAgICJpbnZvY2F0aW9uSWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL3Nsc2EtZnJhbWV3b3JrL2V4YW1wbGUtcGFja2FnZS9hY3Rpb25zL3J1bnMvNDEzNTQ2Mzc0MS9hdHRlbXB0cy8xIgogICAgICB9CiAgICB9CiAgfQp9Cg==",
"signatures": [
{
"keyid": "",
"sig": "MEUCIGIitQ1z1kUQEEaYdGLUtremEsfBzJyGm+Wp2t3PtzSSAiEAiibeJkqt6tTWcxbHNQqUKmtcteyH49NO8U7KiWtu+yc="
}
]
}

View File

@@ -0,0 +1,10 @@
{
"payloadType": "application/vnd.in-toto+json",
"payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAiZGlnZXN0IjogewogICAgICAgICJzaGEyNTYiOiAiMDFlN2U0ZmE3MTY4NjUzODQ0MDAxMmVlMzZhMjYzNGRiYWExOWRmMmRkMTZhNDY2ZjUyNDExZmIzNDhiYmM0ZSIKICAgICAgfSwKICAgICAgIm5hbWUiOiAiYmluYXJ5LWxpbnV4LWFtZDY0LTEiCiAgICB9LAogICAgewogICAgICAiZGlnZXN0IjogewogICAgICAgICJzaGEyNTYiOiAiMDJlN2U0ZmE3MTY4NjUzODQ0MDAxMmVlMzZhMjYzNGRiYWExOWRmMmRkMTZhNDY2ZjUyNDExZmIzNDhiYmM0ZSIKICAgICAgfSwKICAgICAgIm5hbWUiOiAiYmluYXJ5LWxpbnV4LWFtZDY0LTIiCiAgICB9LAogICAgewogICAgICAiZGlnZXN0IjogewogICAgICAgICJzaGEyNTYiOiAiMDNlN2U0ZmE3MTY4NjUzODQ0MDAxMmVlMzZhMjYzNGRiYWExOWRmMmRkMTZhNDY2ZjUyNDExZmIzNDhiYmM0ZSIKICAgICAgfSwKICAgICAgIm5hbWUiOiAiYmluYXJ5LWxpbnV4LWFtZDY0LTMiCiAgICB9CiAgXSwKICAicHJlZGljYXRlVHlwZSI6ICJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjEuMD9kcmFmdCIsCiAgInByZWRpY2F0ZSI6IHsKICAgICJidWlsZERlZmluaXRpb24iOiB7CiAgICAgICJidWlsZE5vdFNMU0EiOiAiaHR0cHM6Ly9naXRodWIuY29tL0F0dGVzdGF0aW9ucy9HaXRIdWJBY3Rpb25zV29ya2Zsb3dAdjEiLAogICAgICAiZXh0ZXJuYWxQYXJhbWF0ZXJzIjogewogICAgICAgICJzb3VyY2UiOiB7CiAgICAgICAgICAidXJpIjogImdpdCtodHRwczovL2dpdGh1Yi5jb20vc2xzYS1mcmFtZXdvcmsvZXhhbXBsZS1wYWNrYWdlIiwKICAgICAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgICAgICJzaGExIjogIjRlNmM1ZjZkMGI0YTEyNmZhMjM3M2Q3ZTU3YjdhMGFmMDUxMDg3OTEiCiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9LAogICAgInJ1bkRldGFpbHMiOiB7CiAgICAgICJidWlsZGVyIjogewogICAgICAgICJpZCI6ICJodHRwczovL2dpdGh1Yi5jb20vQXR0ZXN0YXRpb25zL0dpdEh1Ykhvc3RlZEFjdGlvbnNAdjEiCiAgICAgIH0sCiAgICAgICJtZXRhZGF0YSI6IHsKICAgICAgICAiaW52b2NhdGlvbklkIjogImh0dHBzOi8vZ2l0aHViLmNvbS9zbHNhLWZyYW1ld29yay9leGFtcGxlLXBhY2thZ2UvYWN0aW9ucy9ydW5zLzQxMzU0NjM3NDEvYXR0ZW1wdHMvMSIKICAgICAgfQogICAgfQogIH0KfQo=",
"signatures": [
{
"keyid": "",
"sig": "MEUCIGIitQ1z1kUQEEaYdGLUtremEsfBzJyGm+Wp2t3PtzSSAiEAiibeJkqt6tTWcxbHNQqUKmtcteyH49NO8U7KiWtu+yc="
}
]
}

View File

@@ -0,0 +1,10 @@
{
"payloadType": "application/vnd.in-toto+json",
"payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJzdWJqZWN0IjogWwogICAgewogICAgICAiZGlnZXN0IjogewogICAgICAgICJzaGEyNTYiOiAiMGFlN2U0ZmE3MTY4NjUzODQ0MDAxMmVlMzZhMjYzNGRiYWExOWRmMmRkMTZhNDY2ZjUyNDExZmIzNDhiYmM0ZSIKICAgICAgfSwKICAgICAgIm5hbWUiOiAiYmluYXJ5LWxpbnV4LWFtZDY0IgogICAgfQogIF0sCiAgInByZWRpY2F0ZVR5cGUiOiAiaHR0cHM6Ly9zbHNhLmRldi9wcm92ZW5hbmNlL3YxLjA/ZHJhZnQiLAogICJwcmVkaWNhdGUiOiB7CiAgICAiYnVpbGREZWZpbml0aW9uIjogewogICAgICAiYnVpbGROb3RTTFNBIjogImh0dHBzOi8vZ2l0aHViLmNvbS9BdHRlc3RhdGlvbnMvR2l0SHViQWN0aW9uc1dvcmtmbG93QHYxIiwKICAgICAgImV4dGVybmFsUGFyYW1hdGVycyI6IHsKICAgICAgICAic291cmNlIjogewogICAgICAgICAgInVyaSI6ICJnaXQraHR0cHM6Ly9naXRodWIuY29tL3Nsc2EtZnJhbWV3b3JrL2V4YW1wbGUtcGFja2FnZSIsCiAgICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgICAic2hhMSI6ICI0ZTZjNWY2ZDBiNGExMjZmYTIzNzNkN2U1N2I3YTBhZjA1MTA4NzkxIgogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSwKICAgICJydW5EZXRhaWxzIjogewogICAgICAiYnVpbGRlciI6IHsKICAgICAgICAiaWQiOiAiaHR0cHM6Ly9naXRodWIuY29tL0F0dGVzdGF0aW9ucy9HaXRIdWJIb3N0ZWRBY3Rpb25zQHYxIgogICAgICB9LAogICAgICAibWV0YWRhdGEiOiB7CiAgICAgICAgImludm9jYXRpb25JZCI6ICJodHRwczovL2dpdGh1Yi5jb20vc2xzYS1mcmFtZXdvcmsvZXhhbXBsZS1wYWNrYWdlL2FjdGlvbnMvcnVucy80MTM1NDYzNzQxL2F0dGVtcHRzLzEiCiAgICAgIH0KICAgIH0KICB9Cn0K",
"signatures": [
{
"keyid": "",
"sig": "MEUCIGIitQ1z1kUQEEaYdGLUtremEsfBzJyGm+Wp2t3PtzSSAiEAiibeJkqt6tTWcxbHNQqUKmtcteyH49NO8U7KiWtu+yc="
}
]
}

View File

@@ -96,11 +96,15 @@ func (v *GHAVerifier) VerifyArtifact(ctx context.Context,
return nil, nil, err
}
var signedAtt *SignedAttestation
/* Verify signature on the intoto attestation. */
// TODO(https://github.com/slsa-framework/slsa-github-generator/issues/716):
// We will also need to support bundles when those are complete.
signedAtt, err := VerifyProvenanceSignature(ctx, trustedRoot, rClient,
provenance, artifactHash)
if provenanceOpts.ProvenanceBundle != nil {
signedAtt, err = VerifyProvenanceBundle(ctx, provenanceOpts.ProvenanceBundle,
trustedRoot)
} else {
signedAtt, err = VerifyProvenanceSignature(ctx, trustedRoot, rClient,
provenance, artifactHash)
}
if err != nil {
return nil, nil, err
}

View File

@@ -0,0 +1,21 @@
package utils
import (
"fmt"
serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
)
func GetAsString(environment map[string]any, field string) (string, error) {
value, ok := environment[field]
if !ok {
return "", fmt.Errorf("%w: %s", serrors.ErrorInvalidDssePayload,
fmt.Sprintf("environment type for %s", field))
}
i, ok := value.(string)
if !ok {
return "", fmt.Errorf("%w: %s '%s'", serrors.ErrorInvalidDssePayload, "environment type string", field)
}
return i, nil
}