mirror of https://github.com/containers/image.git
1077 lines
39 KiB
Go
1077 lines
39 KiB
Go
package signature
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// xNewPRSigstoreSigned is like NewPRSigstoreSigned, except it must not fail.
|
|
func xNewPRSigstoreSigned(options ...PRSigstoreSignedOption) PolicyRequirement {
|
|
pr, err := NewPRSigstoreSigned(options...)
|
|
if err != nil {
|
|
panic("xNewPRSigstoreSigned failed")
|
|
}
|
|
return pr
|
|
}
|
|
|
|
func TestNewPRSigstoreSigned(t *testing.T) {
|
|
const testKeyPath = "/foo/bar"
|
|
const testKeyPath2 = "/baz/bar"
|
|
testKeyData := []byte("abc")
|
|
testKeyData2 := []byte("def")
|
|
testFulcio, err := NewPRSigstoreSignedFulcio(
|
|
PRSigstoreSignedFulcioWithCAPath("fixtures/fulcio_v1.crt.pem"),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer("https://github.com/login/oauth"),
|
|
PRSigstoreSignedFulcioWithSubjectEmail("mitr@redhat.com"),
|
|
)
|
|
require.NoError(t, err)
|
|
testPKI, err := NewPRSigstoreSignedPKI(
|
|
PRSigstoreSignedPKIWithCARootsPath("fixtures/pki_root_crts.pem"),
|
|
PRSigstoreSignedPKIWithCAIntermediatesPath("fixtures/pki_intermediate_crts.pem"),
|
|
PRSigstoreSignedPKIWithSubjectHostname("myhost.example.com"),
|
|
)
|
|
require.NoError(t, err)
|
|
const testRekorKeyPath = "/foo/baz"
|
|
testRekorKeyData := []byte("def")
|
|
testIdentity := NewPRMMatchRepoDigestOrExact()
|
|
|
|
type requiresRekor string // A type to indicate whether Rekor is required in the test
|
|
const (
|
|
rekorRequired requiresRekor = "required"
|
|
rekorForbidden requiresRekor = "forbidden"
|
|
rekorOptional requiresRekor = "optional"
|
|
)
|
|
|
|
// Success: combinatoric combinations of key source and Rekor uses
|
|
for _, c := range []struct {
|
|
options []PRSigstoreSignedOption
|
|
requiresRekor requiresRekor
|
|
expected prSigstoreSigned
|
|
}{
|
|
{
|
|
options: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
requiresRekor: rekorOptional,
|
|
expected: prSigstoreSigned{
|
|
prCommon: prCommon{prTypeSigstoreSigned},
|
|
KeyPath: testKeyPath,
|
|
KeyPaths: nil,
|
|
KeyData: nil,
|
|
KeyDatas: nil,
|
|
Fulcio: nil,
|
|
SignedIdentity: testIdentity,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithKeyPaths([]string{testKeyPath, testKeyPath2}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
requiresRekor: rekorOptional,
|
|
expected: prSigstoreSigned{
|
|
prCommon: prCommon{prTypeSigstoreSigned},
|
|
KeyPath: "",
|
|
KeyPaths: []string{testKeyPath, testKeyPath2},
|
|
KeyData: nil,
|
|
KeyDatas: nil,
|
|
Fulcio: nil,
|
|
SignedIdentity: testIdentity,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithKeyData(testKeyData),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
requiresRekor: rekorOptional,
|
|
expected: prSigstoreSigned{
|
|
prCommon: prCommon{prTypeSigstoreSigned},
|
|
KeyPath: "",
|
|
KeyPaths: nil,
|
|
KeyData: testKeyData,
|
|
KeyDatas: nil,
|
|
Fulcio: nil,
|
|
SignedIdentity: testIdentity,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithKeyDatas([][]byte{testKeyData, testKeyData2}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
requiresRekor: rekorOptional,
|
|
expected: prSigstoreSigned{
|
|
prCommon: prCommon{prTypeSigstoreSigned},
|
|
KeyPath: "",
|
|
KeyPaths: nil,
|
|
KeyData: nil,
|
|
KeyDatas: [][]byte{testKeyData, testKeyData2},
|
|
Fulcio: nil,
|
|
SignedIdentity: testIdentity,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithPKI(testPKI),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
requiresRekor: rekorForbidden,
|
|
expected: prSigstoreSigned{
|
|
prCommon: prCommon{prTypeSigstoreSigned},
|
|
KeyPath: "",
|
|
KeyPaths: nil,
|
|
KeyData: nil,
|
|
KeyDatas: nil,
|
|
PKI: testPKI,
|
|
SignedIdentity: testIdentity,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithFulcio(testFulcio),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
requiresRekor: rekorRequired,
|
|
expected: prSigstoreSigned{
|
|
prCommon: prCommon{prTypeSigstoreSigned},
|
|
KeyPath: "",
|
|
KeyPaths: nil,
|
|
KeyData: nil,
|
|
KeyDatas: nil,
|
|
Fulcio: testFulcio,
|
|
SignedIdentity: testIdentity,
|
|
},
|
|
},
|
|
} {
|
|
for _, c2 := range []struct {
|
|
rekorOptions []PRSigstoreSignedOption
|
|
rekorExpected prSigstoreSigned
|
|
}{
|
|
{ // No Rekor
|
|
rekorOptions: []PRSigstoreSignedOption{},
|
|
rekorExpected: prSigstoreSigned{},
|
|
},
|
|
{
|
|
rekorOptions: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath),
|
|
},
|
|
rekorExpected: prSigstoreSigned{
|
|
RekorPublicKeyPath: testRekorKeyPath,
|
|
},
|
|
},
|
|
{
|
|
rekorOptions: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithRekorPublicKeyPaths([]string{testRekorKeyPath, testKeyPath}),
|
|
},
|
|
rekorExpected: prSigstoreSigned{
|
|
RekorPublicKeyPaths: []string{testRekorKeyPath, testKeyPath},
|
|
},
|
|
},
|
|
{
|
|
rekorOptions: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithRekorPublicKeyData(testRekorKeyData),
|
|
},
|
|
rekorExpected: prSigstoreSigned{
|
|
RekorPublicKeyData: testRekorKeyData,
|
|
},
|
|
},
|
|
{
|
|
rekorOptions: []PRSigstoreSignedOption{
|
|
PRSigstoreSignedWithRekorPublicKeyDatas([][]byte{testRekorKeyData, testKeyData}),
|
|
},
|
|
rekorExpected: prSigstoreSigned{
|
|
RekorPublicKeyDatas: [][]byte{testRekorKeyData, testKeyData},
|
|
},
|
|
},
|
|
} {
|
|
if (c.requiresRekor == rekorRequired && len(c2.rekorOptions) == 0) ||
|
|
(c.requiresRekor == rekorForbidden && len(c2.rekorOptions) != 0) {
|
|
continue
|
|
}
|
|
pr, err := newPRSigstoreSigned(append(c.options, c2.rekorOptions...)...)
|
|
require.NoError(t, err)
|
|
expected := c.expected // A shallow copy
|
|
expected.RekorPublicKeyPath = c2.rekorExpected.RekorPublicKeyPath
|
|
expected.RekorPublicKeyPaths = c2.rekorExpected.RekorPublicKeyPaths
|
|
expected.RekorPublicKeyData = c2.rekorExpected.RekorPublicKeyData
|
|
expected.RekorPublicKeyDatas = c2.rekorExpected.RekorPublicKeyDatas
|
|
assert.Equal(t, &expected, pr)
|
|
}
|
|
}
|
|
|
|
testFulcio2, err := NewPRSigstoreSignedFulcio(
|
|
PRSigstoreSignedFulcioWithCAPath("fixtures/fulcio_v1.crt.pem"),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer("https://github.com/login/oauth"),
|
|
PRSigstoreSignedFulcioWithSubjectEmail("test-user@example.com"),
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
testPKI2, err := NewPRSigstoreSignedPKI(
|
|
PRSigstoreSignedPKIWithCARootsPath("fixtures/pki_root_crts.pem"),
|
|
PRSigstoreSignedPKIWithSubjectEmail("test-user@example.com"),
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
for _, c := range [][]PRSigstoreSignedOption{
|
|
{}, // None of keyPath, keyPaths, keyData, keyDatas, fulcio, pki specified
|
|
{ // Both keyPath and keyData specified
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithKeyData(testKeyData),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Both keyPath and fulcio specified
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithFulcio(testFulcio),
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Both keyData and fulcio specified
|
|
PRSigstoreSignedWithKeyData(testKeyData),
|
|
PRSigstoreSignedWithFulcio(testFulcio),
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Both keyPath and pki specified
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithPKI(testPKI),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Both keyData and pki specified
|
|
PRSigstoreSignedWithKeyData(testKeyData),
|
|
PRSigstoreSignedWithPKI(testPKI),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Both fulcio and pki specified
|
|
PRSigstoreSignedWithFulcio(testFulcio),
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath),
|
|
PRSigstoreSignedWithPKI(testPKI),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate keyPath
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithKeyPath(testKeyPath + "1"),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Empty keypaths
|
|
PRSigstoreSignedWithKeyPaths([]string{}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate keyPaths
|
|
PRSigstoreSignedWithKeyPaths([]string{testKeyPath, testKeyPath2}),
|
|
PRSigstoreSignedWithKeyPaths([]string{testKeyPath + "1", testKeyPath2 + "1"}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // keyPath & keyPaths both set
|
|
PRSigstoreSignedWithKeyPath("foobar"),
|
|
PRSigstoreSignedWithKeyPaths([]string{"foobar"}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate keyData
|
|
PRSigstoreSignedWithKeyData(testKeyData),
|
|
PRSigstoreSignedWithKeyData([]byte("def")),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Empty keyDatas
|
|
PRSigstoreSignedWithKeyDatas([][]byte{}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate keyDatas
|
|
PRSigstoreSignedWithKeyDatas([][]byte{testKeyData, testKeyData2}),
|
|
PRSigstoreSignedWithKeyDatas([][]byte{append(testKeyData, 'a'), append(testKeyData2, 'a')}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // keyData & keyDatas both set
|
|
PRSigstoreSignedWithKeyData([]byte("bar")),
|
|
PRSigstoreSignedWithKeyDatas([][]byte{[]byte("foo")}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate fulcio
|
|
PRSigstoreSignedWithFulcio(testFulcio),
|
|
PRSigstoreSignedWithFulcio(testFulcio2),
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // fulcio without Rekor
|
|
PRSigstoreSignedWithFulcio(testFulcio),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Both rekorKeyPath and rekorKeyData specified
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyData(testRekorKeyData),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate rekorKeyPath
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath + "1"),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Both rekorKeyPath and rekorKeyPaths specified
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyPaths([]string{testRekorKeyPath, testKeyPath}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Empty rekorKeyPaths
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyPaths([]string{}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate rekorKeyPaths
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyPaths([]string{testRekorKeyPath, testKeyPath}),
|
|
PRSigstoreSignedWithRekorPublicKeyPaths([]string{testRekorKeyPath + "1", testKeyPath + "1"}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate rekorKeyData
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyData(testRekorKeyData),
|
|
PRSigstoreSignedWithRekorPublicKeyData([]byte("def")),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Both rekorKeyData and rekorKeyDatas specified
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyData(testRekorKeyData),
|
|
PRSigstoreSignedWithRekorPublicKeyDatas([][]byte{testRekorKeyData, []byte("def")}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Empty rekorKeyDatas
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyDatas([][]byte{}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate rekorKeyData
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithRekorPublicKeyDatas([][]byte{testRekorKeyData, testKeyData}),
|
|
PRSigstoreSignedWithRekorPublicKeyDatas([][]byte{[]byte("abc"), []byte("def")}),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Duplicate pki
|
|
PRSigstoreSignedWithPKI(testPKI),
|
|
PRSigstoreSignedWithPKI(testPKI2),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // pki with Rekor
|
|
PRSigstoreSignedWithPKI(testPKI),
|
|
PRSigstoreSignedWithRekorPublicKeyPath(testRekorKeyPath),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
},
|
|
{ // Missing signedIdentity
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
},
|
|
{ // Duplicate signedIdentity
|
|
PRSigstoreSignedWithKeyPath(testKeyPath),
|
|
PRSigstoreSignedWithSignedIdentity(testIdentity),
|
|
PRSigstoreSignedWithSignedIdentity(newPRMMatchRepository()),
|
|
},
|
|
} {
|
|
_, err = newPRSigstoreSigned(c...)
|
|
assert.Error(t, err)
|
|
}
|
|
}
|
|
|
|
func TestNewPRSigstoreSignedKeyPath(t *testing.T) {
|
|
const testPath = "/foo/bar"
|
|
signedIdentity := NewPRMMatchRepoDigestOrExact()
|
|
_pr, err := NewPRSigstoreSignedKeyPath(testPath, signedIdentity)
|
|
require.NoError(t, err)
|
|
pr, ok := _pr.(*prSigstoreSigned)
|
|
require.True(t, ok)
|
|
assert.Equal(t, &prSigstoreSigned{
|
|
prCommon: prCommon{Type: prTypeSigstoreSigned},
|
|
KeyPath: testPath,
|
|
SignedIdentity: NewPRMMatchRepoDigestOrExact(),
|
|
}, pr)
|
|
}
|
|
|
|
func TestNewPRSigstoreSignedKeyData(t *testing.T) {
|
|
testData := []byte("abc")
|
|
signedIdentity := NewPRMMatchRepoDigestOrExact()
|
|
_pr, err := NewPRSigstoreSignedKeyData(testData, signedIdentity)
|
|
require.NoError(t, err)
|
|
pr, ok := _pr.(*prSigstoreSigned)
|
|
require.True(t, ok)
|
|
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
|
|
func tryUnmarshalModifiedSigstoreSigned(t *testing.T, pr *prSigstoreSigned, validJSON []byte, modifyFn func(mSA)) error {
|
|
var tmp mSA
|
|
err := json.Unmarshal(validJSON, &tmp)
|
|
require.NoError(t, err)
|
|
|
|
modifyFn(tmp)
|
|
|
|
*pr = prSigstoreSigned{}
|
|
return jsonUnmarshalFromObject(t, tmp, &pr)
|
|
}
|
|
|
|
func TestPRSigstoreSignedUnmarshalJSON(t *testing.T) {
|
|
keyDataTests := policyJSONUmarshallerTests[PolicyRequirement]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSigned{} },
|
|
newValidObject: func() (PolicyRequirement, error) {
|
|
return NewPRSigstoreSignedKeyData([]byte("abc"), NewPRMMatchRepoDigestOrExact())
|
|
},
|
|
otherJSONParser: newPolicyRequirementFromJSON,
|
|
breakFns: []func(mSA){
|
|
// The "type" field is missing
|
|
func(v mSA) { delete(v, "type") },
|
|
// Wrong "type" field
|
|
func(v mSA) { v["type"] = 1 },
|
|
func(v mSA) { v["type"] = "this is invalid" },
|
|
// Extra top-level sub-object
|
|
func(v mSA) { v["unexpected"] = 1 },
|
|
// All of "keyPath", "keyPaths", "keyData", "keyDatas", "fulcio", and "pki" is missing
|
|
func(v mSA) { delete(v, "keyData") },
|
|
// Both "keyPath" and "keyData" is present
|
|
func(v mSA) { v["keyPath"] = "/foo/bar" },
|
|
// Both "keyPaths" and "keyData" is present
|
|
func(v mSA) { v["keyPaths"] = []string{"/foo/bar", "/foo/baz"} },
|
|
// Both "keyData" and "keyDatas" is present
|
|
func(v mSA) { v["keyDatas"] = [][]byte{[]byte("abc"), []byte("def")} },
|
|
// Both "keyData" and "fulcio" is present
|
|
func(v mSA) {
|
|
v["fulcio"] = mSA{
|
|
"caPath": "/foo/baz",
|
|
"oidcIssuer": "https://example.com",
|
|
"subjectEmail": "test@example.com",
|
|
}
|
|
},
|
|
// Both "keyData" and "pki" is present
|
|
func(v mSA) {
|
|
v["pki"] = mSA{
|
|
"caRootsPath": "/foo/bar",
|
|
"caIntermediatesPath": "/foo/baz",
|
|
"subjectHostname": "example.com",
|
|
}
|
|
},
|
|
// Invalid "keyPath" field
|
|
func(v mSA) { delete(v, "keyData"); v["keyPath"] = 1 },
|
|
// Invalid "keyPaths" field
|
|
func(v mSA) { delete(v, "keyData"); v["keyPaths"] = 1 },
|
|
func(v mSA) { delete(v, "keyData"); v["keyPaths"] = mSA{} },
|
|
func(v mSA) { delete(v, "keyData"); v["keyPaths"] = []string{} },
|
|
// Invalid "keyData" field
|
|
func(v mSA) { v["keyData"] = 1 },
|
|
func(v mSA) { v["keyData"] = "this is invalid base64" },
|
|
// Invalid "keyDatas" field
|
|
func(v mSA) { delete(v, "keyData"); v["keyDatas"] = 1 },
|
|
func(v mSA) { delete(v, "keyData"); v["keyDatas"] = mSA{} },
|
|
func(v mSA) { delete(v, "keyData"); v["keyDatas"] = [][]byte{} },
|
|
// Invalid "fulcio" field
|
|
func(v mSA) { delete(v, "keyData"); v["fulcio"] = 1 },
|
|
func(v mSA) { delete(v, "keyData"); v["fulcio"] = mSA{} },
|
|
// "fulcio" is explicit nil
|
|
func(v mSA) { delete(v, "keyData"); v["fulcio"] = nil },
|
|
// Invalid "pki" field
|
|
func(v mSA) { delete(v, "keyData"); v["pki"] = 1 },
|
|
func(v mSA) { delete(v, "keyData"); v["pki"] = mSA{} },
|
|
// "pki" is explicit nil
|
|
func(v mSA) { delete(v, "keyData"); v["pki"] = nil },
|
|
// Both "rekorKeyPath" and "rekorKeyData" is present
|
|
func(v mSA) {
|
|
v["rekorPublicKeyPath"] = "/foo/baz"
|
|
v["rekorPublicKeyData"] = ""
|
|
},
|
|
// Invalid "rekorPublicKeyPath" field
|
|
func(v mSA) { v["rekorPublicKeyPath"] = 1 },
|
|
// Both "rekorKeyPath" and "rekorKeyPaths" is present
|
|
func(v mSA) {
|
|
v["rekorPublicKeyPath"] = "/foo/baz"
|
|
v["rekorPublicKeyPaths"] = []string{"/baz/a", "/baz/b"}
|
|
},
|
|
// Invalid "rekorPublicKeyPaths" field
|
|
func(v mSA) { v["rekorPublicKeyPaths"] = 1 },
|
|
func(v mSA) { v["rekorPublicKeyPaths"] = mSA{} },
|
|
func(v mSA) { v["rekorPublicKeyPaths"] = []string{} },
|
|
// Invalid "rekorPublicKeyData" field
|
|
func(v mSA) { v["rekorPublicKeyData"] = 1 },
|
|
func(v mSA) { v["rekorPublicKeyData"] = "this is invalid base64" },
|
|
// Both "rekorPublicKeyData" and "rekorPublicKeyDatas" is present
|
|
func(v mSA) {
|
|
v["rekorPublicKeyData"] = []byte("a")
|
|
v["rekorPublicKeyDatas"] = [][]byte{[]byte("a"), []byte("b")}
|
|
},
|
|
// Invalid "rekorPublicKeyDatas" field
|
|
func(v mSA) { v["rekorPublicKeyDatas"] = 1 },
|
|
func(v mSA) { v["rekorPublicKeyDatas"] = mSA{} },
|
|
func(v mSA) { v["rekorPublicKeyDatas"] = [][]byte{} },
|
|
// Invalid "signedIdentity" field
|
|
func(v mSA) { v["signedIdentity"] = "this is invalid" },
|
|
// "signedIdentity" an explicit nil
|
|
func(v mSA) { v["signedIdentity"] = nil },
|
|
},
|
|
duplicateFields: []string{"type", "keyData", "signedIdentity"},
|
|
}
|
|
keyDataTests.run(t)
|
|
// Test keyPath and keyPath-specific duplicate fields
|
|
policyJSONUmarshallerTests[PolicyRequirement]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSigned{} },
|
|
newValidObject: func() (PolicyRequirement, error) {
|
|
return NewPRSigstoreSignedKeyPath("/foo/bar", NewPRMMatchRepoDigestOrExact())
|
|
},
|
|
otherJSONParser: newPolicyRequirementFromJSON,
|
|
duplicateFields: []string{"type", "keyPath", "signedIdentity"},
|
|
}.run(t)
|
|
// Test keyPaths and keyPaths-specific duplicate fields
|
|
policyJSONUmarshallerTests[PolicyRequirement]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSigned{} },
|
|
newValidObject: func() (PolicyRequirement, error) {
|
|
return NewPRSigstoreSigned(
|
|
PRSigstoreSignedWithKeyPaths([]string{"/foo/bar", "/foo/baz"}),
|
|
PRSigstoreSignedWithSignedIdentity(NewPRMMatchRepoDigestOrExact()),
|
|
)
|
|
},
|
|
otherJSONParser: newPolicyRequirementFromJSON,
|
|
duplicateFields: []string{"type", "keyPaths", "signedIdentity"},
|
|
}.run(t)
|
|
// Test keyDatas and keyDatas-specific duplicate fields
|
|
policyJSONUmarshallerTests[PolicyRequirement]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSigned{} },
|
|
newValidObject: func() (PolicyRequirement, error) {
|
|
return NewPRSigstoreSigned(
|
|
PRSigstoreSignedWithKeyDatas([][]byte{[]byte("abc"), []byte("def")}),
|
|
PRSigstoreSignedWithSignedIdentity(NewPRMMatchRepoDigestOrExact()),
|
|
)
|
|
},
|
|
otherJSONParser: newPolicyRequirementFromJSON,
|
|
duplicateFields: []string{"type", "keyDatas", "signedIdentity"},
|
|
}.run(t)
|
|
// Test Fulcio and rekorPublicKeyPath duplicate fields
|
|
testFulcio, err := NewPRSigstoreSignedFulcio(
|
|
PRSigstoreSignedFulcioWithCAPath("fixtures/fulcio_v1.crt.pem"),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer("https://github.com/login/oauth"),
|
|
PRSigstoreSignedFulcioWithSubjectEmail("mitr@redhat.com"),
|
|
)
|
|
require.NoError(t, err)
|
|
policyJSONUmarshallerTests[PolicyRequirement]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSigned{} },
|
|
newValidObject: func() (PolicyRequirement, error) {
|
|
return NewPRSigstoreSigned(
|
|
PRSigstoreSignedWithFulcio(testFulcio),
|
|
PRSigstoreSignedWithRekorPublicKeyPath("/foo/rekor"),
|
|
PRSigstoreSignedWithSignedIdentity(NewPRMMatchRepoDigestOrExact()),
|
|
)
|
|
},
|
|
otherJSONParser: newPolicyRequirementFromJSON,
|
|
duplicateFields: []string{"type", "fulcio", "rekorPublicKeyPath", "signedIdentity"},
|
|
}.run(t)
|
|
// Test rekorPublicKeyPaths duplicate fields
|
|
policyJSONUmarshallerTests[PolicyRequirement]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSigned{} },
|
|
newValidObject: func() (PolicyRequirement, error) {
|
|
return NewPRSigstoreSigned(
|
|
PRSigstoreSignedWithKeyPath("/foo/bar"),
|
|
PRSigstoreSignedWithRekorPublicKeyPaths([]string{"/baz/a", "/baz/b"}),
|
|
PRSigstoreSignedWithSignedIdentity(NewPRMMatchRepoDigestOrExact()),
|
|
)
|
|
},
|
|
otherJSONParser: newPolicyRequirementFromJSON,
|
|
duplicateFields: []string{"type", "keyPath", "rekorPublicKeyPaths", "signedIdentity"},
|
|
}.run(t)
|
|
// Test rekorPublicKeyData duplicate fields
|
|
policyJSONUmarshallerTests[PolicyRequirement]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSigned{} },
|
|
newValidObject: func() (PolicyRequirement, error) {
|
|
return NewPRSigstoreSigned(
|
|
PRSigstoreSignedWithKeyPath("/foo/bar"),
|
|
PRSigstoreSignedWithRekorPublicKeyData([]byte("foo")),
|
|
PRSigstoreSignedWithSignedIdentity(NewPRMMatchRepoDigestOrExact()),
|
|
)
|
|
},
|
|
otherJSONParser: newPolicyRequirementFromJSON,
|
|
duplicateFields: []string{"type", "keyPath", "rekorPublicKeyData", "signedIdentity"},
|
|
}.run(t)
|
|
// Test rekorPublicKeyDatas duplicate fields
|
|
policyJSONUmarshallerTests[PolicyRequirement]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSigned{} },
|
|
newValidObject: func() (PolicyRequirement, error) {
|
|
return NewPRSigstoreSigned(
|
|
PRSigstoreSignedWithKeyPath("/foo/bar"),
|
|
PRSigstoreSignedWithRekorPublicKeyDatas([][]byte{[]byte("foo"), []byte("bar")}),
|
|
PRSigstoreSignedWithSignedIdentity(NewPRMMatchRepoDigestOrExact()),
|
|
)
|
|
},
|
|
otherJSONParser: newPolicyRequirementFromJSON,
|
|
duplicateFields: []string{"type", "keyPath", "rekorPublicKeyDatas", "signedIdentity"},
|
|
}.run(t)
|
|
// Test pki and pki-specific duplicate fields
|
|
testPKI, err := NewPRSigstoreSignedPKI(
|
|
PRSigstoreSignedPKIWithCARootsPath("fixtures/pki_root_crts.pem"),
|
|
PRSigstoreSignedPKIWithSubjectEmail("test-user@example.com"),
|
|
)
|
|
require.NoError(t, err)
|
|
policyJSONUmarshallerTests[PolicyRequirement]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSigned{} },
|
|
newValidObject: func() (PolicyRequirement, error) {
|
|
return NewPRSigstoreSigned(
|
|
PRSigstoreSignedWithPKI(testPKI),
|
|
PRSigstoreSignedWithSignedIdentity(NewPRMMatchRepoDigestOrExact()),
|
|
)
|
|
},
|
|
otherJSONParser: newPolicyRequirementFromJSON,
|
|
duplicateFields: []string{"type", "pki", "signedIdentity"},
|
|
}.run(t)
|
|
|
|
var pr prSigstoreSigned
|
|
|
|
// Start with a valid JSON.
|
|
_, validJSON := keyDataTests.validObjectAndJSON(t)
|
|
|
|
// Various allowed modifications to the requirement
|
|
allowedModificationFns := []func(mSA){
|
|
// Delete the signedIdentity field
|
|
func(v mSA) { delete(v, "signedIdentity") },
|
|
}
|
|
for _, fn := range allowedModificationFns {
|
|
err := tryUnmarshalModifiedSigstoreSigned(t, &pr, validJSON, fn)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Various ways to set signedIdentity to the default value
|
|
signedIdentityDefaultFns := []func(mSA){
|
|
// Set signedIdentity to the default explicitly
|
|
func(v mSA) { v["signedIdentity"] = NewPRMMatchRepoDigestOrExact() },
|
|
// Delete the signedIdentity field
|
|
func(v mSA) { delete(v, "signedIdentity") },
|
|
}
|
|
for _, fn := range signedIdentityDefaultFns {
|
|
err := tryUnmarshalModifiedSigstoreSigned(t, &pr, validJSON, fn)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, NewPRMMatchRepoDigestOrExact(), pr.SignedIdentity)
|
|
}
|
|
}
|
|
|
|
func TestNewPRSigstoreSignedFulcio(t *testing.T) {
|
|
const testCAPath = "/foo/bar"
|
|
testCAData := []byte("abc")
|
|
const testOIDCIssuer = "https://example.com"
|
|
const testSubjectEmail = "test@example.com"
|
|
|
|
// Success:
|
|
for _, c := range []struct {
|
|
options []PRSigstoreSignedFulcioOption
|
|
expected prSigstoreSignedFulcio
|
|
}{
|
|
{
|
|
options: []PRSigstoreSignedFulcioOption{
|
|
PRSigstoreSignedFulcioWithCAPath(testCAPath),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer),
|
|
PRSigstoreSignedFulcioWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedFulcio{
|
|
CAPath: testCAPath,
|
|
OIDCIssuer: testOIDCIssuer,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedFulcioOption{
|
|
PRSigstoreSignedFulcioWithCAData(testCAData),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer),
|
|
PRSigstoreSignedFulcioWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedFulcio{
|
|
CAData: testCAData,
|
|
OIDCIssuer: testOIDCIssuer,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
} {
|
|
pr, err := newPRSigstoreSignedFulcio(c.options...)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, &c.expected, pr)
|
|
}
|
|
|
|
for _, c := range [][]PRSigstoreSignedFulcioOption{
|
|
{ // Neither caPath nor caData specified
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer),
|
|
PRSigstoreSignedFulcioWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{ // Both caPath and caData specified
|
|
PRSigstoreSignedFulcioWithCAPath(testCAPath),
|
|
PRSigstoreSignedFulcioWithCAData(testCAData),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer),
|
|
PRSigstoreSignedFulcioWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{ // Duplicate caPath
|
|
PRSigstoreSignedFulcioWithCAPath(testCAPath),
|
|
PRSigstoreSignedFulcioWithCAPath(testCAPath + "1"),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer),
|
|
PRSigstoreSignedFulcioWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{ // Duplicate caData
|
|
PRSigstoreSignedFulcioWithCAData(testCAData),
|
|
PRSigstoreSignedFulcioWithCAData([]byte("def")),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer),
|
|
PRSigstoreSignedFulcioWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{ // Missing oidcIssuer
|
|
PRSigstoreSignedFulcioWithCAPath(testCAPath),
|
|
PRSigstoreSignedFulcioWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{ // Duplicate oidcIssuer
|
|
PRSigstoreSignedFulcioWithCAPath(testCAPath),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer + "1"),
|
|
PRSigstoreSignedFulcioWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{ // Missing subjectEmail
|
|
PRSigstoreSignedFulcioWithCAPath(testCAPath),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer),
|
|
},
|
|
{ // Duplicate subjectEmail
|
|
PRSigstoreSignedFulcioWithCAPath(testCAPath),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer(testOIDCIssuer),
|
|
PRSigstoreSignedFulcioWithSubjectEmail(testSubjectEmail),
|
|
PRSigstoreSignedFulcioWithSubjectEmail("1" + testSubjectEmail),
|
|
},
|
|
} {
|
|
_, err := newPRSigstoreSignedFulcio(c...)
|
|
logrus.Errorf("%#v", err)
|
|
assert.Error(t, err)
|
|
}
|
|
}
|
|
|
|
func TestPRSigstoreSignedFulcioUnmarshalJSON(t *testing.T) {
|
|
policyJSONUmarshallerTests[PRSigstoreSignedFulcio]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSignedFulcio{} },
|
|
newValidObject: func() (PRSigstoreSignedFulcio, error) {
|
|
return NewPRSigstoreSignedFulcio(
|
|
PRSigstoreSignedFulcioWithCAPath("fixtures/fulcio_v1.crt.pem"),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer("https://github.com/login/oauth"),
|
|
PRSigstoreSignedFulcioWithSubjectEmail("mitr@redhat.com"),
|
|
)
|
|
},
|
|
otherJSONParser: nil,
|
|
breakFns: []func(mSA){
|
|
// Extra top-level sub-object
|
|
func(v mSA) { v["unexpected"] = 1 },
|
|
// Both of "caPath" and "caData" are missing
|
|
func(v mSA) { delete(v, "caPath") },
|
|
// Both "caPath" and "caData" is present
|
|
func(v mSA) { v["caData"] = "" },
|
|
// Invalid "caPath" field
|
|
func(v mSA) { v["caPath"] = 1 },
|
|
// Invalid "oidcIssuer" field
|
|
func(v mSA) { v["oidcIssuer"] = 1 },
|
|
// "oidcIssuer" is missing
|
|
func(v mSA) { delete(v, "oidcIssuer") },
|
|
// Invalid "subjectEmail" field
|
|
func(v mSA) { v["subjectEmail"] = 1 },
|
|
// "subjectEmail" is missing
|
|
func(v mSA) { delete(v, "subjectEmail") },
|
|
},
|
|
duplicateFields: []string{"caPath", "oidcIssuer", "subjectEmail"},
|
|
}.run(t)
|
|
// Test caData specifics
|
|
policyJSONUmarshallerTests[PRSigstoreSignedFulcio]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSignedFulcio{} },
|
|
newValidObject: func() (PRSigstoreSignedFulcio, error) {
|
|
return NewPRSigstoreSignedFulcio(
|
|
PRSigstoreSignedFulcioWithCAData([]byte("abc")),
|
|
PRSigstoreSignedFulcioWithOIDCIssuer("https://github.com/login/oauth"),
|
|
PRSigstoreSignedFulcioWithSubjectEmail("mitr@redhat.com"),
|
|
)
|
|
},
|
|
otherJSONParser: nil,
|
|
breakFns: []func(mSA){
|
|
// Invalid "caData" field
|
|
func(v mSA) { v["caData"] = 1 },
|
|
func(v mSA) { v["caData"] = "this is invalid base64" },
|
|
},
|
|
duplicateFields: []string{"caData", "oidcIssuer", "subjectEmail"},
|
|
}.run(t)
|
|
}
|
|
|
|
func TestNewPRSigstoreSignedPKI(t *testing.T) {
|
|
const testCARootsPath = "/foo/bar"
|
|
testCARootsData := []byte("abc")
|
|
const testCAIntermediatesPath = "/foo/baz"
|
|
testCAIntermediatesData := []byte("def")
|
|
const testSubjectHostname = "https://example.com"
|
|
const testSubjectEmail = "test@example.com"
|
|
|
|
// Success:
|
|
for _, c := range []struct {
|
|
options []PRSigstoreSignedPKIOption
|
|
expected prSigstoreSignedPKI
|
|
}{
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsPath: testCARootsPath,
|
|
SubjectHostname: testSubjectHostname,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsPath: testCARootsPath,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsPath: testCARootsPath,
|
|
SubjectHostname: testSubjectHostname,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsData: testCARootsData,
|
|
SubjectHostname: testSubjectHostname,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsData: testCARootsData,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsData: testCARootsData,
|
|
SubjectHostname: testSubjectHostname,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithCAIntermediatesData(testCAIntermediatesData),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsData: testCARootsData,
|
|
CAIntermediatesData: testCAIntermediatesData,
|
|
SubjectHostname: testSubjectHostname,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithCAIntermediatesData(testCAIntermediatesData),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsData: testCARootsData,
|
|
CAIntermediatesData: testCAIntermediatesData,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithCAIntermediatesData(testCAIntermediatesData),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsData: testCARootsData,
|
|
CAIntermediatesData: testCAIntermediatesData,
|
|
SubjectHostname: testSubjectHostname,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithCAIntermediatesPath(testCAIntermediatesPath),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsData: testCARootsData,
|
|
CAIntermediatesPath: testCAIntermediatesPath,
|
|
SubjectHostname: testSubjectHostname,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithCAIntermediatesPath(testCAIntermediatesPath),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsData: testCARootsData,
|
|
CAIntermediatesPath: testCAIntermediatesPath,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
{
|
|
options: []PRSigstoreSignedPKIOption{
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithCAIntermediatesPath(testCAIntermediatesPath),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
expected: prSigstoreSignedPKI{
|
|
CARootsData: testCARootsData,
|
|
CAIntermediatesPath: testCAIntermediatesPath,
|
|
SubjectHostname: testSubjectHostname,
|
|
SubjectEmail: testSubjectEmail,
|
|
},
|
|
},
|
|
} {
|
|
pr, err := newPRSigstoreSignedPKI(c.options...)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, &c.expected, pr)
|
|
}
|
|
|
|
for _, c := range [][]PRSigstoreSignedPKIOption{
|
|
{ // Neither caRootsPath nor caRootsData specified
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
},
|
|
{ // Both caRootsPath and caRootsData specified
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
},
|
|
{ // Duplicate caRootsPath
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath + "1"),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{ // Duplicate caRootsData
|
|
PRSigstoreSignedPKIWithCARootsData(testCARootsData),
|
|
PRSigstoreSignedPKIWithCARootsData([]byte("def")),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{ // Both caIntermediatesPath and caIntermediatesData specified
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithCAIntermediatesPath(testCAIntermediatesPath),
|
|
PRSigstoreSignedPKIWithCAIntermediatesData(testCAIntermediatesData),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
},
|
|
{
|
|
// Duplicate caIntermediatesPath
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithCAIntermediatesPath(testCAIntermediatesPath),
|
|
PRSigstoreSignedPKIWithCAIntermediatesPath(testCAIntermediatesPath + "1"),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{
|
|
// Duplicate caIntermediatesData
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithCAIntermediatesData(testCAIntermediatesData),
|
|
PRSigstoreSignedPKIWithCAIntermediatesData([]byte("def")),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
},
|
|
{ // Missing subjectEmail and subjectHostname
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
},
|
|
{ // Duplicate subjectHostname
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname),
|
|
PRSigstoreSignedPKIWithSubjectHostname(testSubjectHostname + "1"),
|
|
},
|
|
{ // Duplicate subjectEmail
|
|
PRSigstoreSignedPKIWithCARootsPath(testCARootsPath),
|
|
PRSigstoreSignedPKIWithSubjectEmail(testSubjectEmail),
|
|
PRSigstoreSignedPKIWithSubjectEmail("1" + testSubjectEmail),
|
|
},
|
|
} {
|
|
_, err := newPRSigstoreSignedPKI(c...)
|
|
logrus.Errorf("%#v", err)
|
|
assert.Error(t, err)
|
|
}
|
|
}
|
|
|
|
func TestPRSigstoreSignedPKIUnmarshalJSON(t *testing.T) {
|
|
policyJSONUmarshallerTests[PRSigstoreSignedPKI]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSignedPKI{} },
|
|
newValidObject: func() (PRSigstoreSignedPKI, error) {
|
|
return NewPRSigstoreSignedPKI(
|
|
PRSigstoreSignedPKIWithCARootsPath("fixtures/pki_root_crts.pem"),
|
|
PRSigstoreSignedPKIWithCAIntermediatesPath("fixtures/pki_intermediate_crts.pem"),
|
|
PRSigstoreSignedPKIWithSubjectHostname("myhost.example.com"),
|
|
PRSigstoreSignedPKIWithSubjectEmail("qiwan@redhat.com"),
|
|
)
|
|
},
|
|
otherJSONParser: nil,
|
|
breakFns: []func(mSA){
|
|
// Extra top-level sub-object
|
|
func(v mSA) { v["unexpected"] = 1 },
|
|
// Both of "caRootsPath" and "caRootsData" are missing
|
|
func(v mSA) { delete(v, "caRootsPath") },
|
|
// Both "caRootsPath" and "caRootsData" are present
|
|
func(v mSA) { v["caRootsData"] = "" },
|
|
// Invalid "caRootsPath" field
|
|
func(v mSA) { v["caRootsPath"] = 1 },
|
|
// Both "caIntermediatesPath" and "caIntermediatesData" are present
|
|
func(v mSA) { v["caIntermediatesData"] = "" },
|
|
// Invalid "caIntermediatesPath" field
|
|
func(v mSA) { v["caIntermediatesPath"] = 1 },
|
|
// Invalid "subjectHostname" field
|
|
func(v mSA) { v["subjectHostname"] = 1 },
|
|
// Invalid "subjectEmail" field
|
|
func(v mSA) { v["subjectEmail"] = 1 },
|
|
// Both "subjectHostname" and "subjectEmail" are missing
|
|
func(v mSA) {
|
|
delete(v, "subjectHostname")
|
|
delete(v, "subjectEmail")
|
|
},
|
|
},
|
|
duplicateFields: []string{"caRootsPath", "caIntermediatesPath", "subjectHostname", "subjectEmail"},
|
|
}.run(t)
|
|
|
|
// Test caRootsData specifics
|
|
policyJSONUmarshallerTests[PRSigstoreSignedPKI]{
|
|
newDest: func() json.Unmarshaler { return &prSigstoreSignedPKI{} },
|
|
newValidObject: func() (PRSigstoreSignedPKI, error) {
|
|
return NewPRSigstoreSignedPKI(
|
|
PRSigstoreSignedPKIWithCARootsData([]byte("abc")),
|
|
PRSigstoreSignedPKIWithCAIntermediatesData([]byte("def")),
|
|
PRSigstoreSignedPKIWithSubjectHostname("myhost.example.com"),
|
|
PRSigstoreSignedPKIWithSubjectEmail("qiwan@redhat.com"),
|
|
)
|
|
},
|
|
otherJSONParser: nil,
|
|
breakFns: []func(mSA){
|
|
// Invalid "caRootsData" field
|
|
func(v mSA) { v["caRootsData"] = 1 },
|
|
func(v mSA) { v["caRootsData"] = "this is invalid base64" },
|
|
// Invalid "caIntermediatesData" field
|
|
func(v mSA) { v["caIntermediatesData"] = 1 },
|
|
func(v mSA) { v["caIntermediatesData"] = "this is invalid base64" },
|
|
},
|
|
duplicateFields: []string{"caRootsData", "caIntermediatesData", "subjectHostname", "subjectEmail"},
|
|
}.run(t)
|
|
}
|