Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0510fb76c |
@@ -12,7 +12,7 @@ import (
|
|||||||
const ExpectedStatements = 4
|
const ExpectedStatements = 4
|
||||||
|
|
||||||
func TestExtractAnnotatedStatements(t *testing.T) {
|
func TestExtractAnnotatedStatements(t *testing.T) {
|
||||||
statements, err := attestation.ExtractAnnotatedStatements(test.UnsignedTestImage(".."), intoto.PayloadType)
|
statements, err := attestation.ExtractAnnotatedStatements(test.UnsignedTestIndex(".."), intoto.PayloadType)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equalf(t, len(statements), ExpectedStatements, "expected %d statement, got %d", ExpectedStatements, len(statements))
|
assert.Equalf(t, len(statements), ExpectedStatements, "expected %d statement, got %d", ExpectedStatements, len(statements))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func ExampleManifest() {
|
|||||||
|
|
||||||
ref := "docker/image-signer-verifier:latest"
|
ref := "docker/image-signer-verifier:latest"
|
||||||
|
|
||||||
digest, err := v1.NewHash("sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620")
|
digest, err := v1.NewHash("sha256:7ae6b41655929ad8e1848064874a98ac3f68884996c79907f6525e3045f75390")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// implementation of Resolver that closes over attestations from an oci layout.
|
// implementation of Resolver that closes over attestations from an oci layout.
|
||||||
|
|
||||||
|
var _ Resolver = (*LayoutResolver)(nil)
|
||||||
|
|
||||||
type LayoutResolver struct {
|
type LayoutResolver struct {
|
||||||
*Manifest
|
*Manifest
|
||||||
*oci.ImageSpec
|
*oci.ImageSpec
|
||||||
@@ -86,38 +89,49 @@ func (r *LayoutResolver) ImagePlatform(_ context.Context) (*v1.Platform, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func manifestFromOCILayout(path string, platform *v1.Platform) (*Manifest, error) {
|
func manifestFromOCILayout(path string, platform *v1.Platform) (*Manifest, error) {
|
||||||
idx, err := layout.ImageIndexFromPath(path)
|
layoutIndex, err := layout.ImageIndexFromPath(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
idxm, err := idx.IndexManifest()
|
layoutIndexManifest, err := layoutIndex.IndexManifest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get digest: %w", err)
|
return nil, fmt.Errorf("failed to get digest: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
idxDescriptor := idxm.Manifests[0]
|
layoutDescriptor := layoutIndexManifest.Manifests[0]
|
||||||
idxDigest := idxDescriptor.Digest
|
layoutDescriptorDigest := layoutDescriptor.Digest
|
||||||
subjectName := idxDescriptor.Annotations[ocispec.AnnotationRefName]
|
subjectName := layoutDescriptor.Annotations[ocispec.AnnotationRefName]
|
||||||
if _, err := reference.ParseNamed(subjectName); err != nil {
|
if _, err := reference.ParseNamed(subjectName); err != nil {
|
||||||
// try the containerd annotation if the org.opencontainers.image.ref.name is not a full name
|
// try the containerd annotation if the org.opencontainers.image.ref.name is not a full name
|
||||||
subjectName = idxDescriptor.Annotations[containerd.AnnotationImageName]
|
subjectName = layoutDescriptor.Annotations[containerd.AnnotationImageName]
|
||||||
if _, err := reference.ParseNamed(subjectName); err != nil {
|
if _, err := reference.ParseNamed(subjectName); err != nil {
|
||||||
return nil, fmt.Errorf("failed to find subject name in annotations")
|
return nil, fmt.Errorf("failed to find subject name in annotations")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mfs, err := idx.ImageIndex(idxDigest)
|
// check if digest refers to an image or an index
|
||||||
if err != nil {
|
_, err = layoutIndex.Image(layoutDescriptorDigest)
|
||||||
return nil, fmt.Errorf("failed to extract ImageIndex for digest %s: %w", idxDigest.String(), err)
|
if err == nil {
|
||||||
|
return &Manifest{
|
||||||
|
OriginalLayers: nil,
|
||||||
|
OriginalDescriptor: nil,
|
||||||
|
SubjectName: subjectName,
|
||||||
|
SubjectDescriptor: &layoutDescriptor,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
mfs2, err := mfs.IndexManifest()
|
|
||||||
|
subjectIndex, err := layoutIndex.ImageIndex(layoutDescriptorDigest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to extract ImageIndex for digest %s: %w", layoutDescriptorDigest.String(), err)
|
||||||
|
}
|
||||||
|
subjectIndexManifest, err := subjectIndex.IndexManifest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to extract IndexManifest from ImageIndex: %w", err)
|
return nil, fmt.Errorf("failed to extract IndexManifest from ImageIndex: %w", err)
|
||||||
}
|
}
|
||||||
var subjectDescriptor *v1.Descriptor
|
var subjectDescriptor *v1.Descriptor
|
||||||
for i := range mfs2.Manifests {
|
for i := range subjectIndexManifest.Manifests {
|
||||||
manifest := &mfs2.Manifests[i]
|
manifest := &subjectIndexManifest.Manifests[i]
|
||||||
if manifest.Platform != nil {
|
if manifest.Platform != nil {
|
||||||
if manifest.Platform.Equals(*platform) {
|
if manifest.Platform.Equals(*platform) {
|
||||||
subjectDescriptor = manifest
|
subjectDescriptor = manifest
|
||||||
@@ -128,8 +142,8 @@ func manifestFromOCILayout(path string, platform *v1.Platform) (*Manifest, error
|
|||||||
if subjectDescriptor == nil {
|
if subjectDescriptor == nil {
|
||||||
return nil, fmt.Errorf("platform not found in index")
|
return nil, fmt.Errorf("platform not found in index")
|
||||||
}
|
}
|
||||||
for i := range mfs2.Manifests {
|
for i := range subjectIndexManifest.Manifests {
|
||||||
mf := &mfs2.Manifests[i]
|
mf := &subjectIndexManifest.Manifests[i]
|
||||||
if mf.Annotations[DockerReferenceType] != AttestationManifestType {
|
if mf.Annotations[DockerReferenceType] != AttestationManifestType {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -138,7 +152,7 @@ func manifestFromOCILayout(path string, platform *v1.Platform) (*Manifest, error
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
attestationImage, err := mfs.Image(mf.Digest)
|
attestationImage, err := subjectIndex.Image(mf.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to extract attestation image with digest %s: %w", mf.Digest.String(), err)
|
return nil, fmt.Errorf("failed to extract attestation image with digest %s: %w", mf.Digest.String(), err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package attestation_test
|
package attestation_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -25,7 +26,7 @@ func TestAttestationFromOCILayout(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts := &attestation.SigningOptions{}
|
opts := &attestation.SigningOptions{}
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
|
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -74,7 +75,7 @@ func TestSubjectNameAnnotations(t *testing.T) {
|
|||||||
ociLayoutPath string
|
ociLayoutPath string
|
||||||
errorStr string
|
errorStr string
|
||||||
}{
|
}{
|
||||||
{name: "oci annotation", ociLayoutPath: test.UnsignedTestImage("..")},
|
{name: "oci annotation", ociLayoutPath: test.UnsignedTestIndex("..")},
|
||||||
{name: "containerd annotation", ociLayoutPath: filepath.Join("..", "test", "testdata", "containerd-subject-layout")},
|
{name: "containerd annotation", ociLayoutPath: filepath.Join("..", "test", "testdata", "containerd-subject-layout")},
|
||||||
{name: "missing subject name", ociLayoutPath: filepath.Join("..", "test", "testdata", "missing-subject-layout"), errorStr: "failed to find subject name in annotations"},
|
{name: "missing subject name", ociLayoutPath: filepath.Join("..", "test", "testdata", "missing-subject-layout"), errorStr: "failed to find subject name in annotations"},
|
||||||
}
|
}
|
||||||
@@ -93,3 +94,14 @@ func TestSubjectNameAnnotations(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestImageDetailsFromImageLayout(t *testing.T) {
|
||||||
|
spec, err := oci.ParseImageSpec(oci.LocalPrefix+test.UnsignedTestImage(".."), oci.WithPlatform("linux/arm64"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
resolver, err := policy.CreateImageDetailsResolver(spec)
|
||||||
|
require.NoError(t, err)
|
||||||
|
desc, err := resolver.ImageDescriptor(context.Background())
|
||||||
|
require.NoError(t, err)
|
||||||
|
digest := desc.Digest.String()
|
||||||
|
assert.Equal(t, "sha256:7ae6b41655929ad8e1848064874a98ac3f68884996c79907f6525e3045f75390", digest)
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package attestation
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/docker/attest/internal/test"
|
||||||
"github.com/docker/attest/oci"
|
"github.com/docker/attest/oci"
|
||||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||||
)
|
)
|
||||||
@@ -36,7 +37,7 @@ func (r MockResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error)
|
|||||||
if r.DescriptorFn != nil {
|
if r.DescriptorFn != nil {
|
||||||
return r.DescriptorFn()
|
return r.DescriptorFn()
|
||||||
}
|
}
|
||||||
digest, err := v1.NewHash("sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620")
|
digest, err := v1.NewHash(test.UnsignedLinuxAMD64ImageDigest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ func TestAttestationReferenceTypes(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
opts := &attestation.SigningOptions{}
|
opts := &attestation.SigningOptions{}
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
indexName := fmt.Sprintf("%s/repo:root", u.Host)
|
indexName := fmt.Sprintf("%s/repo:root", u.Host)
|
||||||
@@ -209,7 +209,7 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
opts := &attestation.SigningOptions{}
|
opts := &attestation.SigningOptions{}
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
||||||
@@ -233,7 +233,7 @@ func TestReferencesInDifferentRepo(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
opts := &attestation.SigningOptions{}
|
opts := &attestation.SigningOptions{}
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
||||||
@@ -286,7 +286,7 @@ func TestCorrectArtifactTypeInTagFallback(t *testing.T) {
|
|||||||
repoName := "repo"
|
repoName := "repo"
|
||||||
|
|
||||||
opts := &attestation.SigningOptions{}
|
opts := &attestation.SigningOptions{}
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func TestRegistry(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
opts := &attestation.SigningOptions{}
|
opts := &attestation.SigningOptions{}
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
|
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -46,4 +46,14 @@ func TestRegistry(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
digest := desc.Digest.String()
|
digest := desc.Digest.String()
|
||||||
assert.True(t, strings.Contains(digest, "sha256:"))
|
assert.True(t, strings.Contains(digest, "sha256:"))
|
||||||
|
|
||||||
|
// resolver also works with platform specific digest
|
||||||
|
spec, err = oci.ParseImageSpec(fmt.Sprintf("%s@%s", indexName, digest))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
resolver, err = policy.CreateImageDetailsResolver(spec)
|
||||||
|
require.NoError(t, err)
|
||||||
|
desc, err = resolver.ImageDescriptor(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, desc.Digest.String(), digest)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ func TestSimpleStatementSigning(t *testing.T) {
|
|||||||
PredicateType: attestation.VSAPredicateType,
|
PredicateType: attestation.VSAPredicateType,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
digest, err := v1.NewHash("sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620")
|
digest, err := v1.NewHash(test.UnsignedLinuxAMD64ImageDigest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
subject := &v1.Descriptor{
|
subject := &v1.Descriptor{
|
||||||
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
||||||
|
|||||||
@@ -23,14 +23,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
UseMockKMS = true
|
UseMockKMS = true
|
||||||
|
AWSRegion = "us-east-1"
|
||||||
AWSRegion = "us-east-1"
|
AWSKMSKeyARN = "arn:aws:kms:us-east-1:175142243308:alias/doi-signing" // sandbox
|
||||||
AWSKMSKeyARN = "arn:aws:kms:us-east-1:175142243308:alias/doi-signing" // sandbox
|
UnsignedLinuxAMD64ImageDigest = "sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620"
|
||||||
|
UnsignedLinuxArm64ImageDigest = "sha256:7a76cec943853f9f7105b1976afa1bf7cd5bb6afc4e9d5852dd8da7cf81ae86e"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func UnsignedTestIndex(rel ...string) string {
|
||||||
|
rel = append(rel, "test", "testdata", "unsigned-index")
|
||||||
|
return filepath.Join(rel...)
|
||||||
|
}
|
||||||
|
|
||||||
func UnsignedTestImage(rel ...string) string {
|
func UnsignedTestImage(rel ...string) string {
|
||||||
rel = append(rel, "test", "testdata", "unsigned-test-image")
|
rel = append(rel, "test", "testdata", "unsigned-image")
|
||||||
return filepath.Join(rel...)
|
return filepath.Join(rel...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRegistryAuth(t *testing.T) {
|
func TestRegistryAuth(t *testing.T) {
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// test cases for ecr, gcr and dockerhub
|
// test cases for ecr, gcr and dockerhub
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func TestRefToPurl(t *testing.T) {
|
|||||||
|
|
||||||
// Test fix for https://github.com/docker/secure-artifacts-team-issues/issues/202
|
// Test fix for https://github.com/docker/secure-artifacts-team-issues/issues/202
|
||||||
func TestImageDigestForPlatform(t *testing.T) {
|
func TestImageDigestForPlatform(t *testing.T) {
|
||||||
idx, err := layout.ImageIndexFromPath(test.UnsignedTestImage(".."))
|
idx, err := layout.ImageIndexFromPath(test.UnsignedTestIndex(".."))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
idxm, err := idx.IndexManifest()
|
idxm, err := idx.IndexManifest()
|
||||||
@@ -86,14 +86,14 @@ func TestImageDigestForPlatform(t *testing.T) {
|
|||||||
desc, err := oci.ImageDescriptor(mfs2, p)
|
desc, err := oci.ImageDescriptor(mfs2, p)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
digest := desc.Digest.String()
|
digest := desc.Digest.String()
|
||||||
assert.Equal(t, "sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620", digest)
|
assert.Equal(t, test.UnsignedLinuxAMD64ImageDigest, digest)
|
||||||
|
|
||||||
p, err = oci.ParsePlatform("linux/arm64")
|
p, err = oci.ParsePlatform("linux/arm64")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
desc, err = oci.ImageDescriptor(mfs2, p)
|
desc, err = oci.ImageDescriptor(mfs2, p)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
digest = desc.Digest.String()
|
digest = desc.Digest.String()
|
||||||
assert.Equal(t, "sha256:7a76cec943853f9f7105b1976afa1bf7cd5bb6afc4e9d5852dd8da7cf81ae86e", digest)
|
assert.Equal(t, test.UnsignedLinuxArm64ImageDigest, digest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWithoutTag(t *testing.T) {
|
func TestWithoutTag(t *testing.T) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import (
|
|||||||
|
|
||||||
func TestSavingIndex(t *testing.T) {
|
func TestSavingIndex(t *testing.T) {
|
||||||
outputLayout := test.CreateTempDir(t, "", "mirror-test")
|
outputLayout := test.CreateTempDir(t, "", "mirror-test")
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage(".."))
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
@@ -73,7 +73,7 @@ func TestSavingReferrers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
digest, err := v1.NewHash("sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620")
|
digest, err := v1.NewHash(test.UnsignedLinuxAMD64ImageDigest)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
subject := &v1.Descriptor{
|
subject := &v1.Descriptor{
|
||||||
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/attest/attestation"
|
"github.com/docker/attest/attestation"
|
||||||
@@ -357,6 +358,7 @@ func TestVerifySubject(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
digestHex := strings.TrimPrefix(test.UnsignedLinuxAMD64ImageDigest, "sha256:")
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
defaultResolver.Image = tc.img
|
defaultResolver.Image = tc.img
|
||||||
@@ -365,7 +367,7 @@ func TestVerifySubject(t *testing.T) {
|
|||||||
return &v1.Platform{Architecture: "amd64", OS: "linux"}, nil
|
return &v1.Platform{Architecture: "amd64", OS: "linux"}, nil
|
||||||
}
|
}
|
||||||
// digest from mock resolver
|
// digest from mock resolver
|
||||||
tc.subject[0].Digest = map[string]string{"sha256": "da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620"}
|
tc.subject[0].Digest = map[string]string{"sha256": digestHex}
|
||||||
if tc.digest != "" {
|
if tc.digest != "" {
|
||||||
tc.subject[0].Digest = map[string]string{"sha256": tc.digest}
|
tc.subject[0].Digest = map[string]string{"sha256": tc.digest}
|
||||||
}
|
}
|
||||||
@@ -381,7 +383,7 @@ func TestVerifySubject(t *testing.T) {
|
|||||||
subject := []intoto.Subject{
|
subject := []intoto.Subject{
|
||||||
{
|
{
|
||||||
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
Name: "pkg:docker/alpine@latest?platform=linux%2Famd64",
|
||||||
Digest: map[string]string{"sha256": "da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620"},
|
Digest: map[string]string{"sha256": digestHex},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,36 +10,45 @@ function check_command () {
|
|||||||
|
|
||||||
function cleanup_testdata () {
|
function cleanup_testdata () {
|
||||||
echo "Cleaning up existing testdata..."
|
echo "Cleaning up existing testdata..."
|
||||||
|
rm -rf "${TESTDATA_PATH:?}/${UNSIGNED_INDEX_DIR:?}"
|
||||||
|
rm -rf "${TESTDATA_PATH:?}/${NO_PROVENANCE_INDEX_DIR:?}"
|
||||||
rm -rf "${TESTDATA_PATH:?}/${UNSIGNED_IMAGE_DIR:?}"
|
rm -rf "${TESTDATA_PATH:?}/${UNSIGNED_IMAGE_DIR:?}"
|
||||||
rm -rf "${TESTDATA_PATH:?}/${NO_PROVENANCE_IMAGE_DIR:?}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function build_unsigned_image () {
|
function build_unsigned_index () {
|
||||||
|
echo "Building $UNSIGNED_INDEX_DIR..."
|
||||||
|
docker buildx build "$TEST_INDEX_DOCKERFILE_PATH" --sbom true --provenance true --platform linux/amd64,linux/arm64 \
|
||||||
|
--output type=oci,tar=false,name="$TEST_INDEX_REPO:$TEST_INDEX_TAG",dest="$TESTDATA_PATH/$UNSIGNED_INDEX_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_no_provenance_index () {
|
||||||
|
echo "Building unsigned $NO_PROVENANCE_INDEX_DIR..."
|
||||||
|
docker buildx build "$TEST_INDEX_DOCKERFILE_PATH" --sbom true --provenance false --platform linux/amd64,linux/arm64 \
|
||||||
|
--output type=oci,tar=false,name="$TEST_INDEX_REPO:$TEST_INDEX_TAG",dest="$TESTDATA_PATH/$NO_PROVENANCE_INDEX_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_image () {
|
||||||
echo "Building $UNSIGNED_IMAGE_DIR..."
|
echo "Building $UNSIGNED_IMAGE_DIR..."
|
||||||
docker buildx build "$TEST_IMAGE_DOCKERFILE_PATH" --sbom true --provenance true --platform linux/amd64,linux/arm64 \
|
docker buildx build "$TEST_INDEX_DOCKERFILE_PATH" --sbom false --provenance false --platform linux/amd64 \
|
||||||
--output type=oci,tar=false,name="$TEST_IMAGE_REPO:$TEST_IMAGE_TAG",dest="$TESTDATA_PATH/$UNSIGNED_IMAGE_DIR"
|
--output type=oci,tar=false,name="$TEST_INDEX_REPO:$TEST_INDEX_TAG",dest="$TESTDATA_PATH/$UNSIGNED_IMAGE_DIR"
|
||||||
}
|
|
||||||
|
|
||||||
function build_no_provenance_image () {
|
|
||||||
echo "Building unsigned $NO_PROVENANCE_IMAGE_DIR..."
|
|
||||||
docker buildx build "$TEST_IMAGE_DOCKERFILE_PATH" --sbom true --provenance false --platform linux/amd64,linux/arm64 \
|
|
||||||
--output type=oci,tar=false,name="$TEST_IMAGE_REPO:$TEST_IMAGE_TAG",dest="$TESTDATA_PATH/$NO_PROVENANCE_IMAGE_DIR"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check required commands
|
# Check required commands
|
||||||
check_command docker
|
check_command docker
|
||||||
|
|
||||||
TESTDATA_PATH="../test/testdata"
|
TESTDATA_PATH="../test/testdata"
|
||||||
TEST_IMAGE_DOCKERFILE_PATH="../test"
|
TEST_INDEX_DOCKERFILE_PATH="../test"
|
||||||
TEST_IMAGE_REPO="test-image"
|
TEST_INDEX_REPO="test-image"
|
||||||
TEST_IMAGE_TAG="test"
|
TEST_INDEX_TAG="test"
|
||||||
UNSIGNED_IMAGE_DIR="unsigned-test-image"
|
UNSIGNED_INDEX_DIR="unsigned-index"
|
||||||
NO_PROVENANCE_IMAGE_DIR="no-provenance-image"
|
NO_PROVENANCE_INDEX_DIR="no-provenance-index"
|
||||||
|
UNSIGNED_IMAGE_DIR="unsigned-image"
|
||||||
ATTESTATION_PAYLOADTYPE="application/vnd.in-toto+json"
|
ATTESTATION_PAYLOADTYPE="application/vnd.in-toto+json"
|
||||||
|
|
||||||
# Run steps
|
# Run steps
|
||||||
cleanup_testdata
|
cleanup_testdata
|
||||||
build_unsigned_image
|
build_unsigned_index
|
||||||
build_no_provenance_image
|
build_no_provenance_index
|
||||||
|
build_image
|
||||||
|
|
||||||
echo "Process completed successfully."
|
echo "Process completed successfully."
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
NoProvenanceImage = filepath.Join("test", "testdata", "no-provenance-image")
|
NoProvenanceImage = filepath.Join("test", "testdata", "no-provenance-index")
|
||||||
PassPolicyDir = filepath.Join("test", "testdata", "local-policy-pass")
|
PassPolicyDir = filepath.Join("test", "testdata", "local-policy-pass")
|
||||||
PassMirrorPolicyDir = filepath.Join("test", "testdata", "local-policy-mirror")
|
PassMirrorPolicyDir = filepath.Join("test", "testdata", "local-policy-mirror")
|
||||||
PassNoTLPolicyDir = filepath.Join("test", "testdata", "local-policy-no-tl")
|
PassNoTLPolicyDir = filepath.Join("test", "testdata", "local-policy-no-tl")
|
||||||
@@ -35,8 +35,8 @@ func TestSignVerifyOCILayout(t *testing.T) {
|
|||||||
expectedAttestations int
|
expectedAttestations int
|
||||||
replace bool
|
replace bool
|
||||||
}{
|
}{
|
||||||
{"signed replaced", test.UnsignedTestImage(), 0, 4, true},
|
{"signed replaced", test.UnsignedTestIndex(), 0, 4, true},
|
||||||
{"without replace", test.UnsignedTestImage(), 4, 4, false},
|
{"without replace", test.UnsignedTestIndex(), 4, 4, false},
|
||||||
// image without provenance doesn't fail
|
// image without provenance doesn't fail
|
||||||
{"no provenance (replace)", NoProvenanceImage, 0, 2, true},
|
{"no provenance (replace)", NoProvenanceImage, 0, 2, true},
|
||||||
{"no provenance (no replace)", NoProvenanceImage, 2, 2, false},
|
{"no provenance (no replace)", NoProvenanceImage, 2, 2, false},
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
{"architecture":"unknown","os":"unknown","config":{},"rootfs":{"type":"layers","diff_ids":["sha256:da5651e8877b960aa30f32f317fbeba28f5e06f1ce4d3895b3b8770140280a2e"]}}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"architecture":"unknown","os":"unknown","config":{},"rootfs":{"type":"layers","diff_ids":["sha256:a9646604f9522bf59d203a86ac5c2354a573ea041b8846409c4fc0f8c4a70850"]}}
|
|
||||||
1
test/testdata/no-provenance-image/index.json
vendored
1
test/testdata/no-provenance-image/index.json
vendored
@@ -1 +0,0 @@
|
|||||||
{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.index.v1+json","digest":"sha256:1effe3a77c594e579388dc4553dbbe762e4457a099ab8b706e67f5f9fc934701","size":1607,"annotations":{"org.opencontainers.image.created":"2024-04-29T10:23:48Z","org.opencontainers.image.ref.name":"docker.io/library/test-image:test"}}]}
|
|
||||||
@@ -3,13 +3,13 @@
|
|||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
"config": {
|
"config": {
|
||||||
"mediaType": "application/vnd.oci.image.config.v1+json",
|
"mediaType": "application/vnd.oci.image.config.v1+json",
|
||||||
"digest": "sha256:b6ef78de3633e45d1c08019fbabb4464fabd6dd32e82c67ea2b2a3c4e8bacdf5",
|
"digest": "sha256:bb0ed50656ccdb2eb114407de579554426777d6dc0e4206a6f746afb4ee5237e",
|
||||||
"size": 167
|
"size": 167
|
||||||
},
|
},
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.in-toto+json",
|
"mediaType": "application/vnd.in-toto+json",
|
||||||
"digest": "sha256:a9646604f9522bf59d203a86ac5c2354a573ea041b8846409c4fc0f8c4a70850",
|
"digest": "sha256:618f1e2f903648dde23cc38dc0ed7eed83d5394a6902bb7bfae8fa707c2e5c33",
|
||||||
"size": 946,
|
"size": 946,
|
||||||
"annotations": {
|
"annotations": {
|
||||||
"in-toto.io/predicate-type": "https://spdx.dev/Document"
|
"in-toto.io/predicate-type": "https://spdx.dev/Document"
|
||||||
Binary file not shown.
@@ -3,13 +3,13 @@
|
|||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
"config": {
|
"config": {
|
||||||
"mediaType": "application/vnd.oci.image.config.v1+json",
|
"mediaType": "application/vnd.oci.image.config.v1+json",
|
||||||
"digest": "sha256:2e82727457f04f320b643cb6e13bcbafb8e0dc0adc0443f1a25666f9518c5071",
|
"digest": "sha256:816b20ea86474dcfb2906ffaf4410262dfcb0d49fdfb60698775f7bc10aad7fb",
|
||||||
"size": 167
|
"size": 167
|
||||||
},
|
},
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.in-toto+json",
|
"mediaType": "application/vnd.in-toto+json",
|
||||||
"digest": "sha256:da5651e8877b960aa30f32f317fbeba28f5e06f1ce4d3895b3b8770140280a2e",
|
"digest": "sha256:f0dac65dd0ff6a656c419c654ac672c38029a3f1a4b4acce062bd2f5a923ffae",
|
||||||
"size": 946,
|
"size": 946,
|
||||||
"annotations": {
|
"annotations": {
|
||||||
"in-toto.io/predicate-type": "https://spdx.dev/Document"
|
"in-toto.io/predicate-type": "https://spdx.dev/Document"
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"manifests": [
|
"manifests": [
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
"digest": "sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620",
|
"digest": "sha256:7ae6b41655929ad8e1848064874a98ac3f68884996c79907f6525e3045f75390",
|
||||||
"size": 476,
|
"size": 476,
|
||||||
"platform": {
|
"platform": {
|
||||||
"architecture": "amd64",
|
"architecture": "amd64",
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
"digest": "sha256:7a76cec943853f9f7105b1976afa1bf7cd5bb6afc4e9d5852dd8da7cf81ae86e",
|
"digest": "sha256:52f7a760b9322aa1af76d998763868b7d1bfec2331a2574a438ef44c92c0c46d",
|
||||||
"size": 476,
|
"size": 476,
|
||||||
"platform": {
|
"platform": {
|
||||||
"architecture": "arm64",
|
"architecture": "arm64",
|
||||||
@@ -22,10 +22,10 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
"digest": "sha256:2aaebbb079957470e7c0adddbb054b2b4c01f717d408efba753da2bf6e8905da",
|
"digest": "sha256:059eea09507d0f904b8892ee59fcd3ddec1a637fc40fb7c83c432c6ff27e2f91",
|
||||||
"size": 558,
|
"size": 558,
|
||||||
"annotations": {
|
"annotations": {
|
||||||
"vnd.docker.reference.digest": "sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620",
|
"vnd.docker.reference.digest": "sha256:7ae6b41655929ad8e1848064874a98ac3f68884996c79907f6525e3045f75390",
|
||||||
"vnd.docker.reference.type": "attestation-manifest"
|
"vnd.docker.reference.type": "attestation-manifest"
|
||||||
},
|
},
|
||||||
"platform": {
|
"platform": {
|
||||||
@@ -35,10 +35,10 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
"digest": "sha256:9b009d6b84b1ed941070b3f919823446286a674ad669d0baa8ab2c358aeb3a82",
|
"digest": "sha256:0b1ee0f360b073d2f76ceed15a63e291659fbcc6c3caf3be39e437d8344b520e",
|
||||||
"size": 558,
|
"size": 558,
|
||||||
"annotations": {
|
"annotations": {
|
||||||
"vnd.docker.reference.digest": "sha256:7a76cec943853f9f7105b1976afa1bf7cd5bb6afc4e9d5852dd8da7cf81ae86e",
|
"vnd.docker.reference.digest": "sha256:52f7a760b9322aa1af76d998763868b7d1bfec2331a2574a438ef44c92c0c46d",
|
||||||
"vnd.docker.reference.type": "attestation-manifest"
|
"vnd.docker.reference.type": "attestation-manifest"
|
||||||
},
|
},
|
||||||
"platform": {
|
"platform": {
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"architecture":"amd64","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"WorkingDir":"/"},"created":"2024-09-27T16:10:13.292759474Z","history":[{"created":"2024-09-27T16:10:13.292759474Z","created_by":"COPY /tmp/hello.txt / # buildkit","comment":"buildkit.dockerfile.v0"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:81a78ab7aa0b72d665a9c203b4c30f0423e434b789ed95b2d418e60a1b726470"]}}
|
||||||
@@ -3,13 +3,13 @@
|
|||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
"config": {
|
"config": {
|
||||||
"mediaType": "application/vnd.oci.image.config.v1+json",
|
"mediaType": "application/vnd.oci.image.config.v1+json",
|
||||||
"digest": "sha256:d85d624a324422194b43cccd975b5752cf0acaedd668bb525fcd40c3587cc460",
|
"digest": "sha256:c0bd7799c46e00830b4d7cb8c1f622d14aae81643a90be5ec38c9be4bdd70f6c",
|
||||||
"size": 453
|
"size": 438
|
||||||
},
|
},
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
||||||
"digest": "sha256:97a548f8d65d9ab617f608dd621f59e0d43a3b346f34c34eb58da31f00a9b0ad",
|
"digest": "sha256:07d9a868932bd092fa0a4c4df943785a7ba9cee12dbf446d02488319a5fbf336",
|
||||||
"size": 116
|
"size": 116
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1 +1 @@
|
|||||||
{"_type":"https://in-toto.io/Statement/v0.1","predicateType":"https://spdx.dev/Document","subject":[{"name":"pkg:docker/test-image@test?platform=linux%2Famd64","digest":{"sha256":"da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620"}}],"predicate":{"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"sbom","documentNamespace":"https://anchore.com/syft/dir/sbom-6d900ae6-587d-4695-9c01-511801a85b65","creationInfo":{"licenseListVersion":"3.23","creators":["Organization: Anchore, Inc","Tool: syft-v0.105.0","Tool: buildkit-v0.12.4"],"created":"2024-03-08T16:42:30Z"},"packages":[{"name":"sbom","SPDXID":"SPDXRef-DocumentRoot-Directory-sbom","supplier":"NOASSERTION","downloadLocation":"NOASSERTION","filesAnalyzed":false,"primaryPackagePurpose":"FILE"}],"relationships":[{"spdxElementId":"SPDXRef-DOCUMENT","relatedSpdxElement":"SPDXRef-DocumentRoot-Directory-sbom","relationshipType":"DESCRIBES"}]}}
|
{"_type":"https://in-toto.io/Statement/v0.1","predicateType":"https://spdx.dev/Document","subject":[{"name":"pkg:docker/test-image@test?platform=linux%2Famd64","digest":{"sha256":"7ae6b41655929ad8e1848064874a98ac3f68884996c79907f6525e3045f75390"}}],"predicate":{"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"sbom","documentNamespace":"https://anchore.com/syft/dir/sbom-b92d7d2e-7ffe-4d0a-8194-9af68e80e169","creationInfo":{"licenseListVersion":"3.23","creators":["Organization: Anchore, Inc","Tool: syft-v0.105.0","Tool: buildkit-v0.15.2"],"created":"2024-09-27T16:10:21Z"},"packages":[{"name":"sbom","SPDXID":"SPDXRef-DocumentRoot-Directory-sbom","supplier":"NOASSERTION","downloadLocation":"NOASSERTION","filesAnalyzed":false,"primaryPackagePurpose":"FILE"}],"relationships":[{"spdxElementId":"SPDXRef-DOCUMENT","relatedSpdxElement":"SPDXRef-DocumentRoot-Directory-sbom","relationshipType":"DESCRIBES"}]}}
|
||||||
@@ -3,13 +3,13 @@
|
|||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
"config": {
|
"config": {
|
||||||
"mediaType": "application/vnd.oci.image.config.v1+json",
|
"mediaType": "application/vnd.oci.image.config.v1+json",
|
||||||
"digest": "sha256:1c70b3e7c3a57801501ec127aa6c918c390c373294ec4fc48f2c6fe703fcc6fe",
|
"digest": "sha256:363133d587b90ff7a21f7b32a96be8422c6799683f0e1e6d71de5c03a82ab35e",
|
||||||
"size": 453
|
"size": 438
|
||||||
},
|
},
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
||||||
"digest": "sha256:97a548f8d65d9ab617f608dd621f59e0d43a3b346f34c34eb58da31f00a9b0ad",
|
"digest": "sha256:07d9a868932bd092fa0a4c4df943785a7ba9cee12dbf446d02488319a5fbf336",
|
||||||
"size": 116
|
"size": 116
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"architecture":"unknown","os":"unknown","config":{},"rootfs":{"type":"layers","diff_ids":["sha256:f0dac65dd0ff6a656c419c654ac672c38029a3f1a4b4acce062bd2f5a923ffae"]}}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"architecture":"unknown","os":"unknown","config":{},"rootfs":{"type":"layers","diff_ids":["sha256:618f1e2f903648dde23cc38dc0ed7eed83d5394a6902bb7bfae8fa707c2e5c33"]}}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"architecture":"arm64","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"WorkingDir":"/"},"created":"2024-09-27T16:10:13.292759474Z","history":[{"created":"2024-09-27T16:10:13.292759474Z","created_by":"COPY /tmp/hello.txt / # buildkit","comment":"buildkit.dockerfile.v0"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:81a78ab7aa0b72d665a9c203b4c30f0423e434b789ed95b2d418e60a1b726470"]}}
|
||||||
@@ -1 +1 @@
|
|||||||
{"_type":"https://in-toto.io/Statement/v0.1","predicateType":"https://spdx.dev/Document","subject":[{"name":"pkg:docker/test-image@test?platform=linux%2Farm64","digest":{"sha256":"7a76cec943853f9f7105b1976afa1bf7cd5bb6afc4e9d5852dd8da7cf81ae86e"}}],"predicate":{"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"sbom","documentNamespace":"https://anchore.com/syft/dir/sbom-6d900ae6-587d-4695-9c01-511801a85b65","creationInfo":{"licenseListVersion":"3.23","creators":["Organization: Anchore, Inc","Tool: syft-v0.105.0","Tool: buildkit-v0.12.4"],"created":"2024-03-08T16:42:30Z"},"packages":[{"name":"sbom","SPDXID":"SPDXRef-DocumentRoot-Directory-sbom","supplier":"NOASSERTION","downloadLocation":"NOASSERTION","filesAnalyzed":false,"primaryPackagePurpose":"FILE"}],"relationships":[{"spdxElementId":"SPDXRef-DOCUMENT","relatedSpdxElement":"SPDXRef-DocumentRoot-Directory-sbom","relationshipType":"DESCRIBES"}]}}
|
{"_type":"https://in-toto.io/Statement/v0.1","predicateType":"https://spdx.dev/Document","subject":[{"name":"pkg:docker/test-image@test?platform=linux%2Farm64","digest":{"sha256":"52f7a760b9322aa1af76d998763868b7d1bfec2331a2574a438ef44c92c0c46d"}}],"predicate":{"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"sbom","documentNamespace":"https://anchore.com/syft/dir/sbom-b92d7d2e-7ffe-4d0a-8194-9af68e80e169","creationInfo":{"licenseListVersion":"3.23","creators":["Organization: Anchore, Inc","Tool: syft-v0.105.0","Tool: buildkit-v0.15.2"],"created":"2024-09-27T16:10:21Z"},"packages":[{"name":"sbom","SPDXID":"SPDXRef-DocumentRoot-Directory-sbom","supplier":"NOASSERTION","downloadLocation":"NOASSERTION","filesAnalyzed":false,"primaryPackagePurpose":"FILE"}],"relationships":[{"spdxElementId":"SPDXRef-DOCUMENT","relatedSpdxElement":"SPDXRef-DocumentRoot-Directory-sbom","relationshipType":"DESCRIBES"}]}}
|
||||||
1
test/testdata/no-provenance-index/index.json
vendored
Normal file
1
test/testdata/no-provenance-index/index.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.index.v1+json","digest":"sha256:1e3839ac14fba8c5e4db574df2046ce21a9e012e4030305cea97ad3f07f81a4a","size":1607,"annotations":{"org.opencontainers.image.created":"2024-09-27T20:22:06Z","org.opencontainers.image.ref.name":"docker.io/library/test-image:test"}}]}
|
||||||
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
{"architecture":"amd64","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"WorkingDir":"/"},"created":"2024-09-27T16:10:13.292759474Z","history":[{"created":"2024-09-27T16:10:13.292759474Z","created_by":"COPY /tmp/hello.txt / # buildkit","comment":"buildkit.dockerfile.v0"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:81a78ab7aa0b72d665a9c203b4c30f0423e434b789ed95b2d418e60a1b726470"]}}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
|
"config": {
|
||||||
|
"mediaType": "application/vnd.oci.image.config.v1+json",
|
||||||
|
"digest": "sha256:363133d587b90ff7a21f7b32a96be8422c6799683f0e1e6d71de5c03a82ab35e",
|
||||||
|
"size": 438
|
||||||
|
},
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
|
||||||
|
"digest": "sha256:07d9a868932bd092fa0a4c4df943785a7ba9cee12dbf446d02488319a5fbf336",
|
||||||
|
"size": 116
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1
test/testdata/unsigned-image/index.json
vendored
Normal file
1
test/testdata/unsigned-image/index.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:7ae6b41655929ad8e1848064874a98ac3f68884996c79907f6525e3045f75390","size":476,"annotations":{"org.opencontainers.image.created":"2024-09-27T20:22:07Z","org.opencontainers.image.ref.name":"docker.io/library/test-image:test"},"platform":{"architecture":"amd64","os":"linux"}}]}
|
||||||
1
test/testdata/unsigned-index/oci-layout
vendored
Normal file
1
test/testdata/unsigned-index/oci-layout
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"imageLayoutVersion":"1.0.0"}
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"architecture":"amd64","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"WorkingDir":"/","OnBuild":null},"created":"2024-03-08T16:42:30.065465358Z","history":[{"created":"2024-03-08T16:42:30.065465358Z","created_by":"COPY /tmp/hello.txt / # buildkit","comment":"buildkit.dockerfile.v0"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:b842af8c2f1451ffc802ae4139819eaea8441223357642548d8a25ab5c52cff7"]}}
|
|
||||||
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
{"architecture":"arm64","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"WorkingDir":"/","OnBuild":null},"created":"2024-03-08T16:42:30.065465358Z","history":[{"created":"2024-03-08T16:42:30.065465358Z","created_by":"COPY /tmp/hello.txt / # buildkit","comment":"buildkit.dockerfile.v0"}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:b842af8c2f1451ffc802ae4139819eaea8441223357642548d8a25ab5c52cff7"]}}
|
|
||||||
@@ -80,7 +80,7 @@ func TestVSA(t *testing.T) {
|
|||||||
opts := &attestation.SigningOptions{
|
opts := &attestation.SigningOptions{
|
||||||
TransparencyLog: tlog.GetMockTL(),
|
TransparencyLog: tlog.GetMockTL(),
|
||||||
}
|
}
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage())
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
signedManifests, err := SignStatements(ctx, attIdx.Index, signer, opts)
|
signedManifests, err := SignStatements(ctx, attIdx.Index, signer, opts)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -106,7 +106,7 @@ func TestVSA(t *testing.T) {
|
|||||||
assert.Empty(t, results.Violations)
|
assert.Empty(t, results.Violations)
|
||||||
|
|
||||||
if assert.NotNil(t, results.Input) {
|
if assert.NotNil(t, results.Input) {
|
||||||
assert.Equal(t, "sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620", results.Input.Digest)
|
assert.Equal(t, test.UnsignedLinuxAMD64ImageDigest, results.Input.Digest)
|
||||||
assert.NotNil(t, results.Input.Tag)
|
assert.NotNil(t, results.Input.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ func TestVerificationFailure(t *testing.T) {
|
|||||||
opts := &attestation.SigningOptions{
|
opts := &attestation.SigningOptions{
|
||||||
TransparencyLog: tlog.GetMockTL(),
|
TransparencyLog: tlog.GetMockTL(),
|
||||||
}
|
}
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage())
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
signedManifests, err := SignStatements(ctx, attIdx.Index, signer, opts)
|
signedManifests, err := SignStatements(ctx, attIdx.Index, signer, opts)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -216,7 +216,7 @@ func TestSignVerify(t *testing.T) {
|
|||||||
{name: "mirror with verification", signTL: false, policyDir: LocalKeysPolicy, imageName: "mirror.org/library/test-image:test"},
|
{name: "mirror with verification", signTL: false, policyDir: LocalKeysPolicy, imageName: "mirror.org/library/test-image:test"},
|
||||||
}
|
}
|
||||||
|
|
||||||
attIdx, err := oci.IndexFromPath(test.UnsignedTestImage())
|
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user