mirror of
https://github.com/slsa-framework/slsa-verifier.git
synced 2026-08-19 11:36:49 +00:00
fix: use a uniform verifier interface for provenance type (#478)
* cleanup: use a uniform verifier interface for provenance type Signed-off-by: Asra Ali <asraa@google.com> * fix experimental gateg Signed-off-by: Asra Ali <asraa@google.com> * oops Signed-off-by: Asra Ali <asraa@google.com> --------- Signed-off-by: Asra Ali <asraa@google.com>
This commit is contained in:
@@ -16,10 +16,6 @@ func check(err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func ExperimentalEnabled() bool {
|
||||
return os.Getenv("SLSA_VERIFIER_EXPERIMENTAL") == "1"
|
||||
}
|
||||
|
||||
func rootCmd() *cobra.Command {
|
||||
c := &cobra.Command{
|
||||
Use: "slsa-verifier",
|
||||
|
||||
@@ -43,7 +43,6 @@ 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(),
|
||||
@@ -61,21 +60,6 @@ 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)
|
||||
@@ -86,6 +70,8 @@ func verifyArtifactCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
o.AddFlags(cmd)
|
||||
// --provenance-path must be supplied when verifying an artifact.
|
||||
cmd.MarkFlagRequired("provenance-path")
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ type VerifyOptions struct {
|
||||
BuilderID string
|
||||
/* Other */
|
||||
ProvenancePath string
|
||||
BundlePath string
|
||||
PrintProvenance bool
|
||||
}
|
||||
|
||||
@@ -68,17 +67,11 @@ 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 {
|
||||
|
||||
@@ -30,7 +30,6 @@ 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
|
||||
@@ -63,20 +62,10 @@ func (c *VerifyArtifactCommand) Exec(ctx context.Context, artifacts []string) (*
|
||||
ExpectedID: c.BuilderID,
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
verifiedProvenance, outBuilderID, err := verifiers.VerifyArtifact(ctx, provenance, artifactHash, provenanceOpts, builderOpts)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package options
|
||||
|
||||
import "os"
|
||||
|
||||
func ExperimentalEnabled() bool {
|
||||
return os.Getenv("SLSA_VERIFIER_EXPERIMENTAL") == "1"
|
||||
}
|
||||
@@ -23,9 +23,6 @@ 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.
|
||||
|
||||
@@ -24,6 +24,15 @@ var (
|
||||
ErrorUnexpectedBundleContent = errors.New("expected DSSE bundle content")
|
||||
)
|
||||
|
||||
// IsSigstoreBundle checks if the provenance is a Sigstore bundle.
|
||||
func IsSigstoreBundle(bytes []byte) bool {
|
||||
var bundle bundle_v1.Bundle
|
||||
if err := protojson.Unmarshal(bytes, &bundle); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// verifyRekorEntryFromBundle extracts and verifies the Rekor entry from the Sigstore
|
||||
// bundle verification material, validating the SignedEntryTimestamp.
|
||||
func verifyRekorEntryFromBundle(ctx context.Context, tlogEntry *v1.TransparencyLogEntry,
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -85,6 +86,11 @@ func (v *GHAVerifier) VerifyArtifact(ctx context.Context,
|
||||
provenanceOpts *options.ProvenanceOpts,
|
||||
builderOpts *options.BuilderOpts,
|
||||
) ([]byte, *utils.TrustedBuilderID, error) {
|
||||
isSigstoreBundle := IsSigstoreBundle(provenance)
|
||||
if isSigstoreBundle && !options.ExperimentalEnabled() {
|
||||
return nil, nil, errors.New("sigstore bundle support is only provided in SLSA_VERIFIER_EXPERIMENTAL mode")
|
||||
}
|
||||
|
||||
// This includes a default retry count of 3.
|
||||
rClient, err := client.GetRekorClient(defaultRekorAddr)
|
||||
if err != nil {
|
||||
@@ -98,9 +104,8 @@ func (v *GHAVerifier) VerifyArtifact(ctx context.Context,
|
||||
|
||||
var signedAtt *SignedAttestation
|
||||
/* Verify signature on the intoto attestation. */
|
||||
if provenanceOpts.ProvenanceBundle != nil {
|
||||
signedAtt, err = VerifyProvenanceBundle(ctx, provenanceOpts.ProvenanceBundle,
|
||||
trustedRoot)
|
||||
if isSigstoreBundle {
|
||||
signedAtt, err = VerifyProvenanceBundle(ctx, provenance, trustedRoot)
|
||||
} else {
|
||||
signedAtt, err = VerifyProvenanceSignature(ctx, trustedRoot, rClient,
|
||||
provenance, artifactHash)
|
||||
|
||||
Reference in New Issue
Block a user