From 515807635a09e00edd4b7a7debf111936fa6b4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= Date: Sat, 7 Jan 2023 02:22:49 +0100 Subject: [PATCH] Add functional-option NewPRSigstoreSigned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Possibly reject nil values of pointer fields at input? Signed-off-by: Miloslav Trmač --- signature/policy_config_sigstore.go | 110 ++++++++++++------ signature/policy_config_sigstore_test.go | 86 +++++++++----- signature/policy_config_test.go | 12 +- signature/policy_eval_sigstore_test.go | 137 ++++++++++++++++++----- 4 files changed, 245 insertions(+), 100 deletions(-) diff --git a/signature/policy_config_sigstore.go b/signature/policy_config_sigstore.go index 6171fccc4..b895a8738 100644 --- a/signature/policy_config_sigstore.go +++ b/signature/policy_config_sigstore.go @@ -2,48 +2,90 @@ package signature import ( "encoding/json" + "errors" "fmt" "github.com/containers/image/v5/signature/internal" ) -// newPRSigstoreSigned returns a new prSigstoreSigned if parameters are valid. -func newPRSigstoreSigned(keyPath string, keyData []byte, signedIdentity PolicyReferenceMatch) (*prSigstoreSigned, error) { - if keyPath != "" && keyData != nil { +// PRSigstoreSignedOption is way to pass values to NewPRSigstoreSigned +type PRSigstoreSignedOption func(*prSigstoreSigned) error + +// PRSigstoreSignedWithKeyPath specifies a value for the "keyPath" field when calling NewPRSigstoreSigned. +func PRSigstoreSignedWithKeyPath(keyPath string) PRSigstoreSignedOption { + return func(pr *prSigstoreSigned) error { + if pr.KeyPath != "" { + return errors.New(`"keyPath" already specified`) + } + pr.KeyPath = keyPath + return nil + } +} + +// PRSigstoreSignedWithKeyData specifies a value for the "keyData" field when calling NewPRSigstoreSigned. +func PRSigstoreSignedWithKeyData(keyData []byte) PRSigstoreSignedOption { + return func(pr *prSigstoreSigned) error { + if pr.KeyData != nil { + return errors.New(`"keyData" already specified`) + } + pr.KeyData = keyData + return nil + } +} + +// PRSigstoreSignedWithSignedIdentity specifies a value for the "signedIdentity" field when calling NewPRSigstoreSigned. +func PRSigstoreSignedWithSignedIdentity(signedIdentity PolicyReferenceMatch) PRSigstoreSignedOption { + return func(pr *prSigstoreSigned) error { + if pr.SignedIdentity != nil { + return errors.New(`"signedIdentity" already specified`) + } + pr.SignedIdentity = signedIdentity + return nil + } +} + +// newPRSigstoreSigned is NewPRSigstoreSigned, except it returns the private type. +func newPRSigstoreSigned(options ...PRSigstoreSignedOption) (*prSigstoreSigned, error) { + res := prSigstoreSigned{ + prCommon: prCommon{Type: prTypeSigstoreSigned}, + } + for _, o := range options { + if err := o(&res); err != nil { + return nil, err + } + } + if res.KeyPath != "" && res.KeyData != nil { return nil, InvalidPolicyFormatError("keyType and keyData cannot be used simultaneously") } - if keyPath == "" && keyData == nil { - return nil, InvalidPolicyFormatError("neither keyType nor keyData specified") + if res.KeyPath == "" && res.KeyData == nil { + return nil, InvalidPolicyFormatError("At least one of keyPath and keyData must be specified") } - if signedIdentity == nil { + if res.SignedIdentity == nil { return nil, InvalidPolicyFormatError("signedIdentity not specified") } - return &prSigstoreSigned{ - prCommon: prCommon{Type: prTypeSigstoreSigned}, - KeyPath: keyPath, - KeyData: keyData, - SignedIdentity: signedIdentity, - }, nil + + return &res, nil } -// newPRSigstoreSignedKeyPath is NewPRSigstoreSignedKeyPath, except it returns the private type. -func newPRSigstoreSignedKeyPath(keyPath string, signedIdentity PolicyReferenceMatch) (*prSigstoreSigned, error) { - return newPRSigstoreSigned(keyPath, nil, signedIdentity) +// NewPRSigstoreSigned returns a new "sigstoreSigned" PolicyRequirement based on options. +func NewPRSigstoreSigned(options ...PRSigstoreSignedOption) (PolicyRequirement, error) { + return newPRSigstoreSigned(options...) } // NewPRSigstoreSignedKeyPath returns a new "sigstoreSigned" PolicyRequirement using a KeyPath func NewPRSigstoreSignedKeyPath(keyPath string, signedIdentity PolicyReferenceMatch) (PolicyRequirement, error) { - return newPRSigstoreSignedKeyPath(keyPath, signedIdentity) -} - -// newPRSigstoreSignedKeyData is NewPRSigstoreSignedKeyData, except it returns the private type. -func newPRSigstoreSignedKeyData(keyData []byte, signedIdentity PolicyReferenceMatch) (*prSigstoreSigned, error) { - return newPRSigstoreSigned("", keyData, signedIdentity) + return NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath(keyPath), + PRSigstoreSignedWithSignedIdentity(signedIdentity), + ) } // NewPRSigstoreSignedKeyData returns a new "sigstoreSigned" PolicyRequirement using a KeyData func NewPRSigstoreSignedKeyData(keyData []byte, signedIdentity PolicyReferenceMatch) (PolicyRequirement, error) { - return newPRSigstoreSignedKeyData(keyData, signedIdentity) + return NewPRSigstoreSigned( + PRSigstoreSignedWithKeyData(keyData), + PRSigstoreSignedWithSignedIdentity(signedIdentity), + ) } // Compile-time check that prSigstoreSigned implements json.Unmarshaler. @@ -87,23 +129,17 @@ func (pr *prSigstoreSigned) UnmarshalJSON(data []byte) error { tmp.SignedIdentity = si } - var res *prSigstoreSigned - var err error - switch { - case gotKeyPath && gotKeyData: - return InvalidPolicyFormatError("keyPath and keyData cannot be used simultaneously") - case gotKeyPath && !gotKeyData: - res, err = newPRSigstoreSignedKeyPath(tmp.KeyPath, tmp.SignedIdentity) - case !gotKeyPath && gotKeyData: - res, err = newPRSigstoreSignedKeyData(tmp.KeyData, tmp.SignedIdentity) - case !gotKeyPath && !gotKeyData: - return InvalidPolicyFormatError("At least one of keyPath and keyData must be specified") - default: // Coverage: This should never happen - return fmt.Errorf("Impossible keyPath/keyData presence combination!?") + var opts []PRSigstoreSignedOption + if gotKeyPath { + opts = append(opts, PRSigstoreSignedWithKeyPath(tmp.KeyPath)) } + if gotKeyData { + opts = append(opts, PRSigstoreSignedWithKeyData(tmp.KeyData)) + } + opts = append(opts, PRSigstoreSignedWithSignedIdentity(tmp.SignedIdentity)) + + res, err := newPRSigstoreSigned(opts...) if err != nil { - // Coverage: This cannot currently happen, creating a prSigstoreSigned only fails - // if signedIdentity is nil, which we replace with a default above. return err } *pr = *res diff --git a/signature/policy_config_sigstore_test.go b/signature/policy_config_sigstore_test.go index cbfce8f46..43ffefcbe 100644 --- a/signature/policy_config_sigstore_test.go +++ b/signature/policy_config_sigstore_test.go @@ -8,20 +8,11 @@ import ( "github.com/stretchr/testify/require" ) -// xNewPRSigstoreSignedKeyPath is like NewPRSigstoreSignedKeyPath, except it must not fail. -func xNewPRSigstoreSignedKeyPath(keyPath string, signedIdentity PolicyReferenceMatch) PolicyRequirement { - pr, err := NewPRSigstoreSignedKeyPath(keyPath, signedIdentity) +// xNewPRSigstoreSigned is like NewPRSigstoreSigned, except it must not fail. +func xNewPRSigstoreSigned(options ...PRSigstoreSignedOption) PolicyRequirement { + pr, err := NewPRSigstoreSigned(options...) if err != nil { - panic("xNewPRSigstoreSignedKeyPath failed") - } - return pr -} - -// xNewPRSigstoreSignedKeyData is like NewPRSigstoreSignedKeyData, except it must not fail. -func xNewPRSigstoreSignedKeyData(keyData []byte, signedIdentity PolicyReferenceMatch) PolicyRequirement { - pr, err := NewPRSigstoreSignedKeyData(keyData, signedIdentity) - if err != nil { - panic("xNewPRSigstoreSignedKeyData failed") + panic("xNewPRSigstoreSigned failed") } return pr } @@ -32,7 +23,10 @@ func TestNewPRSigstoreSigned(t *testing.T) { testIdentity := NewPRMMatchRepoDigestOrExact() // Success - pr, err := newPRSigstoreSigned(testPath, nil, testIdentity) + pr, err := newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath(testPath), + PRSigstoreSignedWithSignedIdentity(testIdentity), + ) require.NoError(t, err) assert.Equal(t, &prSigstoreSigned{ prCommon: prCommon{prTypeSigstoreSigned}, @@ -40,7 +34,10 @@ func TestNewPRSigstoreSigned(t *testing.T) { KeyData: nil, SignedIdentity: testIdentity, }, pr) - pr, err = newPRSigstoreSigned("", testData, testIdentity) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyData(testData), + PRSigstoreSignedWithSignedIdentity(testIdentity), + ) require.NoError(t, err) assert.Equal(t, &prSigstoreSigned{ prCommon: prCommon{prTypeSigstoreSigned}, @@ -49,36 +46,63 @@ func TestNewPRSigstoreSigned(t *testing.T) { SignedIdentity: testIdentity, }, pr) - // Both keyPath and keyData specified - _, err = newPRSigstoreSigned(testPath, testData, testIdentity) - assert.Error(t, err) - // Neither keyPath nor keyData specified - _, err = newPRSigstoreSigned("", nil, testIdentity) - assert.Error(t, err) - - // Invalid signedIdentity - _, err = newPRSigstoreSigned(testPath, nil, nil) - assert.Error(t, err) + for _, c := range [][]PRSigstoreSignedOption{ + { // Both keyPath and keyData specified + PRSigstoreSignedWithKeyPath(testPath), + PRSigstoreSignedWithKeyData(testData), + PRSigstoreSignedWithSignedIdentity(testIdentity), + }, + {}, // Neither keyPath nor keyData specified + { // Duplicate keyPath + PRSigstoreSignedWithKeyPath(testPath), + PRSigstoreSignedWithKeyPath(testPath + "1"), + PRSigstoreSignedWithSignedIdentity(testIdentity), + }, + { // Duplicate keyData + PRSigstoreSignedWithKeyData(testData), + PRSigstoreSignedWithKeyData([]byte("def")), + PRSigstoreSignedWithSignedIdentity(testIdentity), + }, + { // Missing signedIdentity + PRSigstoreSignedWithKeyPath(testPath), + }, + { // Duplicate signedIdentity} + PRSigstoreSignedWithKeyPath(testPath), + PRSigstoreSignedWithSignedIdentity(testIdentity), + PRSigstoreSignedWithSignedIdentity(newPRMMatchRepository()), + }, + } { + _, err = newPRSigstoreSigned(c...) + assert.Error(t, err) + } } func TestNewPRSigstoreSignedKeyPath(t *testing.T) { const testPath = "/foo/bar" - _pr, err := NewPRSigstoreSignedKeyPath(testPath, NewPRMMatchRepoDigestOrExact()) + signedIdentity := NewPRMMatchRepoDigestOrExact() + _pr, err := NewPRSigstoreSignedKeyPath(testPath, signedIdentity) require.NoError(t, err) pr, ok := _pr.(*prSigstoreSigned) require.True(t, ok) - assert.Equal(t, testPath, pr.KeyPath) - // Failure cases tested in TestNewPRSigstoreSigned. + assert.Equal(t, &prSigstoreSigned{ + prCommon: prCommon{Type: prTypeSigstoreSigned}, + KeyPath: testPath, + SignedIdentity: NewPRMMatchRepoDigestOrExact(), + }, pr) } func TestNewPRSigstoreSignedKeyData(t *testing.T) { testData := []byte("abc") - _pr, err := NewPRSigstoreSignedKeyData(testData, NewPRMMatchRepoDigestOrExact()) + signedIdentity := NewPRMMatchRepoDigestOrExact() + _pr, err := NewPRSigstoreSignedKeyData(testData, signedIdentity) require.NoError(t, err) pr, ok := _pr.(*prSigstoreSigned) require.True(t, ok) - assert.Equal(t, testData, pr.KeyData) - // Failure cases tested in TestNewPRSigstoreSigned. + assert.Equal(t, &prSigstoreSigned{ + prCommon: prCommon{Type: prTypeSigstoreSigned}, + KeyData: testData, + SignedIdentity: NewPRMMatchRepoDigestOrExact(), + }, pr) } // Return the result of modifying validJSON with fn and unmarshaling it into *pr diff --git a/signature/policy_config_test.go b/signature/policy_config_test.go index 362c34402..9c1df74d5 100644 --- a/signature/policy_config_test.go +++ b/signature/policy_config_test.go @@ -104,12 +104,16 @@ var policyFixtureContents = &Policy{ xNewPRSignedBaseLayer(xNewPRMExactReference("registry.access.redhat.com/rhel7/rhel:latest")), }, "example.com/sigstore/key-data-example": { - xNewPRSigstoreSignedKeyData([]byte("nonsense"), - NewPRMMatchRepoDigestOrExact()), + xNewPRSigstoreSigned( + PRSigstoreSignedWithKeyData([]byte("nonsense")), + PRSigstoreSignedWithSignedIdentity(NewPRMMatchRepoDigestOrExact()), + ), }, "example.com/sigstore/key-path-example": { - xNewPRSigstoreSignedKeyPath("/keys/public-key", - NewPRMMatchRepository()), + xNewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("/keys/public-key"), + PRSigstoreSignedWithSignedIdentity(NewPRMMatchRepository()), + ), }, }, }, diff --git a/signature/policy_eval_sigstore_test.go b/signature/policy_eval_sigstore_test.go index 6124655fe..86efe3c1c 100644 --- a/signature/policy_eval_sigstore_test.go +++ b/signature/policy_eval_sigstore_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestPRrSigstoreSignedIsSignatureAuthorAccepted(t *testing.T) { +func TestPRSigstoreSignedIsSignatureAuthorAccepted(t *testing.T) { // Currently, this fails even with a correctly signed image. prm := NewPRMMatchRepository() // We prefer to test with a Cosign-created signature for interoperability, and that doesn’t work with matchExact. testImage := dirImageMock(t, "fixtures/dir-img-cosign-valid", "192.168.64.2:5000/cosign-signed-single-sample") @@ -21,7 +21,10 @@ func TestPRrSigstoreSignedIsSignatureAuthorAccepted(t *testing.T) { require.NoError(t, err) // Successful validation, with KeyData and KeyPath - pr, err := newPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err := newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) sar, parsedSig, err := pr.isSignatureAuthorAccepted(context.Background(), testImage, testImageSigBlob) assertSARRejected(t, sar, parsedSig, err) @@ -53,14 +56,20 @@ func TestPRrSigstoreSignedIsSignatureAccepted(t *testing.T) { testImageSig := sigstoreSignatureFromFile(t, "fixtures/dir-img-cosign-valid/signature-1") // Successful validation, with KeyData and KeyPath - pr, err := newPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err := newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) sar, err := pr.isSignatureAccepted(context.Background(), testImage, testImageSig) assertAccepted(sar, err) keyData, err := os.ReadFile("fixtures/cosign.pub") require.NoError(t, err) - pr, err = newPRSigstoreSignedKeyData(keyData, prm) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyData(keyData), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) sar, err = pr.isSignatureAccepted(context.Background(), testImage, testImageSig) assertAccepted(sar, err) @@ -74,10 +83,16 @@ func TestPRrSigstoreSignedIsSignatureAccepted(t *testing.T) { return &prSigstoreSigned{KeyPath: "", KeyData: nil, SignedIdentity: prm}, nil }, func() (*prSigstoreSigned, error) { // Invalid KeyPath - return newPRSigstoreSignedKeyPath("/this/does/not/exist", prm) + return newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("/this/does/not/exist"), + PRSigstoreSignedWithSignedIdentity(prm), + ) }, func() (*prSigstoreSigned, error) { // KeyData doesn’t contain a public key. - return newPRSigstoreSignedKeyData([]byte{}, prm) + return newPRSigstoreSigned( + PRSigstoreSignedWithKeyData([]byte{}), + PRSigstoreSignedWithSignedIdentity(prm), + ) }, } { pr, err := fn() @@ -88,7 +103,10 @@ func TestPRrSigstoreSignedIsSignatureAccepted(t *testing.T) { } // Signature has no cryptographic signature - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) // Pass a nil pointer to, kind of, test that the return value does not depend on the image. sar, err = pr.isSignatureAccepted(context.Background(), nil, @@ -96,7 +114,10 @@ func TestPRrSigstoreSignedIsSignatureAccepted(t *testing.T) { assertRejected(sar, err) // A signature which does not verify - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) // Pass a nil pointer to, kind of, test that the return value does not depend on the image. sar, err = pr.isSignatureAccepted(context.Background(), nil, @@ -106,7 +127,10 @@ func TestPRrSigstoreSignedIsSignatureAccepted(t *testing.T) { assertRejected(sar, err) // A valid signature using an unknown key. - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) // Pass a nil pointer to, kind of, test that the return value does not depend on the image. sar, err = pr.isSignatureAccepted(context.Background(), nil, sigstoreSignatureFromFile(t, "fixtures/unknown-cosign-key.signature")) @@ -115,28 +139,40 @@ func TestPRrSigstoreSignedIsSignatureAccepted(t *testing.T) { // A valid signature with a rejected identity. nonmatchingPRM, err := NewPRMExactReference("this/doesnt:match") require.NoError(t, err) - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", nonmatchingPRM) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(nonmatchingPRM), + ) require.NoError(t, err) sar, err = pr.isSignatureAccepted(context.Background(), testImage, testImageSig) assertRejected(sar, err) // Error reading image manifest image := dirImageMock(t, "fixtures/dir-img-cosign-no-manifest", "192.168.64.2:5000/cosign-signed-single-sample") - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) sar, err = pr.isSignatureAccepted(context.Background(), image, sigstoreSignatureFromFile(t, "fixtures/dir-img-cosign-no-manifest/signature-1")) assertRejected(sar, err) // Error computing manifest digest image = dirImageMock(t, "fixtures/dir-img-cosign-manifest-digest-error", "192.168.64.2:5000/cosign-signed-single-sample") - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) sar, err = pr.isSignatureAccepted(context.Background(), image, sigstoreSignatureFromFile(t, "fixtures/dir-img-cosign-manifest-digest-error/signature-1")) assertRejected(sar, err) // A valid signature with a non-matching manifest image = dirImageMock(t, "fixtures/dir-img-cosign-modified-manifest", "192.168.64.2:5000/cosign-signed-single-sample") - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) sar, err = pr.isSignatureAccepted(context.Background(), image, sigstoreSignatureFromFile(t, "fixtures/dir-img-cosign-modified-manifest/signature-1")) assertRejected(sar, err) @@ -144,18 +180,27 @@ func TestPRrSigstoreSignedIsSignatureAccepted(t *testing.T) { // Minimally check that the prmMatchExact also works as expected: // - Signatures with a matching tag work image = dirImageMock(t, "fixtures/dir-img-cosign-valid-with-tag", "192.168.64.2:5000/skopeo-signed:tag") - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", NewPRMMatchExact()) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(NewPRMMatchExact()), + ) require.NoError(t, err) sar, err = pr.isSignatureAccepted(context.Background(), image, sigstoreSignatureFromFile(t, "fixtures/dir-img-cosign-valid-with-tag/signature-1")) assertAccepted(sar, err) // - Signatures with a non-matching tag are rejected image = dirImageMock(t, "fixtures/dir-img-cosign-valid-with-tag", "192.168.64.2:5000/skopeo-signed:othertag") - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", NewPRMMatchExact()) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(NewPRMMatchExact()), + ) require.NoError(t, err) sar, err = pr.isSignatureAccepted(context.Background(), image, sigstoreSignatureFromFile(t, "fixtures/dir-img-cosign-valid-with-tag/signature-1")) assertRejected(sar, err) // - Cosign-created signatures are rejected - pr, err = newPRSigstoreSignedKeyPath("fixtures/cosign.pub", NewPRMMatchExact()) + pr, err = newPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(NewPRMMatchExact()), + ) require.NoError(t, err) sar, err = pr.isSignatureAccepted(context.Background(), testImage, testImageSig) assertRejected(sar, err) @@ -166,7 +211,10 @@ func TestPRSigstoreSignedIsRunningImageAllowed(t *testing.T) { // A simple success case: single valid signature. image := dirImageMock(t, "fixtures/dir-img-cosign-valid", "192.168.64.2:5000/cosign-signed-single-sample") - pr, err := NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err := NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) allowed, err := pr.isRunningImageAllowed(context.Background(), image) assertRunningAllowed(t, allowed, err) @@ -174,56 +222,80 @@ func TestPRSigstoreSignedIsRunningImageAllowed(t *testing.T) { // Error reading signatures invalidSigDir := createInvalidSigDir(t) image = dirImageMock(t, invalidSigDir, "192.168.64.2:5000/cosign-signed-single-sample") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningRejected(t, allowed, err) // No signatures image = dirImageMock(t, "fixtures/dir-img-unsigned", "testing/manifest:latest") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningRejected(t, allowed, err) // Only non-sigstore signatures image = dirImageMock(t, "fixtures/dir-img-valid", "testing/manifest:latest") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningRejected(t, allowed, err) // Only non-signature sigstore attachments image = dirImageMock(t, "fixtures/dir-img-cosign-other-attachment", "testing/manifest:latest") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningRejected(t, allowed, err) // 1 invalid signature: use dir-img-valid, but a non-matching Docker reference image = dirImageMock(t, "fixtures/dir-img-cosign-valid", "testing/manifest:notlatest") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningRejectedPolicyRequirement(t, allowed, err) // 2 valid signatures image = dirImageMock(t, "fixtures/dir-img-cosign-valid-2", "192.168.64.2:5000/cosign-signed-single-sample") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningAllowed(t, allowed, err) // One invalid, one valid signature (in this order) image = dirImageMock(t, "fixtures/dir-img-cosign-mixed", "192.168.64.2:5000/cosign-signed-single-sample") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningAllowed(t, allowed, err) // 2 invalid signajtures: use dir-img-cosign-valid-2, but a non-matching Docker reference image = dirImageMock(t, "fixtures/dir-img-cosign-valid-2", "this/doesnt:match") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", prm) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(prm), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningRejectedPolicyRequirement(t, allowed, err) @@ -231,19 +303,28 @@ func TestPRSigstoreSignedIsRunningImageAllowed(t *testing.T) { // Minimally check that the prmMatchExact also works as expected: // - Signatures with a matching tag work image = dirImageMock(t, "fixtures/dir-img-cosign-valid-with-tag", "192.168.64.2:5000/skopeo-signed:tag") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", NewPRMMatchExact()) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(NewPRMMatchExact()), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningAllowed(t, allowed, err) // - Signatures with a non-matching tag are rejected image = dirImageMock(t, "fixtures/dir-img-cosign-valid-with-tag", "192.168.64.2:5000/skopeo-signed:othertag") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", NewPRMMatchExact()) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(NewPRMMatchExact()), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningRejectedPolicyRequirement(t, allowed, err) // - Cosign-created signatures are rejected image = dirImageMock(t, "fixtures/dir-img-cosign-valid", "192.168.64.2:5000/cosign-signed-single-sample") - pr, err = NewPRSigstoreSignedKeyPath("fixtures/cosign.pub", NewPRMMatchExact()) + pr, err = NewPRSigstoreSigned( + PRSigstoreSignedWithKeyPath("fixtures/cosign.pub"), + PRSigstoreSignedWithSignedIdentity(NewPRMMatchExact()), + ) require.NoError(t, err) allowed, err = pr.isRunningImageAllowed(context.Background(), image) assertRunningRejectedPolicyRequirement(t, allowed, err)