Add support for selecting a policy by ID (#41)
This commit is contained in:
@@ -56,6 +56,7 @@ func ExampleVerify_remote() {
|
|||||||
TufClient: tufClient,
|
TufClient: tufClient,
|
||||||
LocalTargetsDir: filepath.Join(home, ".docker", "policy"), // location to store policy files downloaded from TUF
|
LocalTargetsDir: filepath.Join(home, ".docker", "policy"), // location to store policy files downloaded from TUF
|
||||||
LocalPolicyDir: "", // overrides TUF policy for local policy files if set
|
LocalPolicyDir: "", // overrides TUF policy for local policy files if set
|
||||||
|
PolicyId: "", // set to ignore policy mapping and select a policy by id
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify attestations
|
// verify attestations
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ type PolicyOptions struct {
|
|||||||
TufClient tuf.TUFClient
|
TufClient tuf.TUFClient
|
||||||
LocalTargetsDir string
|
LocalTargetsDir string
|
||||||
LocalPolicyDir string
|
LocalPolicyDir string
|
||||||
|
PolicyId string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Policy struct {
|
type Policy struct {
|
||||||
@@ -195,7 +196,44 @@ func findPolicyMatch(named reference.Named, mappings *PolicyMappings) (*PolicyMa
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolvePolicyById(opts *PolicyOptions) (*Policy, error) {
|
||||||
|
if opts.PolicyId != "" {
|
||||||
|
localMappings, err := LoadLocalMappings(opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to load local policy mappings: %w", err)
|
||||||
|
}
|
||||||
|
if localMappings != nil {
|
||||||
|
for _, mapping := range localMappings.Policies {
|
||||||
|
if mapping.Id == opts.PolicyId {
|
||||||
|
return resolveLocalPolicy(opts, &mapping)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// must check tuf
|
||||||
|
tufMappings, err := loadTufMappings(opts.TufClient, opts.LocalTargetsDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to load tuf policy mappings: %w", err)
|
||||||
|
}
|
||||||
|
for _, mapping := range tufMappings.Policies {
|
||||||
|
if mapping.Id == opts.PolicyId {
|
||||||
|
return resolveTufPolicy(opts, &mapping)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("policy with id %s not found", opts.PolicyId)
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ResolvePolicy(ctx context.Context, resolver oci.AttestationResolver, opts *PolicyOptions) (*Policy, error) {
|
func ResolvePolicy(ctx context.Context, resolver oci.AttestationResolver, opts *PolicyOptions) (*Policy, error) {
|
||||||
|
p, err := resolvePolicyById(opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to resolve policy by id: %w", err)
|
||||||
|
}
|
||||||
|
if p != nil {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
imageName, err := resolver.ImageName(ctx)
|
imageName, err := resolver.ImageName(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get image name: %w", err)
|
return nil, fmt.Errorf("failed to get image name: %w", err)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func loadAttestation(t *testing.T, path string) *attestation.Envelope {
|
|||||||
|
|
||||||
func TestRegoEvaluator_Evaluate(t *testing.T) {
|
func TestRegoEvaluator_Evaluate(t *testing.T) {
|
||||||
ctx, _ := test.Setup(t)
|
ctx, _ := test.Setup(t)
|
||||||
|
errorStr := "failed to resolve policy by id: policy with id non-existent-policy-id not found"
|
||||||
TestDataPath := filepath.Join("..", "..", "test", "testdata")
|
TestDataPath := filepath.Join("..", "..", "test", "testdata")
|
||||||
ExampleAttestation := filepath.Join(TestDataPath, "example_attestation.json")
|
ExampleAttestation := filepath.Join(TestDataPath, "example_attestation.json")
|
||||||
|
|
||||||
@@ -47,8 +47,12 @@ func TestRegoEvaluator_Evaluate(t *testing.T) {
|
|||||||
isCanonical bool
|
isCanonical bool
|
||||||
resolver oci.AttestationResolver
|
resolver oci.AttestationResolver
|
||||||
policy *policy.PolicyOptions
|
policy *policy.PolicyOptions
|
||||||
|
policyId string
|
||||||
|
errorStr string
|
||||||
}{
|
}{
|
||||||
{repo: "testdata/mock-tuf-allow", expectSuccess: true, isCanonical: false, resolver: defaultResolver},
|
{repo: "testdata/mock-tuf-allow", expectSuccess: true, isCanonical: false, resolver: defaultResolver},
|
||||||
|
{repo: "testdata/mock-tuf-allow", expectSuccess: true, isCanonical: false, resolver: defaultResolver, policyId: "docker-official-images"},
|
||||||
|
{repo: "testdata/mock-tuf-allow", expectSuccess: false, isCanonical: false, resolver: defaultResolver, policyId: "non-existent-policy-id", errorStr: errorStr},
|
||||||
{repo: "testdata/mock-tuf-deny", expectSuccess: false, isCanonical: false, resolver: defaultResolver},
|
{repo: "testdata/mock-tuf-deny", expectSuccess: false, isCanonical: false, resolver: defaultResolver},
|
||||||
{repo: "testdata/mock-tuf-verify-sig", expectSuccess: true, isCanonical: false, resolver: defaultResolver},
|
{repo: "testdata/mock-tuf-verify-sig", expectSuccess: true, isCanonical: false, resolver: defaultResolver},
|
||||||
{repo: "testdata/mock-tuf-wrong-key", expectSuccess: false, isCanonical: false, resolver: defaultResolver},
|
{repo: "testdata/mock-tuf-wrong-key", expectSuccess: false, isCanonical: false, resolver: defaultResolver},
|
||||||
@@ -69,11 +73,17 @@ func TestRegoEvaluator_Evaluate(t *testing.T) {
|
|||||||
tc.policy = &policy.PolicyOptions{
|
tc.policy = &policy.PolicyOptions{
|
||||||
TufClient: tufClient,
|
TufClient: tufClient,
|
||||||
LocalTargetsDir: test.CreateTempDir(t, "", "tuf-targets"),
|
LocalTargetsDir: test.CreateTempDir(t, "", "tuf-targets"),
|
||||||
|
PolicyId: tc.policyId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
policy, err := policy.ResolvePolicy(ctx, tc.resolver, tc.policy)
|
policy, err := policy.ResolvePolicy(ctx, tc.resolver, tc.policy)
|
||||||
assert.NoErrorf(t, err, "failed to resolve policy")
|
if tc.errorStr != "" {
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), tc.errorStr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.NoErrorf(t, err, "failed to resolve policy")
|
||||||
result, err := re.Evaluate(ctx, tc.resolver, policy, input)
|
result, err := re.Evaluate(ctx, tc.resolver, policy, input)
|
||||||
require.NoErrorf(t, err, "Evaluate failed")
|
require.NoErrorf(t, err, "Evaluate failed")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user