feat: fixes #724: add input for --provenance-repository while image verification (#736)

@laurentsimon Added a new image verification cmd input
`--provenance-repository`
This replicates the feature of the `COSIGN_REPOSITORY` environment
variable when provenance is stored in a different repository/registry

Order of precedence:
- If input `--provenance-repository` is set, leverages the non-empty
input value
- If the env variable `COSIGN_REPOSITORY` is set, it is NOT consumed

README edit :
https://github.com/slsa-framework/slsa-verifier/pull/736/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R280

---------

Signed-off-by: saisatishkarra <saisatish.karra@konghq.com>
Co-authored-by: laurentsimon <64505099+laurentsimon@users.noreply.github.com>
This commit is contained in:
saisatishkarra
2024-01-22 12:10:11 -06:00
committed by GitHub
parent ceaebee236
commit 9b2467f836
6 changed files with 61 additions and 22 deletions

View File

@@ -262,6 +262,28 @@ The only requirement is that the provenance file covers all artifacts passed as
To verify a container image, you need to pass a container image name that is _immutable_ by providing its digest, in order to avoid [TOCTOU attacks](#toctou-attacks).
#### The verify-image command
```bash
$ slsa-verifier verify-image --help
Verifies SLSA provenance for an image
Usage:
slsa-verifier verify-image [flags] tarball
Flags:
--build-workflow-input map[] [optional] a workflow input provided by a user at trigger time in the format 'key=value'. (Only for 'workflow_dispatch' events on GitHub Actions). (default map[])
--builder-id string [optional] the unique builder ID who created the provenance
-h, --help help for verify-npm-package
--print-provenance [optional] print the verified provenance to stdout
--provenance-path string path to a provenance file
--provenance-repository string [optional] provenance repository when stored different from image repository. When set, overrides COSIGN_REPOSITORY environment variable
--source-branch string [optional] expected branch the binary was compiled from
--source-tag string [optional] expected tag the binary was compiled from
--source-uri string expected source repository that should have produced the binary, e.g. github.com/some/repo
--source-versioned-tag string [optional] expected version the binary was compiled from. Uses semantic version to match the tag
```
First set the image name:
```shell

View File

@@ -96,6 +96,9 @@ func verifyImageCmd() *cobra.Command {
if cmd.Flags().Changed("provenance-path") {
v.ProvenancePath = &o.ProvenancePath
}
if cmd.Flags().Changed("provenance-repository") {
v.ProvenanceRepository = &o.ProvenanceRepository
}
if cmd.Flags().Changed("source-branch") {
v.SourceBranch = &o.SourceBranch
}

View File

@@ -38,8 +38,9 @@ type VerifyOptions struct {
BuildWorkflowInputs workflowInputs
BuilderID string
/* Other */
ProvenancePath string
PrintProvenance bool
ProvenancePath string
ProvenanceRepository string
PrintProvenance bool
}
var _ Interface = (*VerifyOptions)(nil)
@@ -67,6 +68,9 @@ func (o *VerifyOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.ProvenancePath, "provenance-path", "",
"path to a provenance file")
cmd.Flags().StringVar(&o.ProvenanceRepository, "provenance-repository", "",
"image repository for provenance with format: <registry>/<repository>")
cmd.Flags().BoolVar(&o.PrintProvenance, "print-provenance", false,
"[optional] print the verified provenance to stdout")

View File

@@ -30,14 +30,15 @@ type ComputeDigestFn func(string) (string, error)
// Note: nil branch, tag, version-tag and builder-id means we ignore them during verification.
type VerifyImageCommand struct {
// May be nil if supplied alongside in the registry
ProvenancePath *string
BuilderID *string
SourceURI string
SourceBranch *string
SourceTag *string
SourceVersionTag *string
BuildWorkflowInputs map[string]string
PrintProvenance bool
ProvenancePath *string
ProvenanceRepository *string
BuilderID *string
SourceURI string
SourceBranch *string
SourceTag *string
SourceVersionTag *string
BuildWorkflowInputs map[string]string
PrintProvenance bool
}
func (c *VerifyImageCommand) Exec(ctx context.Context, artifacts []string) (*utils.TrustedBuilderID, error) {
@@ -50,12 +51,13 @@ func (c *VerifyImageCommand) Exec(ctx context.Context, artifacts []string) (*uti
}
provenanceOpts := &options.ProvenanceOpts{
ExpectedSourceURI: c.SourceURI,
ExpectedBranch: c.SourceBranch,
ExpectedDigest: digest,
ExpectedVersionedTag: c.SourceVersionTag,
ExpectedTag: c.SourceTag,
ExpectedWorkflowInputs: c.BuildWorkflowInputs,
ExpectedSourceURI: c.SourceURI,
ExpectedBranch: c.SourceBranch,
ExpectedDigest: digest,
ExpectedVersionedTag: c.SourceVersionTag,
ExpectedTag: c.SourceTag,
ExpectedProvenanceRepository: c.ProvenanceRepository,
ExpectedWorkflowInputs: c.BuildWorkflowInputs,
}
builderOpts := &options.BuilderOpts{
@@ -71,6 +73,7 @@ func (c *VerifyImageCommand) Exec(ctx context.Context, artifacts []string) (*uti
}
verifiedProvenance, outBuilderID, err := verifiers.VerifyImage(ctx, artifacts[0], provenance, provenanceOpts, builderOpts)
if err != nil {
return nil, err
}

View File

@@ -27,6 +27,9 @@ type ProvenanceOpts struct {
ExpectedPackageName *string
ExpectedPackageVersion *string
// ExpectedProvenanceRepository is the provenance repository that is passed from user and not verified
ExpectedProvenanceRepository *string
}
// BuildOpts are the options for checking the builder.

View File

@@ -9,6 +9,7 @@ import (
"os"
"strings"
"github.com/google/go-containerregistry/pkg/name"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
"github.com/sigstore/cosign/v2/pkg/cosign"
"github.com/sigstore/rekor/pkg/client"
@@ -245,8 +246,7 @@ func (v *GHAVerifier) VerifyArtifact(ctx context.Context,
// VerifyImage verifies provenance for an OCI image.
func (v *GHAVerifier) VerifyImage(ctx context.Context,
provenance []byte, artifactImage string,
provenanceOpts *options.ProvenanceOpts,
provenance []byte, artifactImage string, provenanceOpts *options.ProvenanceOpts,
builderOpts *options.BuilderOpts,
) ([]byte, *utils.TrustedBuilderID, error) {
/* Retrieve any valid signed attestations that chain up to Fulcio root CA. */
@@ -255,10 +255,13 @@ func (v *GHAVerifier) VerifyImage(ctx context.Context,
return nil, nil, err
}
// Parse any provenance target repository set using environment variable COSIGN_REPOSITORY
provenanceTargetRepository, err := ociremote.GetEnvTargetRepository()
if err != nil {
return nil, nil, err
var provenanceTargetRepository name.Repository
// Consume input for --provenance-repository when set
if provenanceOpts.ExpectedProvenanceRepository != nil {
provenanceTargetRepository, err = name.NewRepository(*provenanceOpts.ExpectedProvenanceRepository)
if err != nil {
return nil, nil, err
}
}
registryClientOpts := []ociremote.Option{}
@@ -276,6 +279,7 @@ func (v *GHAVerifier) VerifyImage(ctx context.Context,
RekorPubKeys: trustedRoot.RekorPubKeys,
CTLogPubKeys: trustedRoot.CTPubKeys,
}
atts, _, err := container.RunCosignImageVerification(ctx,
artifactImage, opts)
if err != nil {