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

feat: vsa support #777

Merged
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
7980fde
Changed success message to a more general "PASSED: SLSA verification …
ramonpetgrave64 Jun 13, 2024
b5eb147
skeletion verify-vsa command
ramonpetgrave64 Jun 13, 2024
a25abe2
testdata, sample invocation in README.md
ramonpetgrave64 Jun 13, 2024
b90ede0
rename to TrustedProducerID, allow muyltiple --subject-digest flags
ramonpetgrave64 Jun 14, 2024
a3a573a
cleanup
ramonpetgrave64 Jun 17, 2024
9704c97
parse dsse envelope
ramonpetgrave64 Jun 17, 2024
2f76f12
different test example
ramonpetgrave64 Jun 18, 2024
2dc64f7
vsa parser
ramonpetgrave64 Jun 18, 2024
1f123f3
attempt to verify envelope
ramonpetgrave64 Jun 18, 2024
edde0a8
cleanup, more skeleton
ramonpetgrave64 Jun 18, 2024
ead4e9b
use utility to parse envelope, docs, use keyID
ramonpetgrave64 Jun 18, 2024
13a74b5
embed the google vsa key, match against all signatures, match the sub…
ramonpetgrave64 Jun 18, 2024
610ef6f
verify reamining fields, print attestations
ramonpetgrave64 Jun 19, 2024
944c9a6
singular print-attestation
ramonpetgrave64 Jun 19, 2024
2ef9a40
minify test data
ramonpetgrave64 Jun 20, 2024
f0fedec
verify vsa passed message
ramonpetgrave64 Jun 20, 2024
ad1b81d
update README
ramonpetgrave64 Jun 20, 2024
f5362e5
rename to PublicKeyHashAlgo
ramonpetgrave64 Jun 20, 2024
5636d0a
rename to resource URI
ramonpetgrave64 Jun 20, 2024
fec61b1
use pointers
ramonpetgrave64 Jun 20, 2024
8befbc6
use plain bool
ramonpetgrave64 Jun 20, 2024
7fb5bf9
switch wanted, got order
ramonpetgrave64 Jun 20, 2024
fbe83fb
change error type
ramonpetgrave64 Jun 20, 2024
00fed87
typo
ramonpetgrave64 Jun 20, 2024
e47312f
literl hash algo
ramonpetgrave64 Jun 20, 2024
cba639f
specific errors and test cases
ramonpetgrave64 Jun 20, 2024
ff1cf43
undo regression tag change
ramonpetgrave64 Jun 20, 2024
942d8bb
remove accidental binary
ramonpetgrave64 Jun 20, 2024
73c9884
lint: no pointer for crypto.publickkey
ramonpetgrave64 Jun 20, 2024
0172a12
lint
ramonpetgrave64 Jun 20, 2024
e27f99f
no need for sigstoreEnvelope
ramonpetgrave64 Jun 20, 2024
968a34d
typo
ramonpetgrave64 Jun 21, 2024
519a928
clarify comments
ramonpetgrave64 Jun 22, 2024
b9c6de5
flag descriptions, optional --verified-levels
ramonpetgrave64 Jun 22, 2024
f3b63b7
reword simple hash
ramonpetgrave64 Jun 22, 2024
e0919a8
hash-algo description
ramonpetgrave64 Jun 22, 2024
23d8e33
singular attestation path
ramonpetgrave64 Jun 22, 2024
bf38fb0
help docs
ramonpetgrave64 Jun 22, 2024
1ccec0e
comment doc
ramonpetgrave64 Jun 25, 2024
92ce34e
fix capitalization
ramonpetgrave64 Jun 25, 2024
f9a4b35
cli help about default options
ramonpetgrave64 Jun 25, 2024
9b2554e
cli about print-attestation
ramonpetgrave64 Jun 25, 2024
e452493
fix cap
ramonpetgrave64 Jun 25, 2024
7813046
remove experimental
ramonpetgrave64 Jun 25, 2024
721eee5
singular attestation
ramonpetgrave64 Jun 25, 2024
719e118
typo
ramonpetgrave64 Jun 25, 2024
311b211
func doc comment
ramonpetgrave64 Jun 25, 2024
e8ed9cc
algo help
ramonpetgrave64 Jun 25, 2024
3d6e498
caps
ramonpetgrave64 Jun 25, 2024
9560d1a
rename
ramonpetgrave64 Jun 25, 2024
21f5c3a
lint
ramonpetgrave64 Jun 25, 2024
80b4cec
typo
ramonpetgrave64 Jun 25, 2024
368e43c
readme: caveats
ramonpetgrave64 Jun 25, 2024
d33cbc3
dont use TrustedAttestorID
ramonpetgrave64 Jun 25, 2024
a71e44a
rename to public-key-signing-hash-algo
ramonpetgrave64 Jun 25, 2024
6aef931
cleanup
ramonpetgrave64 Jun 26, 2024
8cf01ea
capitalization
ramonpetgrave64 Jun 28, 2024
15e9019
typo
ramonpetgrave64 Jun 28, 2024
9cd9553
go.mod conflicts
ramonpetgrave64 Jun 28, 2024
891ffff
Merge branch 'main' into ramonpetgrave64-vsa
ramonpetgrave64 Jun 28, 2024
b145f36
remove --public-key-hash-algo, make verified-levels an array
ramonpetgrave64 Jul 1, 2024
701d13a
Merge branch 'main' into ramonpetgrave64-vsa
ramonpetgrave64 Jul 1, 2024
59deb51
fix readme
ramonpetgrave64 Jul 2, 2024
4cf2972
typo
ramonpetgrave64 Jul 2, 2024
475962b
more keyid tests
ramonpetgrave64 Jul 2, 2024
a1068c4
add slsa level inference
ramonpetgrave64 Jul 9, 2024
9ad9097
revise link to how-to-verify
ramonpetgrave64 Jul 10, 2024
9f25bde
Revert "revise link to how-to-verify"
ramonpetgrave64 Jul 10, 2024
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
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,40 @@ The verified in-toto statement may be written to stdout with the

