Fix attestation cmd offline unit test failure (#8933)

* pass policy to Verify method

Signed-off-by: Meredith Lancaster <malancas@github.com>

* remove policy argument from SigstoreVerifier constructor

Signed-off-by: Meredith Lancaster <malancas@github.com>

* add SigstoreVerifier interface and introduce mock SigstoreVerifier struct for unit testing

Signed-off-by: Meredith Lancaster <malancas@github.com>

* gofmt

Signed-off-by: Meredith Lancaster <malancas@github.com>

* rename LiveSigstoreVerifier constructor

Signed-off-by: Meredith Lancaster <malancas@github.com>

* pr feedback, add todos for tests that need to be reimplemented

Signed-off-by: Meredith Lancaster <malancas@github.com>

* remove unused import

Signed-off-by: Meredith Lancaster <malancas@github.com>

* add more missing TODO statements

Signed-off-by: Meredith Lancaster <malancas@github.com>

* update skipped test

Signed-off-by: Meredith Lancaster <malancas@github.com>

---------

Signed-off-by: Meredith Lancaster <malancas@github.com>
This commit is contained in:
Meredith Lancaster 2024-04-11 18:09:10 -06:00 committed by GitHub
parent 88a7e529ab
commit 02158e896b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 288 additions and 181 deletions

View file

@ -1,11 +1,9 @@
package api
import (
"encoding/json"
"fmt"
"os"
"github.com/sigstore/sigstore-go/pkg/bundle"
"github.com/cli/cli/v2/pkg/cmd/attestation/test/data"
)
type MockClient struct {
@ -22,18 +20,7 @@ func (m MockClient) GetByOwnerAndDigest(owner, digest string, limit int) ([]*Att
}
func makeTestAttestation() Attestation {
bundleBytes, err := os.ReadFile("../test/data/sigstore-js-2.1.0-bundle.json")
if err != nil {
panic(err)
}
var b *bundle.ProtobufBundle
err = json.Unmarshal(bundleBytes, &b)
if err != nil {
panic(err)
}
return Attestation{Bundle: b}
return Attestation{Bundle: data.SigstoreBundle(nil)}
}
func OnGetByRepoAndDigestSuccess(repo, digest string, limit int) ([]*Attestation, error) {

View file

@ -73,6 +73,17 @@ func NewInspectCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Command
return runF(opts)
}
config := verification.SigstoreConfig{
Logger: opts.Logger,
}
sigstore, err := verification.NewLiveSigstoreVerifier(config)
if err != nil {
return err
}
opts.SigstoreVerifier = sigstore
if err := runInspect(opts); err != nil {
return fmt.Errorf("Failed to inspect the artifact and bundle: %w", err)
}
@ -101,21 +112,12 @@ func runInspect(opts *Options) error {
return fmt.Errorf("failed to read attestations for subject: %s", artifact.DigestWithAlg())
}
config := verification.SigstoreConfig{
Logger: opts.Logger,
}
policy, err := buildPolicy(*artifact)
if err != nil {
return fmt.Errorf("failed to build policy: %v", err)
}
sigstore, err := verification.NewSigstoreVerifier(config, policy)
if err != nil {
return err
}
res := sigstore.Verify(attestations)
res := opts.SigstoreVerifier.Verify(attestations, policy)
if res.Error != nil {
return fmt.Errorf("at least one attestation failed to verify against Sigstore: %v", res.Error)
}

View file

@ -11,6 +11,7 @@ import (
"github.com/cli/cli/v2/pkg/cmd/attestation/artifact/oci"
"github.com/cli/cli/v2/pkg/cmd/attestation/io"
"github.com/cli/cli/v2/pkg/cmd/attestation/test"
"github.com/cli/cli/v2/pkg/cmd/attestation/verification"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/httpmock"
@ -53,10 +54,11 @@ func TestNewInspectCmd(t *testing.T) {
name: "Invalid digest-alg flag",
cli: fmt.Sprintf("%s --bundle %s --digest-alg sha384", artifactPath, bundlePath),
wants: Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha384",
OCIClient: oci.MockClient{},
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha384",
OCIClient: oci.MockClient{},
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: true,
},
@ -64,10 +66,11 @@ func TestNewInspectCmd(t *testing.T) {
name: "Use default digest-alg value",
cli: fmt.Sprintf("%s --bundle %s", artifactPath, bundlePath),
wants: Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha256",
OCIClient: oci.MockClient{},
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha256",
OCIClient: oci.MockClient{},
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: false,
},
@ -75,10 +78,11 @@ func TestNewInspectCmd(t *testing.T) {
name: "Use custom digest-alg value",
cli: fmt.Sprintf("%s --bundle %s --digest-alg sha512", artifactPath, bundlePath),
wants: Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
OCIClient: oci.MockClient{},
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
OCIClient: oci.MockClient{},
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: false,
},
@ -86,9 +90,10 @@ func TestNewInspectCmd(t *testing.T) {
name: "Missing bundle flag",
cli: artifactPath,
wants: Options{
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
OCIClient: oci.MockClient{},
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
OCIClient: oci.MockClient{},
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: true,
},
@ -96,10 +101,11 @@ func TestNewInspectCmd(t *testing.T) {
name: "Prints output in JSON format",
cli: fmt.Sprintf("%s --bundle %s --format json", artifactPath, bundlePath),
wants: Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha256",
OCIClient: oci.MockClient{},
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha256",
OCIClient: oci.MockClient{},
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsExporter: true,
},
@ -128,8 +134,8 @@ func TestNewInspectCmd(t *testing.T) {
assert.Equal(t, tc.wants.ArtifactPath, opts.ArtifactPath)
assert.Equal(t, tc.wants.BundlePath, opts.BundlePath)
assert.Equal(t, tc.wants.DigestAlgorithm, opts.DigestAlgorithm)
assert.NotNil(t, opts.OCIClient)
assert.NotNil(t, opts.Logger)
assert.NotNil(t, opts.OCIClient)
assert.Equal(t, tc.wantsExporter, opts.exporter != nil)
})
}
@ -137,11 +143,12 @@ func TestNewInspectCmd(t *testing.T) {
func TestRunInspect(t *testing.T) {
opts := Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
Logger: io.NewTestHandler(),
OCIClient: oci.MockClient{},
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
Logger: io.NewTestHandler(),
OCIClient: oci.MockClient{},
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
}
t.Run("with valid artifact and bundle", func(t *testing.T) {
@ -164,12 +171,13 @@ func TestRunInspect(t *testing.T) {
func TestJSONOutput(t *testing.T) {
testIO, _, out, _ := iostreams.Test()
opts := Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
Logger: io.NewHandler(testIO),
OCIClient: oci.MockClient{},
exporter: cmdutil.NewJSONExporter(),
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
Logger: io.NewHandler(testIO),
OCIClient: oci.MockClient{},
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
exporter: cmdutil.NewJSONExporter(),
}
require.Nil(t, runInspect(&opts))

View file

@ -5,17 +5,19 @@ import (
"github.com/cli/cli/v2/pkg/cmd/attestation/artifact/oci"
"github.com/cli/cli/v2/pkg/cmd/attestation/io"
"github.com/cli/cli/v2/pkg/cmd/attestation/verification"
"github.com/cli/cli/v2/pkg/cmdutil"
)
// Options captures the options for the inspect command
type Options struct {
ArtifactPath string
BundlePath string
DigestAlgorithm string
Logger *io.Handler
OCIClient oci.Client
exporter cmdutil.Exporter
ArtifactPath string
BundlePath string
DigestAlgorithm string
Logger *io.Handler
OCIClient oci.Client
SigstoreVerifier verification.SigstoreVerifier
exporter cmdutil.Exporter
}
// Clean cleans the file path option values

View file

@ -0,0 +1,17 @@
package data
import (
_ "embed"
"testing"
"github.com/sigstore/sigstore-go/pkg/bundle"
sgData "github.com/sigstore/sigstore-go/pkg/testing/data"
)
//go:embed sigstore-js-2.1.0-bundle.json
var SigstoreBundleRaw []byte
// SigstoreBundle returns a test *sigstore.Bundle
func SigstoreBundle(t *testing.T) *bundle.ProtobufBundle {
return sgData.TestBundle(t, SigstoreBundleRaw)
}

View file

@ -0,0 +1,50 @@
package verification
import (
"fmt"
"testing"
"github.com/cli/cli/v2/pkg/cmd/attestation/api"
"github.com/cli/cli/v2/pkg/cmd/attestation/test/data"
"github.com/in-toto/in-toto-golang/in_toto"
"github.com/sigstore/sigstore-go/pkg/verify"
)
const SLSAPredicateType = "https://slsa.dev/provenance/v1"
type MockSigstoreVerifier struct {
t *testing.T
}
func (v *MockSigstoreVerifier) Verify(attestations []*api.Attestation, policy verify.PolicyBuilder) *SigstoreResults {
statement := &in_toto.Statement{}
statement.PredicateType = SLSAPredicateType
result := AttestationProcessingResult{
Attestation: &api.Attestation{
Bundle: data.SigstoreBundle(v.t),
},
VerificationResult: &verify.VerificationResult{
Statement: statement,
},
}
results := []*AttestationProcessingResult{&result}
return &SigstoreResults{
VerifyResults: results,
}
}
func NewMockSigstoreVerifier(t *testing.T) *MockSigstoreVerifier {
return &MockSigstoreVerifier{t}
}
type FailSigstoreVerifier struct{}
func (v *FailSigstoreVerifier) Verify(attestations []*api.Attestation, policy verify.PolicyBuilder) *SigstoreResults {
return &SigstoreResults{
Error: fmt.Errorf("failed to verify attestations"),
}
}

View file

@ -34,19 +34,22 @@ type SigstoreConfig struct {
NoPublicGood bool
}
type SigstoreVerifier struct {
type SigstoreVerifier interface {
Verify(attestations []*api.Attestation, policy verify.PolicyBuilder) *SigstoreResults
}
type LiveSigstoreVerifier struct {
ghVerifier *verify.SignedEntityVerifier
publicGoodVerifier *verify.SignedEntityVerifier
customVerifier *verify.SignedEntityVerifier
policy verify.PolicyBuilder
onlyVerifyWithGithub bool
Logger *io.Handler
}
// NewSigstoreVerifier creates a new SigstoreVerifier struct
// NewLiveSigstoreVerifier creates a new LiveSigstoreVerifier struct
// that is used to verify artifacts and attestations against the
// Public Good, GitHub, or a custom trusted root.
func NewSigstoreVerifier(config SigstoreConfig, policy verify.PolicyBuilder) (*SigstoreVerifier, error) {
func NewLiveSigstoreVerifier(config SigstoreConfig) (*LiveSigstoreVerifier, error) {
customVerifier, err := newCustomVerifier(config.CustomTrustedRoot)
if err != nil {
return nil, fmt.Errorf("failed to create custom verifier: %v", err)
@ -62,17 +65,16 @@ func NewSigstoreVerifier(config SigstoreConfig, policy verify.PolicyBuilder) (*S
return nil, fmt.Errorf("failed to create GitHub Sigstore verifier: %v", err)
}
return &SigstoreVerifier{
return &LiveSigstoreVerifier{
ghVerifier: ghVerifier,
publicGoodVerifier: publicGoodVerifier,
customVerifier: customVerifier,
Logger: config.Logger,
policy: policy,
onlyVerifyWithGithub: config.NoPublicGood,
}, nil
}
func (v *SigstoreVerifier) chooseVerifier(b *bundle.ProtobufBundle) (*verify.SignedEntityVerifier, string, error) {
func (v *LiveSigstoreVerifier) chooseVerifier(b *bundle.ProtobufBundle) (*verify.SignedEntityVerifier, string, error) {
verifyContent, err := b.VerificationContent()
if err != nil {
return nil, "", fmt.Errorf("failed to get bundle verification content: %v", err)
@ -103,7 +105,7 @@ func (v *SigstoreVerifier) chooseVerifier(b *bundle.ProtobufBundle) (*verify.Sig
return nil, "", fmt.Errorf("leaf certificate issuer is not recognized")
}
func (v *SigstoreVerifier) Verify(attestations []*api.Attestation) *SigstoreResults {
func (v *LiveSigstoreVerifier) Verify(attestations []*api.Attestation, policy verify.PolicyBuilder) *SigstoreResults {
// initialize the processing results before attempting to verify
// with multiple verifiers
results := make([]*AttestationProcessingResult, len(attestations))
@ -128,7 +130,7 @@ func (v *SigstoreVerifier) Verify(attestations []*api.Attestation) *SigstoreResu
v.Logger.VerbosePrintf("Attempting verification against issuer \"%s\"\n", issuer)
// attempt to verify the attestation
result, err := verifier.Verify(apr.Attestation.Bundle, v.policy)
result, err := verifier.Verify(apr.Attestation.Bundle, policy)
// if verification fails, create the error and exit verification early
if err != nil {
v.Logger.VerbosePrint(v.Logger.ColorScheme.Redf(

View file

@ -21,7 +21,7 @@ func buildPolicy(a artifact.DigestedArtifact) (verify.PolicyBuilder, error) {
return policy, nil
}
func TestNewSigstoreVerifier(t *testing.T) {
func TestNewLiveSigstoreVerifier(t *testing.T) {
artifactPath := test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0.tgz")
artifact, err := artifact.NewDigestedArtifact(nil, artifactPath, "sha512")
require.NoError(t, err)
@ -32,7 +32,7 @@ func TestNewSigstoreVerifier(t *testing.T) {
c := SigstoreConfig{
Logger: io.NewTestHandler(),
}
verifier, err := NewSigstoreVerifier(c, policy)
verifier, err := NewLiveSigstoreVerifier(c)
require.NoError(t, err)
t.Run("with invalid signature", func(t *testing.T) {
@ -41,7 +41,7 @@ func TestNewSigstoreVerifier(t *testing.T) {
require.NotNil(t, attestations)
require.NoError(t, err)
res := verifier.Verify(attestations)
res := verifier.Verify(attestations, policy)
require.Error(t, res.Error)
require.ErrorContains(t, res.Error, "verifying with issuer \"sigstore.dev\"")
require.Nil(t, res.VerifyResults)
@ -53,7 +53,7 @@ func TestNewSigstoreVerifier(t *testing.T) {
require.Len(t, attestations, 2)
require.NoError(t, err)
res := verifier.Verify(attestations)
res := verifier.Verify(attestations, policy)
require.Len(t, res.VerifyResults, 2)
require.NoError(t, res.Error)
})

View file

@ -8,6 +8,7 @@ import (
"github.com/cli/cli/v2/pkg/cmd/attestation/api"
"github.com/cli/cli/v2/pkg/cmd/attestation/artifact/oci"
"github.com/cli/cli/v2/pkg/cmd/attestation/io"
"github.com/cli/cli/v2/pkg/cmd/attestation/verification"
"github.com/cli/cli/v2/pkg/cmdutil"
)
@ -18,6 +19,7 @@ type Options struct {
CustomTrustedRoot string
DenySelfHostedRunner bool
DigestAlgorithm string
Limit int
NoPublicGood bool
OIDCIssuer string
Owner string
@ -26,8 +28,8 @@ type Options struct {
SANRegex string
APIClient api.Client
Logger *io.Handler
Limit int
OCIClient oci.Client
SigstoreVerifier verification.SigstoreVerifier
exporter cmdutil.Exporter
}

View file

@ -1,7 +1,6 @@
package verify
import (
// "encoding/json"
"errors"
"fmt"
@ -106,6 +105,19 @@ func NewVerifyCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Command
return runF(opts)
}
config := verification.SigstoreConfig{
CustomTrustedRoot: opts.CustomTrustedRoot,
Logger: opts.Logger,
NoPublicGood: opts.NoPublicGood,
}
sv, err := verification.NewLiveSigstoreVerifier(config)
if err != nil {
return err
}
opts.SigstoreVerifier = sv
if err := runVerify(opts); err != nil {
return fmt.Errorf("Failed to verify the artifact: %v", err)
}
@ -163,18 +175,7 @@ func runVerify(opts *Options) error {
return fmt.Errorf("failed to build policy: %v", err)
}
config := verification.SigstoreConfig{
CustomTrustedRoot: opts.CustomTrustedRoot,
Logger: opts.Logger,
NoPublicGood: opts.NoPublicGood,
}
sv, err := verification.NewSigstoreVerifier(config, policy)
if err != nil {
return err
}
sigstoreRes := sv.Verify(attestations)
sigstoreRes := opts.SigstoreVerifier.Verify(attestations, policy)
if sigstoreRes.Error != nil {
return fmt.Errorf("at least one attestation failed to verify against Sigstore: %v", sigstoreRes.Error)
}

View file

@ -58,12 +58,13 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Invalid digest-alg flag",
cli: fmt.Sprintf("%s --bundle %s --digest-alg sha384 --owner sigstore", artifactPath, bundlePath),
wants: Options{
ArtifactPath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0.tgz"),
BundlePath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0-bundle.json"),
DigestAlgorithm: "sha384",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
ArtifactPath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0.tgz"),
BundlePath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0-bundle.json"),
DigestAlgorithm: "sha384",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: true,
},
@ -71,13 +72,14 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Use default digest-alg value",
cli: fmt.Sprintf("%s --bundle %s --owner sigstore", artifactPath, bundlePath),
wants: Options{
ArtifactPath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0.tgz"),
BundlePath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0-bundle.json"),
DigestAlgorithm: "sha256",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
ArtifactPath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0.tgz"),
BundlePath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0-bundle.json"),
DigestAlgorithm: "sha256",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: false,
},
@ -85,13 +87,14 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Use custom digest-alg value",
cli: fmt.Sprintf("%s --bundle %s --owner sigstore --digest-alg sha512", artifactPath, bundlePath),
wants: Options{
ArtifactPath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0.tgz"),
BundlePath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0-bundle.json"),
DigestAlgorithm: "sha512",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
ArtifactPath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0.tgz"),
BundlePath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0-bundle.json"),
DigestAlgorithm: "sha512",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: false,
},
@ -99,12 +102,13 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Missing owner and repo flags",
cli: artifactPath,
wants: Options{
ArtifactPath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0.tgz"),
DigestAlgorithm: "sha256",
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
Limit: 30,
SANRegex: "^https://github.com/sigstore/",
ArtifactPath: test.NormalizeRelativePath("../test/data/sigstore-js-2.1.0.tgz"),
DigestAlgorithm: "sha256",
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
Limit: 30,
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: true,
},
@ -112,12 +116,13 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Has both owner and repo flags",
cli: fmt.Sprintf("%s --owner sigstore --repo sigstore/sigstore-js", artifactPath),
wants: Options{
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
Repo: "sigstore/sigstore-js",
Limit: 30,
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
Repo: "sigstore/sigstore-js",
Limit: 30,
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: true,
},
@ -125,12 +130,13 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Uses default limit flag",
cli: fmt.Sprintf("%s --owner sigstore", artifactPath),
wants: Options{
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: false,
},
@ -138,12 +144,13 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Uses custom limit flag",
cli: fmt.Sprintf("%s --owner sigstore --limit 101", artifactPath),
wants: Options{
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
Limit: 101,
SANRegex: "^https://github.com/sigstore/",
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
Limit: 101,
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: false,
},
@ -151,12 +158,13 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Uses invalid limit flag",
cli: fmt.Sprintf("%s --owner sigstore --limit 0", artifactPath),
wants: Options{
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
Limit: 0,
SANRegex: "^https://github.com/sigstore/",
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
Limit: 0,
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: true,
},
@ -164,13 +172,14 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Has both cert-identity and cert-identity-regex flags",
cli: fmt.Sprintf("%s --owner sigstore --cert-identity https://github.com/sigstore/ --cert-identity-regex ^https://github.com/sigstore/", artifactPath),
wants: Options{
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SAN: "https://github.com/sigstore/",
SANRegex: "^https://github.com/sigstore/",
ArtifactPath: artifactPath,
DigestAlgorithm: "sha256",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SAN: "https://github.com/sigstore/",
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsErr: true,
},
@ -178,13 +187,14 @@ func TestNewVerifyCmd(t *testing.T) {
name: "Prints output in JSON format",
cli: fmt.Sprintf("%s --bundle %s --owner sigstore --format json", artifactPath, bundlePath),
wants: Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha256",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha256",
Limit: 30,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
},
wantsExporter: true,
},
@ -233,16 +243,17 @@ func TestNewVerifyCmd(t *testing.T) {
func TestJSONOutput(t *testing.T) {
testIO, _, out, _ := iostreams.Test()
opts := Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
APIClient: api.NewTestClient(),
Logger: io.NewHandler(testIO),
OCIClient: oci.MockClient{},
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
exporter: cmdutil.NewJSONExporter(),
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
APIClient: api.NewTestClient(),
Logger: io.NewHandler(testIO),
OCIClient: oci.MockClient{},
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
exporter: cmdutil.NewJSONExporter(),
}
require.Nil(t, runVerify(&opts))
@ -255,15 +266,16 @@ func TestRunVerify(t *testing.T) {
logger := io.NewTestHandler()
publicGoodOpts := Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
APIClient: api.NewTestClient(),
Logger: logger,
OCIClient: oci.MockClient{},
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
ArtifactPath: artifactPath,
BundlePath: bundlePath,
DigestAlgorithm: "sha512",
APIClient: api.NewTestClient(),
Logger: logger,
OCIClient: oci.MockClient{},
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SANRegex: "^https://github.com/sigstore/",
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
}
t.Run("with valid artifact and bundle", func(t *testing.T) {
@ -330,48 +342,72 @@ func TestRunVerify(t *testing.T) {
require.ErrorContains(t, err, "failed to fetch attestations for subject")
})
// TODO: this test can only be tested with a live SigstoreVerifier
// add integration tests or HTTP mocked sigstore verifier tests
// to test this case
t.Run("with invalid OIDC issuer", func(t *testing.T) {
t.Skip()
opts := publicGoodOpts
opts.OIDCIssuer = "not-a-real-issuer"
require.Error(t, runVerify(&opts))
})
// TODO: this test can only be tested with a live SigstoreVerifier
// add integration tests or HTTP mocked sigstore verifier tests
// to test this case
t.Run("with SAN enforcement", func(t *testing.T) {
t.Skip()
opts := Options{
ArtifactPath: artifactPath,
BundlePath: bundlePath,
APIClient: api.NewTestClient(),
DigestAlgorithm: "sha512",
Logger: logger,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SAN: SigstoreSanValue,
ArtifactPath: artifactPath,
BundlePath: bundlePath,
APIClient: api.NewTestClient(),
DigestAlgorithm: "sha512",
Logger: logger,
OIDCIssuer: GitHubOIDCIssuer,
Owner: "sigstore",
SAN: SigstoreSanValue,
SigstoreVerifier: verification.NewMockSigstoreVerifier(t),
}
require.Nil(t, runVerify(&opts))
})
// TODO: this test can only be tested with a live SigstoreVerifier
// add integration tests or HTTP mocked sigstore verifier tests
// to test this case
t.Run("with invalid SAN", func(t *testing.T) {
t.Skip()
opts := publicGoodOpts
opts.SAN = "fake san"
require.Error(t, runVerify(&opts))
})
// TODO: this test can only be tested with a live SigstoreVerifier
// add integration tests or HTTP mocked sigstore verifier tests
// to test this case
t.Run("with SAN regex enforcement", func(t *testing.T) {
t.Skip()
opts := publicGoodOpts
opts.SANRegex = SigstoreSanRegex
require.Nil(t, runVerify(&opts))
})
// TODO: this test can only be tested with a live SigstoreVerifier
// add integration tests or HTTP mocked sigstore verifier tests
// to test this case
t.Run("with invalid SAN regex", func(t *testing.T) {
t.Skip()
opts := publicGoodOpts
opts.SANRegex = "^https://github.com/sigstore/not-real/"
require.Error(t, runVerify(&opts))
})
// TODO: this test can only be tested with a live SigstoreVerifier
// add integration tests or HTTP mocked sigstore verifier tests
// to test this case
t.Run("with no matching OIDC issuer", func(t *testing.T) {
t.Skip()
opts := publicGoodOpts
opts.OIDCIssuer = "some-other-issuer"
require.Error(t, runVerify(&opts))
})