Merge pull request #138 from docker/feat-add-tuf-resolver-tests

feat: add policy resolver tests
This commit is contained in:
Joel Kamp
2024-08-29 10:28:34 -05:00
committed by GitHub
4 changed files with 124 additions and 12 deletions

View File

@@ -42,7 +42,7 @@ func TestRegoEvaluator_Evaluate(t *testing.T) {
}
testCases := []struct {
repo string
policyPath string
expectSuccess bool
isCanonical bool
resolver attestation.Resolver
@@ -50,19 +50,19 @@ func TestRegoEvaluator_Evaluate(t *testing.T) {
policyID string
resolveErrorStr string
}{
{repo: "testdata/policies/allow", expectSuccess: true, resolver: defaultResolver},
{repo: "testdata/policies/allow", expectSuccess: true, resolver: defaultResolver, policyID: "docker-official-images"},
{repo: "testdata/policies/allow", resolver: defaultResolver, policyID: "non-existent-policy-id", resolveErrorStr: resolveErrorStr},
{repo: "testdata/policies/deny", resolver: defaultResolver},
{repo: "testdata/policies/verify-sig", expectSuccess: true, resolver: defaultResolver},
{repo: "testdata/policies/wrong-key", resolver: defaultResolver},
{repo: "testdata/policies/allow-canonical", expectSuccess: true, isCanonical: true, resolver: defaultResolver},
{repo: "testdata/policies/allow-canonical", resolver: defaultResolver},
{repo: "testdata/policies/no-rego", resolver: defaultResolver, resolveErrorStr: "no policy file found in policy mapping"},
{policyPath: "testdata/policies/allow", expectSuccess: true, resolver: defaultResolver},
{policyPath: "testdata/policies/allow", expectSuccess: true, resolver: defaultResolver, policyID: "docker-official-images"},
{policyPath: "testdata/policies/allow", resolver: defaultResolver, policyID: "non-existent-policy-id", resolveErrorStr: resolveErrorStr},
{policyPath: "testdata/policies/deny", resolver: defaultResolver},
{policyPath: "testdata/policies/verify-sig", expectSuccess: true, resolver: defaultResolver},
{policyPath: "testdata/policies/wrong-key", resolver: defaultResolver},
{policyPath: "testdata/policies/allow-canonical", expectSuccess: true, isCanonical: true, resolver: defaultResolver},
{policyPath: "testdata/policies/allow-canonical", resolver: defaultResolver},
{policyPath: "testdata/policies/no-rego", resolver: defaultResolver, resolveErrorStr: "no policy file found in policy mapping"},
}
for _, tc := range testCases {
t.Run(tc.repo, func(t *testing.T) {
t.Run(tc.policyPath, func(t *testing.T) {
input := &policy.Input{
Digest: "sha256:test-digest",
PURL: "test-purl",
@@ -75,7 +75,7 @@ func TestRegoEvaluator_Evaluate(t *testing.T) {
tc.opts = &policy.Options{
LocalTargetsDir: test.CreateTempDir(t, "", "tuf-targets"),
PolicyID: tc.policyID,
LocalPolicyDir: tc.repo,
LocalPolicyDir: tc.policyPath,
DisableTUF: true,
}
}

View File

@@ -0,0 +1,65 @@
package policy_test
import (
"context"
"testing"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/pkg/policy"
"github.com/docker/attest/pkg/tuf"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestResolvePolicy(t *testing.T) {
localPolicyPath := "testdata/policies/allow"
tufPolicyPath := "testdata/policies/allow-canonical"
noLocalPolicyPath := "testdata/policies/no-policy"
testPolicyID := "docker-official-images"
testImageName := "localhost:5001/test/repo:tag"
testCases := []struct {
name string
policyPath string
policyID string
localOverridesTUF bool // if a policy is provided locally, it should override TUF
DisableTUF bool
}{
{name: "resolve by id (TUF only)", policyID: testPolicyID, DisableTUF: false},
{name: "resolve by id (local mapping, TUF policy)", policyPath: noLocalPolicyPath, policyID: testPolicyID, DisableTUF: false},
{name: "resolve by id (local mapping, local policy, no TUF)", policyPath: localPolicyPath, policyID: testPolicyID, DisableTUF: true},
{name: "resolve by id (local mapping, local policy)", policyPath: localPolicyPath, policyID: testPolicyID, DisableTUF: false, localOverridesTUF: true},
{name: "resolve by match (TUF only)", DisableTUF: false},
{name: "resolve by match (local mapping, TUF policy)", policyPath: noLocalPolicyPath, DisableTUF: false},
{name: "resolve by match (local mapping, local policy, no TUF)", policyPath: localPolicyPath, DisableTUF: true},
{name: "resolve by match (local mapping, local policy)", policyPath: localPolicyPath, DisableTUF: false, localOverridesTUF: true},
}
var tufClient tuf.Downloader
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
opts := &policy.Options{}
tempDir := test.CreateTempDir(t, "", "tuf-dest")
if !tc.DisableTUF {
tufClient = tuf.NewMockTufClient(tufPolicyPath)
}
if tc.policyID != "" {
opts.PolicyID = tc.policyID
}
if tc.policyPath != "" {
opts.LocalPolicyDir = tc.policyPath
}
opts.DisableTUF = tc.DisableTUF
opts.LocalTargetsDir = tempDir
resolver := policy.NewResolver(tufClient, opts)
policy, err := resolver.ResolvePolicy(context.Background(), testImageName)
require.NoError(t, err)
assert.NotNil(t, policy)
if tc.DisableTUF || tc.localOverridesTUF {
assert.Contains(t, policy.URI, localPolicyPath)
} else {
assert.Contains(t, policy.URI, tufPolicyPath)
}
})
}
}

View File

@@ -0,0 +1,10 @@
# map repos to policies
version: v1
kind: policy-mapping
rules:
- pattern: "^docker[.]io/library/(.*)$"
policy-id: docker-official-images
- pattern: ^localhost:5001/(.*)$
rewrite: docker.io/library/$1
- pattern: ^registry[.]local:5000/(.*)$
rewrite: docker.io/library/$1

View File

@@ -1,5 +1,42 @@
package tuf
import (
"io"
"os"
"path/filepath"
"github.com/docker/attest/internal/util"
)
type MockTufClient struct {
srcPath string
}
func NewMockTufClient(srcPath string) *MockTufClient {
if srcPath == "" {
panic("srcPath must be set")
}
return &MockTufClient{
srcPath: srcPath,
}
}
func (dc *MockTufClient) DownloadTarget(target string, _ string) (file *TargetFile, err error) {
targetPath := filepath.Join(dc.srcPath, target)
src, err := os.Open(targetPath)
if err != nil {
return nil, err
}
defer src.Close()
b, err := io.ReadAll(src)
if err != nil {
return nil, err
}
return &TargetFile{TargetURI: targetPath, Data: b, Digest: util.SHA256Hex(b)}, nil
}
type MockVersionChecker struct {
err error
}