Note that `--source-uri` supports GitHub repository URIs like `github.com/$OWNER/$REPO` when the build was enabled with a Cloud Build [GitHub trigger](https://cloud.google.com/build/docs/automating-builds/github/build-repos-from-github). Otherwise, the build provenance will contain the name of the Cloud Storage bucket used to host the source files, usually of the form `gs://[PROJECT_ID]_cloudbuild/source` (see [Running build](https://cloud.google.com/build/docs/running-builds/submit-build-via-cli-api#running_builds)). We recommend using GitHub triggers in order to preserve the source provenance and valiate that the source came from an expected, version-controlled repository. You _may_ match on the fully-qualified tar like `gs://[PROJECT_ID]_cloudbuild/source/1665165360.279777-955d1904741e4bbeb3461080299e929a.tgz`.

### Verification Summary Attestations (VSA)

We have experimental support for [verifying](https://slsa.dev/spec/v1.1/verification_summary#how-to-verify) VSAs.
Rather than passing in filepaths as arguments, we allow passing in mulitple `--subject-digest` cli options, to
accomodate subjects that are not simple-files.

This experimental support does not work yet with VSAs wrapped in Sigstore bundles, only with simple DSSE envelopes.
loosebazooka marked this conversation as resolved.
Show resolved Hide resolved
With that, we allow the user to pass in the public key.
Note that if the DSSE Envelope `signatures` specifies a `keyid` that is not a simple hash of the key, then you
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved
must supply the `--public-key-id` cli option.

To verify VSAs, invoke like this

```shell
SLSA_VERIFIER_EXPERIMENTAL=1 \
go run ./cli/slsa-verifier/ verify-vsa \
--subject-digest gce_image_id:8970095005306000053 \
--attestations-path ./cli/slsa-verifier/testdata/vsa/gce/v1/gke-gce-pre.bcid-vsa.jsonl \
--verifier-id https://bcid.corp.google.com/verifier/bcid_package_enforcer/v0.1 \
--resource-uri gce_image://gke-node-images:gke-12615-gke1418000-cos-101-17162-463-29-c-cgpv1-pre \
--verified-levels "BCID_L1, SLSA_BUILD_LEVEL_2" \
--public-key-path ./cli/slsa-verifier/testdata/vsa/gce/v1/vsa_signing_public_key.pem \
--public-key-id keystore://76574:prod:vsa_signing_public_key \
--public-key-hash-algo SHA256 \
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved
--print-attestation
```

For multiple subhects, use:
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved

```
--subject-digest sha256:abc123
--subject-digest sha256:xyz456
```

## Known Issues

### tuf: invalid key
Expand Down
1 change: 1 addition & 0 deletions cli/slsa-verifier/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ For more information on SLSA, visit https://slsa.dev`,
c.AddCommand(verifyArtifactCmd())
c.AddCommand(verifyImageCmd())
c.AddCommand(verifyNpmPackageCmd())
c.AddCommand(verifyVSACmd())
// We print our own errors and usage in the check function.
c.SilenceErrors = true
return c
Expand Down
93 changes: 93 additions & 0 deletions cli/slsa-verifier/main_regression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1795,6 +1795,99 @@ func Test_runVerifyNpmPackage(t *testing.T) {
}
}

func Test_runVerifyVSA(t *testing.T) {
// We cannot use t.Setenv due to parallelized tests.
os.Setenv("SLSA_VERIFIER_EXPERIMENTAL", "1")
t.Parallel()

tests := []struct {
name string
attestationsPath *string
subjectDigests *[]string
verifierID *string
resourceURI *string
verifiedLevels *[]string
publicKeyPath *string
publicKeyID *string
publicKeyHashAlgo *string
err error
}{
{
name: "success: gke",
attestationsPath: PointerTo("gce/v1/gke-gce-pre.bcid-vsa.jsonl"),
subjectDigests: PointerTo([]string{"gce_image_id:8970095005306000053"}),
verifierID: PointerTo("https://bcid.corp.google.com/verifier/bcid_package_enforcer/v0.1"),
resourceURI: PointerTo("gce_image://gke-node-images:gke-12615-gke1418000-cos-101-17162-463-29-c-cgpv1-pre"),
verifiedLevels: PointerTo([]string{"BCID_L1", "SLSA_BUILD_LEVEL_2"}),
publicKeyPath: PointerTo("gce/v1/vsa_signing_public_key.pem"),
publicKeyID: PointerTo("keystore://76574:prod:vsa_signing_public_key"),
publicKeyHashAlgo: PointerTo("SHA256"),
},
{
name: "success: gke, default public key hash algo",
attestationsPath: PointerTo("gce/v1/gke-gce-pre.bcid-vsa.jsonl"),
subjectDigests: PointerTo([]string{"gce_image_id:8970095005306000053"}),
verifierID: PointerTo("https://bcid.corp.google.com/verifier/bcid_package_enforcer/v0.1"),
resourceURI: PointerTo("gce_image://gke-node-images:gke-12615-gke1418000-cos-101-17162-463-29-c-cgpv1-pre"),
verifiedLevels: PointerTo([]string{"BCID_L1", "SLSA_BUILD_LEVEL_2"}),
publicKeyPath: PointerTo("gce/v1/vsa_signing_public_key.pem"),
publicKeyID: PointerTo("keystore://76574:prod:vsa_signing_public_key"),
publicKeyHashAlgo: PointerTo(""),
},
{
name: "fail: gke, unsupported public key hash algo",
attestationsPath: PointerTo("gce/v1/gke-gce-pre.bcid-vsa.jsonl"),
publicKeyPath: PointerTo("gce/v1/vsa_signing_public_key.pem"),
publicKeyHashAlgo: PointerTo("SHA123"),
err: serrors.ErrorInvalidHashAlgo,
},
{
name: "fail: gke, wrong public key hash algo",
attestationsPath: PointerTo("gce/v1/gke-gce-pre.bcid-vsa.jsonl"),
publicKeyPath: PointerTo("gce/v1/vsa_signing_public_key.pem"),
publicKeyID: PointerTo(""),
publicKeyHashAlgo: PointerTo("SHA512"),
err: serrors.ErrorNoValidSignature,
},
{
name: "fail: gke, wrong key id",
attestationsPath: PointerTo("gce/v1/gke-gce-pre.bcid-vsa.jsonl"),
publicKeyPath: PointerTo("gce/v1/vsa_signing_public_key.pem"),
publicKeyID: PointerTo("my_key_id"),
publicKeyHashAlgo: PointerTo("SHA256"),
err: serrors.ErrorNoValidSignature,
},
// TODO: Add more tests for different scenarios.
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved
}

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()

attestationsPath := filepath.Clean(filepath.Join(TEST_DIR, "vsa", *tt.attestationsPath))
publicKeyPath := filepath.Clean(filepath.Join(TEST_DIR, "vsa", *tt.publicKeyPath))

cmd := verify.VerifyVSACommand{
AttestationsPath: &attestationsPath,
SubjectDigests: tt.subjectDigests,
VerifierID: tt.verifierID,
ResourceURI: tt.resourceURI,
VerifiedLevels: tt.verifiedLevels,
PublicKeyPath: &publicKeyPath,
PublicKeyID: tt.publicKeyID,
PublicKeyHashAlgo: tt.publicKeyHashAlgo,
}

_, err := cmd.Exec(context.Background())
if diff := cmp.Diff(tt.err, err, cmpopts.EquateErrors()); diff != "" {
t.Fatalf("unexpected error (-want +got): \n%s", diff)
}
})
}

}

ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved
func PointerTo[K any](object K) *K {
return &object
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJwcmVkaWNhdGVUeXBlIjoiaHR0cHM6Ly9zbHNhLmRldi92ZXJpZmljYXRpb25fc3VtbWFyeS92MSIsInByZWRpY2F0ZSI6eyJ0aW1lVmVyaWZpZWQiOiIyMDI0LTA2LTEyVDA3OjI0OjM0LjM1MTYwOFoiLCJ2ZXJpZmllciI6eyJpZCI6Imh0dHBzOi8vYmNpZC5jb3JwLmdvb2dsZS5jb20vdmVyaWZpZXIvYmNpZF9wYWNrYWdlX2VuZm9yY2VyL3YwLjEifSwidmVyaWZpY2F0aW9uUmVzdWx0IjoiUEFTU0VEIiwidmVyaWZpZWRMZXZlbHMiOlsiQkNJRF9MMSIsIlNMU0FfQlVJTERfTEVWRUxfMiJdLCJyZXNvdXJjZVVyaSI6ImdjZV9pbWFnZTovL2drZS1ub2RlLWltYWdlczpna2UtMTI2MTUtZ2tlMTQxODAwMC1jb3MtMTAxLTE3MTYyLTQ2My0yOS1jLWNncHYxLXByZSIsInBvbGljeSI6eyJ1cmkiOiJnb29nbGVmaWxlOi9nb29nbGVfc3JjL2ZpbGVzLzY0MjUxMzE5Mi9kZXBvdC9nb29nbGUzL3Byb2R1Y3Rpb24vc2VjdXJpdHkvYmNpZC9zb2Z0d2FyZS9nY2VfaW1hZ2UvZ2tlL3ZtX2ltYWdlcy5zd19wb2xpY3kudGV4dHByb3RvIn19LCJzdWJqZWN0IjpbeyJuYW1lIjoiXyIsImRpZ2VzdCI6eyJnY2VfaW1hZ2VfaWQiOiI4OTcwMDk1MDA1MzA2MDAwMDUzIn19XX0=",
"payloadType": "application/vnd.in-toto+json",
"signatures": [
{
"sig": "bmIy2gfnQt6oYpd0WbpQMtZcMRtmntDmyki+Be+2Z9qkboMVbi2RQAD1b5AWbBs7iAP8NZVJOI4R/4jOVYB/FA==",
"keyid": "keystore://76574:prod:vsa_signing_public_key"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeGa6ZCZn0q6WpaUwJrSk+PPYEsca
3Xkk3UrxvbQtoZzTmq0zIYq+4QQl0YBedSyy+XcwAMaUWTouTrB05WhYtg==
-----END PUBLIC KEY-----
34 changes: 33 additions & 1 deletion cli/slsa-verifier/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
)

const (
SUCCESS = "PASSED: Verified SLSA provenance"
SUCCESS = "PASSED: SLSA verification passed"
FAILURE = "FAILED: SLSA verification failed"
)

Expand Down Expand Up @@ -184,3 +184,35 @@ func verifyNpmPackageCmd() *cobra.Command {
o.AddFlags(cmd)
return cmd
}

func verifyVSACmd() *cobra.Command {
o := &verify.VerifyVSAOptions{}

cmd := &cobra.Command{
Use: "verify-vsa [flags] subject-digest [subject-digest...]",
Args: cobra.NoArgs,
Short: "Verifies SLSA VSAs for the given subject-digests [experimental]",
Run: func(cmd *cobra.Command, args []string) {
v := verify.VerifyVSACommand{
SubjectDigests: &o.SubjectDigests,
AttestationsPath: &o.AttestationsPath,
VerifierID: &o.VerifierID,
ResourceURI: &o.ResourceURI,
VerifiedLevels: &o.VerifiedLevels,
PrintAttestation: o.PrintAttestation,
PublicKeyPath: &o.PublicKeyPath,
PublicKeyID: &o.PublicKeyID,
PublicKeyHashAlgo: &o.PublicKeyHashAlgo,
}
if _, err := v.Exec(cmd.Context()); 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
}
53 changes: 53 additions & 0 deletions cli/slsa-verifier/verify/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,59 @@ func (o *VerifyNpmOptions) AddFlags(cmd *cobra.Command) {
cmd.MarkFlagsMutuallyExclusive("source-versioned-tag", "source-tag")
}

// VerifyVSAOptions is the top-level options for the `verifyVSA` command.
type VerifyVSAOptions struct {
SubjectDigests []string
AttestationsPath string
VerifierID string
ResourceURI string
VerifiedLevels []string
PublicKeyPath string
PublicKeyID string
PublicKeyHashAlgo string
PrintAttestation bool
}

var _ Interface = (*VerifyVSAOptions)(nil)

// AddFlags implements Interface.
func (o *VerifyVSAOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringArrayVar(&o.SubjectDigests, "subject-digest", []string{},
"the digests to be verified. Pass multiple digests by repeating the flag.")
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved

cmd.Flags().StringVar(&o.AttestationsPath, "attestations-path", "",
"path to a file containing the attestations")

cmd.Flags().StringVar(&o.VerifierID, "verifier-id", "",
"the unique verifier ID who created the attestations")

cmd.Flags().StringVar(&o.ResourceURI, "resource-uri", "",
"the resource URI to be verified")

cmd.Flags().StringSliceVar(&o.VerifiedLevels, "verified-levels", []string{},
"the levels of verification to be performed")
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved

cmd.Flags().BoolVar(&o.PrintAttestation, "print-attestation", false,
"[optional] print the verified attestations to stdout")

cmd.Flags().StringVar(&o.PublicKeyPath, "public-key-path", "",
"path to a public key file")

cmd.Flags().StringVar(&o.PublicKeyID, "public-key-id", "",
"the ID of the public key")
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved

cmd.Flags().StringVar(&o.PublicKeyHashAlgo, "public-key-hash-algo", "SHA256",
"the hash algorithm used to hash the public key, one of SHA256, SHA384, or SHA512")
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved

cmd.MarkFlagRequired("subject-digests")
cmd.MarkFlagRequired("attestations-path")
cmd.MarkFlagRequired("verifier-id")
cmd.MarkFlagRequired("resource-uri")
cmd.MarkFlagRequired("verified-levels")
cmd.MarkFlagRequired("public-key-path")
// public-key-id" and "public-key-hash-algo" are optional since they have useful defaults
}

type workflowInputs struct {
kv map[string]string
}
Expand Down
107 changes: 107 additions & 0 deletions cli/slsa-verifier/verify/verify_vsa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright 2022 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"
"errors"
"fmt"
"os"

"github.com/sigstore/sigstore/pkg/cryptoutils"
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"
"github.com/slsa-framework/slsa-verifier/v2/verifiers/utils"
)

// VerifyVSACommand contains the parameters for the verify-vsa command.
type VerifyVSACommand struct {
SubjectDigests *[]string
AttestationsPath *string
VerifierID *string
ResourceURI *string
VerifiedLevels *[]string
PrintAttestation bool
PublicKeyPath *string
PublicKeyID *string
PublicKeyHashAlgo *string
}

var hashAlgos = map[string]crypto.Hash{
"": crypto.SHA256, // default to SHA256
"SHA256": crypto.SHA256,
"SHA384": crypto.SHA384,
"SHA512": crypto.SHA512,
}

// Exec executes the verifiers.VerifyVSA.
func (c *VerifyVSACommand) Exec(ctx context.Context) (*utils.TrustedAttesterID, error) {
if !options.ExperimentalEnabled() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a process for when we can remove the experimental flag?

Would it be sufficient to not have this flag but have a release candidate build, & get feedback and iterate before cutting a final release?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove it when we're ready to merge this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SG, once this leaves draft, can you remove it?

err := errors.New("feature support is only provided in SLSA_VERIFIER_EXPERIMENTAL mode")
printFailed(err)
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved
return nil, err
}
vsaOpts := &options.VSAOpts{
ExpectedDigests: c.SubjectDigests,
ExpectedVerifierID: c.VerifierID,
ExpectedResourceURI: c.ResourceURI,
ExpectedVerifiedLevels: c.VerifiedLevels,
}
pubKeyBytes, err := os.ReadFile(*c.PublicKeyPath)
if err != nil {
printFailed(err)
return nil, err
}
pubKey, err := cryptoutils.UnmarshalPEMToPublicKey(pubKeyBytes)
if err != nil {
err = fmt.Errorf("%w: %w", serrors.ErrorInvalidPublicKey, err)
printFailed(err)
return nil, err
}
hashHalgo, ok := hashAlgos[*c.PublicKeyHashAlgo]
ramonpetgrave64 marked this conversation as resolved.
Show resolved Hide resolved
if !ok {
err := fmt.Errorf("%w: %s", serrors.ErrorInvalidHashAlgo, *c.PublicKeyHashAlgo)
printFailed(err)
return nil, err
}
VerificationOpts := &options.VerificationOpts{
PublicKey: pubKey,
PublicKeyID: c.PublicKeyID,
PublicKeyHashAlgo: hashHalgo,
}
attestations, err := os.ReadFile(*c.AttestationsPath)
if err != nil {
printFailed(err)
return nil, err
}
verifiedProvenance, outProducerID, err := verifiers.VerifyVSA(ctx, attestations, vsaOpts, VerificationOpts)
if err != nil {
printFailed(err)
return nil, err
}
if c.PrintAttestation {
fmt.Fprintf(os.Stdout, "%s\n", string(verifiedProvenance))
}
fmt.Fprintf(os.Stderr, "Verifying VSA: PASSED\n\n")
loosebazooka marked this conversation as resolved.
Show resolved Hide resolved
// verfiers.VerifyVSA already checks if the producerID matches
return outProducerID, nil
}

// printFailed prints the error message to stderr.
func printFailed(err error) {
fmt.Fprintf(os.Stderr, "Verifying VSA: FAILED: %v\n\n", err)
}
6 changes: 6 additions & 0 deletions errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,10 @@ var (
ErrorInvalidHash = errors.New("invalid hash")
ErrorNotPresent = errors.New("not present")
ErrorInvalidPublicKey = errors.New("invalid public key")
ErrorInvalidHashAlgo = errors.New("unsupported hash algorithm")
ErrorMismatchSLSAResult = errors.New("SLSA result does not match")
ErrorMismatchVerifiedLevels = errors.New("verified levels do not match")
ErrorMissingSubjectDigest = errors.New("missing subject digest")
ErrorMismatchResourceURI = errors.New("resource URI does not match")
ErrorMismatchVerifierID = errors.New("verifier ID does not match")
)
Loading
Loading