aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg/trust/policy.go8
-rw-r--r--pkg/trust/testdata/default.yaml25
-rw-r--r--pkg/trust/testdata/redhat.yaml3
-rw-r--r--pkg/trust/trust.go13
-rw-r--r--pkg/trust/trust_test.go92
5 files changed, 135 insertions, 6 deletions
diff --git a/pkg/trust/policy.go b/pkg/trust/policy.go
index d2b904b07..7f32e2afc 100644
--- a/pkg/trust/policy.go
+++ b/pkg/trust/policy.go
@@ -53,6 +53,10 @@ func DefaultPolicyPath(sys *types.SystemContext) string {
return systemDefaultPolicyPath
}
+// gpgIDReader returns GPG key IDs of keys stored at the provided path.
+// It exists only for tests, production code should always use getGPGIdFromKeyPath.
+type gpgIDReader func(string) []string
+
// createTmpFile creates a temp file under dir and writes the content into it
func createTmpFile(dir, pattern string, content []byte) (string, error) {
tmpfile, err := ioutil.TempFile(dir, pattern)
@@ -79,7 +83,7 @@ func getGPGIdFromKeyPath(path string) []string {
}
// getGPGIdFromKeyData returns GPG key IDs of keys in the provided keyring.
-func getGPGIdFromKeyData(key string) []string {
+func getGPGIdFromKeyData(idReader gpgIDReader, key string) []string {
decodeKey, err := base64.StdEncoding.DecodeString(key)
if err != nil {
logrus.Errorf("%s, error decoding key data", err)
@@ -90,7 +94,7 @@ func getGPGIdFromKeyData(key string) []string {
logrus.Errorf("Creating key date temp file %s", err)
}
defer os.Remove(tmpfileName)
- return getGPGIdFromKeyPath(tmpfileName)
+ return idReader(tmpfileName)
}
func parseUids(colonDelimitKeys []byte) []string {
diff --git a/pkg/trust/testdata/default.yaml b/pkg/trust/testdata/default.yaml
new file mode 100644
index 000000000..31bcd35ef
--- /dev/null
+++ b/pkg/trust/testdata/default.yaml
@@ -0,0 +1,25 @@
+# This is a default registries.d configuration file. You may
+# add to this file or create additional files in registries.d/.
+#
+# lookaside: indicates a location that is read and write
+# lookaside-staging: indicates a location that is only for write
+#
+# lookaside and lookaside-staging take a value of the following:
+# lookaside: {schema}://location
+#
+# For reading signatures, schema may be http, https, or file.
+# For writing signatures, schema may only be file.
+
+# This is the default signature write location for docker registries.
+default-docker:
+# lookaside: file:///var/lib/containers/sigstore
+ lookaside-staging: file:///var/lib/containers/sigstore
+
+# The 'docker' indicator here is the start of the configuration
+# for docker registries.
+#
+# docker:
+#
+# privateregistry.com:
+# lookaside: http://privateregistry.com/sigstore/
+# lookaside-staging: /mnt/nfs/privateregistry/sigstore
diff --git a/pkg/trust/testdata/redhat.yaml b/pkg/trust/testdata/redhat.yaml
new file mode 100644
index 000000000..35f2c611c
--- /dev/null
+++ b/pkg/trust/testdata/redhat.yaml
@@ -0,0 +1,3 @@
+docker:
+ registry.redhat.io:
+ sigstore: https://registry.redhat.io/containers/sigstore
diff --git a/pkg/trust/trust.go b/pkg/trust/trust.go
index e93b4cd9d..9dd6878f9 100644
--- a/pkg/trust/trust.go
+++ b/pkg/trust/trust.go
@@ -19,18 +19,23 @@ type Policy struct {
// PolicyDescription returns an user-focused description of the policy in policyPath and registries.d data from registriesDirPath.
func PolicyDescription(policyPath, registriesDirPath string) ([]*Policy, error) {
+ return policyDescriptionWithGPGIDReader(policyPath, registriesDirPath, getGPGIdFromKeyPath)
+}
+
+// policyDescriptionWithGPGIDReader is PolicyDescription with a gpgIDReader parameter. It exists only to make testing easier.
+func policyDescriptionWithGPGIDReader(policyPath, registriesDirPath string, idReader gpgIDReader) ([]*Policy, error) {
policyContentStruct, err := getPolicy(policyPath)
if err != nil {
return nil, fmt.Errorf("could not read trust policies: %w", err)
}
- res, err := getPolicyShowOutput(policyContentStruct, registriesDirPath)
+ res, err := getPolicyShowOutput(policyContentStruct, registriesDirPath, idReader)
if err != nil {
return nil, fmt.Errorf("could not show trust policies: %w", err)
}
return res, nil
}
-func getPolicyShowOutput(policyContentStruct policyContent, systemRegistriesDirPath string) ([]*Policy, error) {
+func getPolicyShowOutput(policyContentStruct policyContent, systemRegistriesDirPath string, idReader gpgIDReader) ([]*Policy, error) {
var output []*Policy
registryConfigs, err := loadAndMergeConfig(systemRegistriesDirPath)
@@ -76,10 +81,10 @@ func getPolicyShowOutput(policyContentStruct policyContent, systemRegistriesDirP
uids := []string{}
for _, repoele := range repoval {
if len(repoele.KeyPath) > 0 {
- uids = append(uids, getGPGIdFromKeyPath(repoele.KeyPath)...)
+ uids = append(uids, idReader(repoele.KeyPath)...)
}
if len(repoele.KeyData) > 0 {
- uids = append(uids, getGPGIdFromKeyData(repoele.KeyData)...)
+ uids = append(uids, getGPGIdFromKeyData(idReader, repoele.KeyData)...)
}
}
tempTrustShowOutput.GPGId = strings.Join(uids, ", ")
diff --git a/pkg/trust/trust_test.go b/pkg/trust/trust_test.go
new file mode 100644
index 000000000..fc906572d
--- /dev/null
+++ b/pkg/trust/trust_test.go
@@ -0,0 +1,92 @@
+package trust
+
+import (
+ "encoding/json"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/containers/image/v5/signature"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestPolicyDescription(t *testing.T) {
+ tempDir := t.TempDir()
+ policyPath := filepath.Join(tempDir, "policy.json")
+
+ // Override getGPGIdFromKeyPath because we don't want to bother with (and spend the unit-test time on) generating valid GPG keys, and running the real GPG binary.
+ // Instead of reading the files at all, just expect file names like /id1,id2,...,idN.pub
+ idReader := func(keyPath string) []string {
+ require.True(t, strings.HasPrefix(keyPath, "/"))
+ require.True(t, strings.HasSuffix(keyPath, ".pub"))
+ return strings.Split(keyPath[1:len(keyPath)-4], ",")
+ }
+
+ for _, c := range []struct {
+ policy *signature.Policy
+ expected []*Policy
+ }{
+ {
+ &signature.Policy{
+ Default: signature.PolicyRequirements{
+ signature.NewPRReject(),
+ },
+ Transports: map[string]signature.PolicyTransportScopes{
+ "docker": {
+ "quay.io/accepted": {
+ signature.NewPRInsecureAcceptAnything(),
+ },
+ "registry.redhat.io": {
+ xNewPRSignedByKeyPath(t, "/redhat.pub", signature.NewPRMMatchRepoDigestOrExact()),
+ },
+ "quay.io/multi-signed": {
+ xNewPRSignedByKeyPath(t, "/1.pub", signature.NewPRMMatchRepoDigestOrExact()),
+ xNewPRSignedByKeyPath(t, "/2,3.pub", signature.NewPRMMatchRepoDigestOrExact()),
+ },
+ },
+ },
+ },
+ []*Policy{
+ {
+ Transport: "all",
+ Name: "* (default)",
+ RepoName: "default",
+ Type: "reject",
+ },
+ {
+ Transport: "repository",
+ Name: "quay.io/accepted",
+ RepoName: "quay.io/accepted",
+ Type: "accept",
+ },
+ {
+ Transport: "repository",
+ Name: "quay.io/multi-signed",
+ RepoName: "quay.io/multi-signed",
+ Type: "signed",
+ SignatureStore: "",
+ GPGId: "1, 2, 3",
+ },
+ {
+ Transport: "repository",
+ Name: "registry.redhat.io",
+ RepoName: "registry.redhat.io",
+ Type: "signed",
+ SignatureStore: "https://registry.redhat.io/containers/sigstore",
+ GPGId: "redhat",
+ },
+ },
+ },
+ } {
+ policyJSON, err := json.Marshal(c.policy)
+ require.NoError(t, err)
+ err = os.WriteFile(policyPath, policyJSON, 0600)
+ require.NoError(t, err)
+
+ res, err := policyDescriptionWithGPGIDReader(policyPath, "./testdata", idReader)
+ require.NoError(t, err)
+ assert.Equal(t, c.expected, res)
+ }
+}