diff --git a/internal/test/test.go b/internal/test/test.go index 4f63668..f769476 100644 --- a/internal/test/test.go +++ b/internal/test/test.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "os" + "path/filepath" "strings" "testing" @@ -45,6 +46,14 @@ func CreateTempDir(t *testing.T, dir, pattern string) string { return tempDir } +func GetMockSigner(_ context.Context) (dsse.SignerVerifier, error) { + priv, err := os.ReadFile(filepath.Join("..", "..", "test", "testdata", "test-signing-key.pem")) + if err != nil { + return nil, err + } + return signerverifier.LoadKeyPair(priv) +} + func Setup(t *testing.T) (context.Context, dsse.SignerVerifier) { var tl tlog.TL if UseMockTL { diff --git a/pkg/attest/sign_test.go b/pkg/attest/sign_test.go index 06c4b49..de577fe 100644 --- a/pkg/attest/sign_test.go +++ b/pkg/attest/sign_test.go @@ -15,9 +15,6 @@ import ( "github.com/docker/attest/pkg/policy" "github.com/google/go-containerregistry/pkg/registry" v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/empty" - "github.com/google/go-containerregistry/pkg/v1/layout" - "github.com/google/go-containerregistry/pkg/v1/mutate" "github.com/google/go-containerregistry/pkg/v1/static" "github.com/google/go-containerregistry/pkg/v1/types" intoto "github.com/in-toto/in-toto-golang/in_toto" @@ -66,21 +63,11 @@ func TestSignVerifyOCILayout(t *testing.T) { signedIndex := attIdx.Index signedIndex, err = attestation.UpdateIndexImages(signedIndex, signedManifests, attestation.WithReplacedLayers(tc.replace)) require.NoError(t, err) - // output signed attestations - idx := v1.ImageIndex(empty.Index) - idx = mutate.AppendManifests(idx, mutate.IndexAddendum{ - Add: signedIndex, - Descriptor: v1.Descriptor{ - Annotations: map[string]string{ - oci.OCIReferenceTarget: attIdx.Name, - }, - }, - }) - _, err = layout.Write(outputLayout, idx) + spec, err := oci.ParseImageSpec(oci.LocalPrefix + outputLayout) require.NoError(t, err) - src, err := oci.ParseImageSpec("oci://" + outputLayout) + err = mirror.SaveIndex([]*oci.ImageSpec{spec}, signedIndex, attIdx.Name) require.NoError(t, err) - policy, err := Verify(ctx, src, policyOpts) + policy, err := Verify(ctx, spec, policyOpts) require.NoError(t, err) assert.Equalf(t, OutcomeSuccess, policy.Outcome, "Policy should have been found") diff --git a/pkg/attest/verify_test.go b/pkg/attest/verify_test.go index 04c4805..34c4ecc 100644 --- a/pkg/attest/verify_test.go +++ b/pkg/attest/verify_test.go @@ -10,12 +10,10 @@ import ( "github.com/docker/attest/internal/test" "github.com/docker/attest/pkg/attestation" + "github.com/docker/attest/pkg/config" + "github.com/docker/attest/pkg/mirror" "github.com/docker/attest/pkg/oci" "github.com/docker/attest/pkg/policy" - v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/google/go-containerregistry/pkg/v1/empty" - "github.com/google/go-containerregistry/pkg/v1/layout" - "github.com/google/go-containerregistry/pkg/v1/mutate" intoto "github.com/in-toto/in-toto-golang/in_toto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -34,7 +32,7 @@ func TestVerifyAttestations(t *testing.T) { env := new(attestation.Envelope) err = json.Unmarshal(ex, env) assert.NoError(t, err) - resolver := &test.MockResolver{ + resolver := &oci.MockResolver{ Envs: []*attestation.Envelope{env}, } @@ -84,25 +82,17 @@ func TestVSA(t *testing.T) { require.NoError(t, err) // output signed attestations - idx := v1.ImageIndex(empty.Index) - idx = mutate.AppendManifests(idx, mutate.IndexAddendum{ - Add: signedIndex, - Descriptor: v1.Descriptor{ - Annotations: map[string]string{ - oci.OCIReferenceTarget: attIdx.Name, - }, - }, - }) - _, err = layout.Write(outputLayout, idx) + spec, err := oci.ParseImageSpec(oci.LocalPrefix+outputLayout, oci.WithPlatform(LinuxAMD64)) + require.NoError(t, err) + err = mirror.SaveIndex([]*oci.ImageSpec{spec}, signedIndex, attIdx.Name) assert.NoError(t, err) // mocked vsa query should pass policyOpts := &policy.Options{ - LocalPolicyDir: PassPolicyDir, + LocalPolicyDir: PassPolicyDir, + AttestationStyle: config.AttestationStyleAttached, } - src, err := oci.ParseImageSpec("oci://"+outputLayout, oci.WithPlatform(LinuxAMD64)) - require.NoError(t, err) - results, err := Verify(ctx, src, policyOpts) + results, err := Verify(ctx, spec, policyOpts) require.NoError(t, err) assert.Equal(t, OutcomeSuccess, results.Outcome) assert.Empty(t, results.Violations) @@ -142,25 +132,17 @@ func TestVerificationFailure(t *testing.T) { require.NoError(t, err) // output signed attestations - idx := v1.ImageIndex(empty.Index) - idx = mutate.AppendManifests(idx, mutate.IndexAddendum{ - Add: signedIndex, - Descriptor: v1.Descriptor{ - Annotations: map[string]string{ - oci.OCIReferenceTarget: attIdx.Name, - }, - }, - }) - _, err = layout.Write(outputLayout, idx) + spec, err := oci.ParseImageSpec(oci.LocalPrefix+outputLayout, oci.WithPlatform(LinuxAMD64)) + require.NoError(t, err) + err = mirror.SaveIndex([]*oci.ImageSpec{spec}, signedIndex, attIdx.Name) assert.NoError(t, err) // mocked vsa query should fail policyOpts := &policy.Options{ - LocalPolicyDir: FailPolicyDir, + LocalPolicyDir: FailPolicyDir, + AttestationStyle: config.AttestationStyleAttached, } - src, err := oci.ParseImageSpec("oci://"+outputLayout, oci.WithPlatform(LinuxAMD64)) - require.NoError(t, err) - results, err := Verify(ctx, src, policyOpts) + results, err := Verify(ctx, spec, policyOpts) require.NoError(t, err) assert.Equal(t, OutcomeFailure, results.Outcome) assert.Len(t, results.Violations, 1) @@ -224,24 +206,15 @@ func TestSignVerify(t *testing.T) { imageName = attIdx.Name } // output signed attestations - idx := v1.ImageIndex(empty.Index) - idx = mutate.AppendManifests(idx, mutate.IndexAddendum{ - Add: signedIndex, - Descriptor: v1.Descriptor{ - Annotations: map[string]string{ - oci.OCIReferenceTarget: imageName, - }, - }, - }) - _, err = layout.Write(outputLayout, idx) - assert.NoError(t, err) + spec, err := oci.ParseImageSpec(oci.LocalPrefix+outputLayout, oci.WithPlatform(LinuxAMD64)) + require.NoError(t, err) + err = mirror.SaveIndex([]*oci.ImageSpec{spec}, signedIndex, imageName) + require.NoError(t, err) policyOpts := &policy.Options{ LocalPolicyDir: tc.policyDir, } - src, err := oci.ParseImageSpec("oci://"+outputLayout, oci.WithPlatform(LinuxAMD64)) - require.NoError(t, err) - results, err := Verify(ctx, src, policyOpts) + results, err := Verify(ctx, spec, policyOpts) if tc.expectError { require.Error(t, err) return diff --git a/pkg/attestation/types.go b/pkg/attestation/types.go index fd28c83..3305b24 100644 --- a/pkg/attestation/types.go +++ b/pkg/attestation/types.go @@ -36,7 +36,7 @@ type Manifest struct { // accumulated during signing SignedLayers []*Layer - // details of subect image + // details of subject image SubjectName string SubjectDescriptor *v1.Descriptor } diff --git a/pkg/mirror/mirror.go b/pkg/mirror/mirror.go index eb927ac..e9e35de 100644 --- a/pkg/mirror/mirror.go +++ b/pkg/mirror/mirror.go @@ -129,6 +129,7 @@ func SaveImage(output *oci.ImageSpec, image v1.Image, imageName string) error { func SaveReferrers(manifest *attestation.Manifest, outputs []*oci.ImageSpec) error { for _, output := range outputs { + // OCI layout output for referrers not supported if output.Type == oci.OCI { continue } @@ -147,10 +148,10 @@ func SaveReferrers(manifest *attestation.Manifest, outputs []*oci.ImageSpec) err return fmt.Errorf("failed to build image: %w", err) } for _, image := range images { - err = SaveImage(attOut, image, "") - } - if err != nil { - return fmt.Errorf("failed to push image: %w", err) + err := PushImageToRegistry(image, attOut.Identifier) + if err != nil { + return fmt.Errorf("failed to push image: %w", err) + } } } return nil diff --git a/pkg/mirror/mirror_test.go b/pkg/mirror/mirror_test.go index 75ca87d..7a42d80 100644 --- a/pkg/mirror/mirror_test.go +++ b/pkg/mirror/mirror_test.go @@ -36,7 +36,7 @@ func TestSavingIndex(t *testing.T) { err = SaveIndex(output, attIdx.Index, indexName) require.NoError(t, err) - ociOutput, err := oci.ParseImageSpecs("oci://" + outputLayout) + ociOutput, err := oci.ParseImageSpecs(oci.LocalPrefix + outputLayout) require.NoError(t, err) err = SaveIndex(ociOutput, attIdx.Index, indexName) require.NoError(t, err) @@ -59,7 +59,7 @@ func TestSavingImage(t *testing.T) { err = SaveImage(output, img, indexName) require.NoError(t, err) - ociOutput, err := oci.ParseImageSpec("oci://" + outputLayout) + ociOutput, err := oci.ParseImageSpec(oci.LocalPrefix + outputLayout) require.NoError(t, err) err = SaveImage(ociOutput, img, indexName) require.NoError(t, err) @@ -96,9 +96,9 @@ func TestSavingReferrers(t *testing.T) { err = SaveReferrers(manifest, output) require.NoError(t, err) - reg := &test.MockRegistryResolver{ + reg := &oci.MockRegistryResolver{ Subject: subject, - MockResolver: &test.MockResolver{}, + MockResolver: &oci.MockResolver{}, ImageNameStr: indexName, } require.NoError(t, err) diff --git a/pkg/oci/layout.go b/pkg/oci/layout.go index 5c54ebd..634be9e 100644 --- a/pkg/oci/layout.go +++ b/pkg/oci/layout.go @@ -95,7 +95,6 @@ func attestationManifestFromOCILayout(path string, platform *v1.Platform) (*atte } idxDescriptor := idxm.Manifests[0] - name := idxDescriptor.Annotations["org.opencontainers.image.ref.name"] idxDigest := idxDescriptor.Digest mfs, err := idx.ImageIndex(idxDigest) @@ -109,11 +108,16 @@ func attestationManifestFromOCILayout(path string, platform *v1.Platform) (*atte var subjectDescriptor *v1.Descriptor for i := range mfs2.Manifests { manifest := &mfs2.Manifests[i] - if manifest.Platform.Equals(*platform) { - subjectDescriptor = manifest - break + if manifest.Platform != nil { + if manifest.Platform.Equals(*platform) { + subjectDescriptor = manifest + break + } } } + if subjectDescriptor == nil { + return nil, fmt.Errorf("platform not found in index") + } for i := range mfs2.Manifests { mf := &mfs2.Manifests[i] if mf.Annotations[att.DockerReferenceType] != attestation.AttestationManifestType { @@ -135,7 +139,7 @@ func attestationManifestFromOCILayout(path string, platform *v1.Platform) (*atte attest := &attestation.Manifest{ OriginalLayers: layers, OriginalDescriptor: mf, - SubjectName: name, + SubjectName: idxDescriptor.Annotations["org.opencontainers.image.ref.name"], SubjectDescriptor: subjectDescriptor, } return attest, nil diff --git a/pkg/oci/layout_test.go b/pkg/oci/layout_test.go new file mode 100644 index 0000000..12feb93 --- /dev/null +++ b/pkg/oci/layout_test.go @@ -0,0 +1,69 @@ +package oci_test + +import ( + "strings" + "testing" + + "github.com/docker/attest/internal/test" + "github.com/docker/attest/pkg/attest" + "github.com/docker/attest/pkg/attestation" + "github.com/docker/attest/pkg/mirror" + "github.com/docker/attest/pkg/oci" + "github.com/docker/attest/pkg/policy" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestAttestationFromOCILayout(t *testing.T) { + ctx, signer := test.Setup(t) + outputLayout := test.CreateTempDir(t, "", "attest-oci-layout") + + invalidPlatform := &v1.Platform{ + Architecture: "invalid", + OS: "invalid", + } + + opts := &attestation.SigningOptions{} + attIdx, err := oci.IndexFromPath(oci.UnsignedTestImage) + require.NoError(t, err) + signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts) + require.NoError(t, err) + signedIndex := attIdx.Index + signedIndex, err = attestation.UpdateIndexImages(signedIndex, signedManifests) + require.NoError(t, err) + spec, err := oci.ParseImageSpec(oci.LocalPrefix + outputLayout) + require.NoError(t, err) + err = mirror.SaveIndex([]*oci.ImageSpec{spec}, signedIndex, outputLayout) + require.NoError(t, err) + + testCases := []struct { + name string + platform *v1.Platform + errorStr string + }{ + {name: "nominal", platform: spec.Platform}, + {name: "invalid platform", platform: invalidPlatform, errorStr: "platform not found in index"}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + spec := &oci.ImageSpec{ + Type: oci.OCI, + Identifier: outputLayout, + Platform: tc.platform, + } + resolver, err := policy.CreateImageDetailsResolver(spec) + if tc.errorStr != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tc.errorStr) + return + } + require.NoError(t, err) + desc, err := resolver.ImageDescriptor(ctx) + require.NoError(t, err) + digest := desc.Digest.String() + assert.True(t, strings.Contains(digest, "sha256:")) + }) + } +} diff --git a/internal/test/mocks.go b/pkg/oci/mock.go similarity index 71% rename from internal/test/mocks.go rename to pkg/oci/mock.go index 096ddf2..537d9ae 100644 --- a/internal/test/mocks.go +++ b/pkg/oci/mock.go @@ -1,15 +1,10 @@ -package test +package oci import ( "context" - "os" - "path/filepath" "github.com/docker/attest/pkg/attestation" - "github.com/docker/attest/pkg/oci" - "github.com/docker/attest/pkg/signerverifier" v1 "github.com/google/go-containerregistry/pkg/v1" - "github.com/secure-systems-lab/go-securesystemslib/dsse" ) type MockResolver struct { @@ -37,7 +32,7 @@ func (r MockResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error) } func (r MockResolver) ImagePlatform(_ context.Context) (*v1.Platform, error) { - return oci.ParsePlatform("linux/amd64") + return ParsePlatform("linux/amd64") } type MockRegistryResolver struct { @@ -53,11 +48,3 @@ func (r *MockRegistryResolver) ImageDescriptor(_ context.Context) (*v1.Descripto func (r *MockRegistryResolver) ImageName(_ context.Context) (string, error) { return r.ImageNameStr, nil } - -func GetMockSigner(_ context.Context) (dsse.SignerVerifier, error) { - priv, err := os.ReadFile(filepath.Join("..", "..", "test", "testdata", "test-signing-key.pem")) - if err != nil { - return nil, err - } - return signerverifier.LoadKeyPair(priv) -} diff --git a/pkg/oci/oci_test.go b/pkg/oci/oci_test.go index 545ad36..3039aac 100644 --- a/pkg/oci/oci_test.go +++ b/pkg/oci/oci_test.go @@ -95,10 +95,10 @@ func TestWithoutTag(t *testing.T) { {name: "image:tag", expected: "index.docker.io/library/image"}, {name: "image", expected: "index.docker.io/library/image"}, {name: "image:sha256-digest.att", expected: "index.docker.io/library/image"}, - {name: "docker://image:tag", expected: "docker://index.docker.io/library/image"}, + {name: RegistryPrefix + "image:tag", expected: RegistryPrefix + "index.docker.io/library/image"}, {name: "image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: "index.docker.io/library/image"}, - {name: "docker://image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: "docker://index.docker.io/library/image"}, - {name: "docker://127.0.0.1:36555/repo:latest", expected: "docker://127.0.0.1:36555/repo"}, + {name: RegistryPrefix + "image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: RegistryPrefix + "index.docker.io/library/image"}, + {name: RegistryPrefix + "127.0.0.1:36555/repo:latest", expected: RegistryPrefix + "127.0.0.1:36555/repo"}, } for _, c := range tc { t.Run(c.name, func(t *testing.T) { @@ -116,11 +116,11 @@ func TestReplaceTag(t *testing.T) { {name: "image:tag", expected: "index.docker.io/library/image:sha256-digest.att"}, {name: "image", expected: "index.docker.io/library/image:sha256-digest.att"}, {name: "image:sha256-digest.att", expected: "index.docker.io/library/image:sha256-digest.att"}, - {name: "docker://image:tag", expected: "docker://index.docker.io/library/image:sha256-digest.att"}, + {name: RegistryPrefix + "image:tag", expected: RegistryPrefix + "index.docker.io/library/image:sha256-digest.att"}, {name: "image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: "index.docker.io/library/image:sha256-digest.att"}, - {name: "oci://foobar", expected: "oci://foobar"}, - {name: "docker://image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: "docker://index.docker.io/library/image:sha256-digest.att"}, - {name: "docker://127.0.0.1:36555/repo:latest", expected: "docker://127.0.0.1:36555/repo:sha256-digest.att"}, + {name: LocalPrefix + "foobar", expected: LocalPrefix + "foobar"}, + {name: RegistryPrefix + "image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: RegistryPrefix + "index.docker.io/library/image:sha256-digest.att"}, + {name: RegistryPrefix + "127.0.0.1:36555/repo:latest", expected: RegistryPrefix + "127.0.0.1:36555/repo:sha256-digest.att"}, } digest := v1.Hash{ diff --git a/pkg/oci/referrers.go b/pkg/oci/referrers.go index f5401c3..b74b4a8 100644 --- a/pkg/oci/referrers.go +++ b/pkg/oci/referrers.go @@ -3,6 +3,7 @@ package oci import ( "context" "fmt" + "strings" "github.com/docker/attest/pkg/attestation" att "github.com/docker/attest/pkg/attestation" @@ -58,7 +59,7 @@ func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateTy } var referrersSubjectRef name.Digest if r.referrersRepo != "" { - referrersSubjectRef, err = name.NewDigest(fmt.Sprintf("%s@%s", r.referrersRepo, subjectDigest)) + referrersSubjectRef, err = name.NewDigest(fmt.Sprintf("%s@%s", strings.TrimPrefix(r.referrersRepo, RegistryPrefix), subjectDigest)) if err != nil { return nil, fmt.Errorf("failed to create referrers reference: %w", err) } diff --git a/pkg/policy/policy.go b/pkg/policy/policy.go index 4320d1f..0582192 100644 --- a/pkg/policy/policy.go +++ b/pkg/policy/policy.go @@ -219,19 +219,20 @@ func CreateImageDetailsResolver(imageSource *oci.ImageSpec) (oci.ImageDetailsRes } func CreateAttestationResolver(resolver oci.ImageDetailsResolver, mapping *config.PolicyMapping) (oci.AttestationResolver, error) { - switch resolver := resolver.(type) { - case *oci.RegistryImageDetailsResolver: - if mapping.Attestations != nil && mapping.Attestations.Style == config.AttestationStyleAttached { - return oci.NewRegistryAttestationResolver(resolver) - } else { - if mapping.Attestations != nil && mapping.Attestations.Repo != "" { - return oci.NewReferrersAttestationResolver(resolver, oci.WithReferrersRepo(mapping.Attestations.Repo)) + if mapping.Attestations != nil { + if mapping.Attestations.Style == config.AttestationStyleAttached { + switch resolver := resolver.(type) { + case *oci.RegistryImageDetailsResolver: + return oci.NewRegistryAttestationResolver(resolver) + case *oci.LayoutResolver: + return resolver, nil + default: + return nil, fmt.Errorf("unsupported image details resolver type: %T", resolver) } - return oci.NewReferrersAttestationResolver(resolver) } - case *oci.LayoutResolver: - return resolver, nil - default: - return nil, fmt.Errorf("unsupported image details resolver type: %T", resolver) + if mapping.Attestations.Repo != "" { + return oci.NewReferrersAttestationResolver(resolver, oci.WithReferrersRepo(mapping.Attestations.Repo)) + } } + return oci.NewReferrersAttestationResolver(resolver) } diff --git a/pkg/policy/policy_test.go b/pkg/policy/policy_test.go index c9917c1..65f8a60 100644 --- a/pkg/policy/policy_test.go +++ b/pkg/policy/policy_test.go @@ -38,7 +38,7 @@ func TestRegoEvaluator_Evaluate(t *testing.T) { re := policy.NewRegoEvaluator(true) - defaultResolver := test.MockResolver{ + defaultResolver := oci.MockResolver{ Envs: []*attestation.Envelope{loadAttestation(t, ExampleAttestation)}, } @@ -115,3 +115,64 @@ func TestLoadingMappings(t *testing.T) { } } } + +func TestCreateAttestationResolver(t *testing.T) { + mockResolver := oci.MockResolver{ + Envs: []*attestation.Envelope{}, + } + layoutResolver := &oci.LayoutResolver{} + registryResolver := &oci.RegistryImageDetailsResolver{} + + nilRepoReferrers := &config.PolicyMapping{ + Attestations: &config.AttestationConfig{ + Style: config.AttestationStyleReferrers, + }, + } + referrers := &config.PolicyMapping{ + Attestations: &config.AttestationConfig{ + Repo: "localhost:5000/repo", + Style: config.AttestationStyleReferrers, + }, + } + attached := &config.PolicyMapping{ + Attestations: &config.AttestationConfig{ + Style: config.AttestationStyleAttached, + }, + } + + testCases := []struct { + name string + resolver oci.ImageDetailsResolver + mapping *config.PolicyMapping + errorStr string + }{ + {name: "referrers", resolver: layoutResolver, mapping: referrers}, + {name: "referrers (no mapped repo)", resolver: layoutResolver, mapping: nilRepoReferrers}, + {name: "referrers (no mapping)", resolver: layoutResolver, mapping: &config.PolicyMapping{Attestations: nil}}, + {name: "attached (registry)", resolver: registryResolver, mapping: attached}, + {name: "attached (layout)", resolver: layoutResolver, mapping: attached}, + {name: "attached (unsupported)", resolver: mockResolver, mapping: attached, errorStr: "unsupported image details resolver type"}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + resolver, err := policy.CreateAttestationResolver(tc.resolver, tc.mapping) + if tc.errorStr == "" { + require.NoError(t, err) + } else { + assert.Contains(t, err.Error(), tc.errorStr) + } + if tc.mapping.Attestations == nil { + return + } + switch resolver.(type) { + case *oci.ReferrersResolver: + assert.Equal(t, tc.mapping.Attestations.Style, config.AttestationStyleReferrers) + case *oci.RegistryResolver: + assert.Equal(t, tc.mapping.Attestations.Style, config.AttestationStyleAttached) + case *oci.LayoutResolver: + assert.Equal(t, tc.mapping.Attestations.Style, config.AttestationStyleAttached) + } + }) + } +}