diff --git a/pkg/attest/example_sign_test.go b/pkg/attest/example_sign_test.go index 358bb2e..0a90d36 100644 --- a/pkg/attest/example_sign_test.go +++ b/pkg/attest/example_sign_test.go @@ -47,7 +47,7 @@ func ExampleSign_remote() { } // push image index with signed attestation-manifests - err = mirror.PushToRegistry(signedImageIndex, ref) + err = mirror.PushIndexToRegistry(signedImageIndex, ref) if err != nil { panic(err) } @@ -62,7 +62,7 @@ func ExampleSign_remote() { }, }, }) - err = mirror.SaveAsOCILayout(idx, path) + err = mirror.SaveIndexAsOCILayout(idx, path) if err != nil { panic(err) } diff --git a/pkg/attestation/referrers_test.go b/pkg/attestation/referrers_test.go index a536c31..0b7173a 100644 --- a/pkg/attestation/referrers_test.go +++ b/pkg/attestation/referrers_test.go @@ -61,7 +61,7 @@ func TestAttestationReferenceTypes(t *testing.T) { indexName := fmt.Sprintf("%s/repo:root", u.Host) require.NoError(t, err) - err = mirror.PushToRegistry(signedIndex, indexName) + err = mirror.PushIndexToRegistry(signedIndex, indexName) for _, platform := range platforms { // can eval policy in the normal way @@ -121,7 +121,7 @@ func TestReferencesInDifferentRepo(t *testing.T) { require.NoError(t, err) indexName := fmt.Sprintf("%s/%s:latest", serverUrl.Host, repoName) - err = mirror.PushToRegistry(attIdx.Index, indexName) + err = mirror.PushIndexToRegistry(attIdx.Index, indexName) require.NoError(t, err) signedImages, err := attest.SignedAttestationImages(ctx, attIdx.Index, signer, opts) @@ -130,7 +130,7 @@ func TestReferencesInDifferentRepo(t *testing.T) { // push signed attestation image to the ref server for _, img := range signedImages { // push references using subject-digest.att convention - err = mirror.PushToRegistry(img.Image, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerUrl.Host, repoName)) + err = mirror.PushImageToRegistry(img.Image, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerUrl.Host, repoName)) require.NoError(t, err) } mfs2, err := attIdx.Index.IndexManifest() diff --git a/pkg/mirror/example_mirror_test.go b/pkg/mirror/example_mirror_test.go index c4b6cbd..2b9cea8 100644 --- a/pkg/mirror/example_mirror_test.go +++ b/pkg/mirror/example_mirror_test.go @@ -13,7 +13,7 @@ import ( ) type TufMirrorOutput struct { - metadata *v1.Image + metadata v1.Image delegatedMetadata []*mirror.MirrorImage targets []*mirror.MirrorImage delegatedTargets []*mirror.MirrorIndex @@ -80,7 +80,7 @@ func ExampleNewTufMirror() { func mirrorToRegistry(o *TufMirrorOutput) error { // push metadata to registry metadataRepo := "registry-1.docker.io/docker/tuf-metadata:latest" - err := mirror.PushToRegistry(o.metadata, metadataRepo) + err := mirror.PushImageToRegistry(o.metadata, metadataRepo) if err != nil { return err } @@ -91,7 +91,7 @@ func mirrorToRegistry(o *TufMirrorOutput) error { return fmt.Errorf("failed to get repo without tag: %s", metadataRepo) } imageName := fmt.Sprintf("%s:%s", repo, metadata.Tag) - err = mirror.PushToRegistry(metadata.Image, imageName) + err = mirror.PushImageToRegistry(metadata.Image, imageName) if err != nil { return err } @@ -101,7 +101,7 @@ func mirrorToRegistry(o *TufMirrorOutput) error { targetsRepo := "registry-1.docker.io/docker/tuf-targets" for _, target := range o.targets { imageName := fmt.Sprintf("%s:%s", targetsRepo, target.Tag) - err = mirror.PushToRegistry(target.Image, imageName) + err = mirror.PushImageToRegistry(target.Image, imageName) if err != nil { return err } @@ -109,7 +109,7 @@ func mirrorToRegistry(o *TufMirrorOutput) error { // push delegated targets to registry for _, target := range o.delegatedTargets { imageName := fmt.Sprintf("%s:%s", targetsRepo, target.Tag) - err = mirror.PushToRegistry(target.Index, imageName) + err = mirror.PushIndexToRegistry(target.Index, imageName) if err != nil { return err } @@ -119,14 +119,14 @@ func mirrorToRegistry(o *TufMirrorOutput) error { func mirrorToLocal(o *TufMirrorOutput, outputPath string) error { // output metadata to local directory - err := mirror.SaveAsOCILayout(o.metadata, outputPath) + err := mirror.SaveImageAsOCILayout(o.metadata, outputPath) if err != nil { return err } // output delegated metadata to local directory for _, metadata := range o.delegatedMetadata { path := filepath.Join(outputPath, metadata.Tag) - err = mirror.SaveAsOCILayout(metadata.Image, path) + err = mirror.SaveImageAsOCILayout(metadata.Image, path) if err != nil { return err } @@ -135,7 +135,7 @@ func mirrorToLocal(o *TufMirrorOutput, outputPath string) error { // output top-level targets to local directory for _, target := range o.targets { path := filepath.Join(outputPath, target.Tag) - err = mirror.SaveAsOCILayout(target.Image, path) + err = mirror.SaveImageAsOCILayout(target.Image, path) if err != nil { return err } @@ -143,7 +143,7 @@ func mirrorToLocal(o *TufMirrorOutput, outputPath string) error { // output delegated targets to local directory for _, target := range o.delegatedTargets { path := filepath.Join(outputPath, target.Tag) - err = mirror.SaveAsOCILayout(target.Index, path) + err = mirror.SaveIndexAsOCILayout(target.Index, path) if err != nil { return err } diff --git a/pkg/mirror/metadata.go b/pkg/mirror/metadata.go index aca4e8f..81f1c9f 100644 --- a/pkg/mirror/metadata.go +++ b/pkg/mirror/metadata.go @@ -17,7 +17,7 @@ import ( // ----------------- // GetMetadataManifest returns an image with TUF root metadata as layers -func (m *TufMirror) GetMetadataManifest(metadataURL string) (*v1.Image, error) { +func (m *TufMirror) GetMetadataManifest(metadataURL string) (v1.Image, error) { metadata, err := m.getTufMetadataMirror(metadataURL) if err != nil { return nil, fmt.Errorf("failed to get metadata: %w", err) @@ -78,7 +78,7 @@ func (m *TufMirror) getTufMetadataMirror(metadataURL string) (*TufMetadata, erro } // buildMetadataManifest returns an OCI image with TUF metadata as layers with annotations -func (m *TufMirror) buildMetadataManifest(metadata *TufMetadata) (*v1.Image, error) { +func (m *TufMirror) buildMetadataManifest(metadata *TufMetadata) (v1.Image, error) { img := empty.Image img = mutate.MediaType(img, types.OCIManifestSchema1) img = mutate.ConfigMediaType(img, types.OCIConfigJSON) @@ -87,17 +87,17 @@ func (m *TufMirror) buildMetadataManifest(metadata *TufMetadata) (*v1.Image, err if err != nil { return nil, fmt.Errorf("failed to make role layer: %w", err) } - img, err = mutate.Append(img, *layers...) + img, err = mutate.Append(img, layers...) if err != nil { return nil, fmt.Errorf("failed to append role layer to image: %w", err) } } - return &img, nil + return img, nil } // makeRoleLayers returns a list of layers for a given TUF role -func (m *TufMirror) makeRoleLayers(role TufRole, tufMetadata *TufMetadata) (*[]mutate.Addendum, error) { - layers := new([]mutate.Addendum) +func (m *TufMirror) makeRoleLayers(role TufRole, tufMetadata *TufMetadata) ([]mutate.Addendum, error) { + var layers []mutate.Addendum ann := map[string]string{tufFileAnnotation: ""} switch role { case metadata.ROOT: @@ -108,7 +108,7 @@ func (m *TufMirror) makeRoleLayers(role TufRole, tufMetadata *TufMetadata) (*[]m layers = m.annotatedMetaLayers(tufMetadata.Targets) case metadata.TIMESTAMP: ann[tufFileAnnotation] = fmt.Sprintf("%s.json", role) - *layers = append(*layers, mutate.Addendum{Layer: static.NewLayer(tufMetadata.Timestamp, tufMetadataMediaType), Annotations: ann}) + layers = append(layers, mutate.Addendum{Layer: static.NewLayer(tufMetadata.Timestamp, tufMetadataMediaType), Annotations: ann}) default: return nil, fmt.Errorf("unsupported TUF role: %s", role) } @@ -116,11 +116,11 @@ func (m *TufMirror) makeRoleLayers(role TufRole, tufMetadata *TufMetadata) (*[]m } // annotatedMetaLayers returns a list of layers with annotations for each TUF metadata file -func (m *TufMirror) annotatedMetaLayers(meta map[string][]byte) *[]mutate.Addendum { - layers := new([]mutate.Addendum) +func (m *TufMirror) annotatedMetaLayers(meta map[string][]byte) []mutate.Addendum { + var layers []mutate.Addendum for name, data := range meta { ann := map[string]string{tufFileAnnotation: name} - *layers = append(*layers, mutate.Addendum{Layer: static.NewLayer(data, tufMetadataMediaType), Annotations: ann}) + layers = append(layers, mutate.Addendum{Layer: static.NewLayer(data, tufMetadataMediaType), Annotations: ann}) } return layers } @@ -144,8 +144,8 @@ func (m *TufMirror) GetDelegatedMetadataMirrors() ([]*MirrorImage, error) { } // getDelegatedTargetsMetadata returns delegated targets metadata as a list of DelegatedTargetMetadata (role name and data) -func (m *TufMirror) getDelegatedTargetsMetadata() (*[]DelegatedTargetMetadata, error) { - delegatedTargets := new([]DelegatedTargetMetadata) +func (m *TufMirror) getDelegatedTargetsMetadata() ([]DelegatedTargetMetadata, error) { + var delegatedTargets []DelegatedTargetMetadata md := m.TufClient.GetMetadata() for _, role := range md.Targets[metadata.TARGETS].Signed.Delegations.Roles { roleMetadata, err := m.TufClient.LoadDelegatedTargets(role.Name, metadata.TARGETS) @@ -165,15 +165,15 @@ func (m *TufMirror) getDelegatedTargetsMetadata() (*[]DelegatedTargetMetadata, e if md.Root.Signed.ConsistentSnapshot { version = strconv.FormatInt(meta.Version, 10) } - *delegatedTargets = append(*delegatedTargets, DelegatedTargetMetadata{Name: role.Name, Version: version, Data: roleBytes}) + delegatedTargets = append(delegatedTargets, DelegatedTargetMetadata{Name: role.Name, Version: version, Data: roleBytes}) } return delegatedTargets, nil } // buildDelegatedMetadataManifests returns a list of mirrors (image/tag pairs) for each delegated target role metadata -func (m *TufMirror) buildDelegatedMetadataManifests(delegated *[]DelegatedTargetMetadata) ([]*MirrorImage, error) { +func (m *TufMirror) buildDelegatedMetadataManifests(delegated []DelegatedTargetMetadata) ([]*MirrorImage, error) { manifests := []*MirrorImage{} - for _, role := range *delegated { + for _, role := range delegated { img := empty.Image img = mutate.MediaType(img, types.OCIManifestSchema1) img = mutate.ConfigMediaType(img, types.OCIConfigJSON) @@ -183,7 +183,7 @@ func (m *TufMirror) buildDelegatedMetadataManifests(delegated *[]DelegatedTarget if err != nil { return nil, fmt.Errorf("failed to append delegated targets layer to image: %w", err) } - manifests = append(manifests, &MirrorImage{Image: &img, Tag: role.Name}) + manifests = append(manifests, &MirrorImage{Image: img, Tag: role.Name}) } return manifests, nil } diff --git a/pkg/mirror/metadata_test.go b/pkg/mirror/metadata_test.go index 0aeb277..03b722c 100644 --- a/pkg/mirror/metadata_test.go +++ b/pkg/mirror/metadata_test.go @@ -46,8 +46,7 @@ func TestGetMetadataManifest(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, img) - image := *img - mf, err := image.RawManifest() + mf, err := img.RawManifest() assert.NoError(t, err) type Annotations struct { diff --git a/pkg/mirror/mirror.go b/pkg/mirror/mirror.go index 22c9625..291761f 100644 --- a/pkg/mirror/mirror.go +++ b/pkg/mirror/mirror.go @@ -26,7 +26,7 @@ func NewTufMirror(root []byte, tufPath, metadataURL, targetsURL string, versionC return &TufMirror{TufClient: tufClient, tufPath: tufPath, metadataURL: metadataURL, targetsURL: targetsURL}, nil } -func PushToRegistry(image any, imageName string) error { +func PushImageToRegistry(image v1.Image, imageName string) error { // Parse the image name ref, err := name.ParseReference(imageName) if err != nil { @@ -38,45 +38,48 @@ func PushToRegistry(image any, imageName string) error { log.Fatalf("Failed to get authenticator: %v", err) } // Push the image to the registry - switch image := image.(type) { - case v1.Image: - if err := remote.Write(ref, image, remote.WithAuth(auth)); err != nil { - return fmt.Errorf("failed to push image %s: %w", imageName, err) - } - case v1.ImageIndex: - if err := remote.WriteIndex(ref, image, remote.WithAuth(auth)); err != nil { - return fmt.Errorf("failed to push image index %s: %w", imageName, err) - } - default: - return fmt.Errorf("unknown image type") - } - return nil + return remote.Write(ref, image, remote.WithAuth(auth)) } -func SaveAsOCILayout(image any, path string) error { +func PushIndexToRegistry(image v1.ImageIndex, imageName string) error { + // Parse the index name + ref, err := name.ParseReference(imageName) + if err != nil { + log.Fatalf("Failed to parse image name: %v", err) + } + // Get the authenticator from the default Docker keychain + auth, err := authn.DefaultKeychain.Resolve(ref.Context()) + if err != nil { + log.Fatalf("Failed to get authenticator: %v", err) + } + // Push the index to the registry + return remote.WriteIndex(ref, image, remote.WithAuth(auth)) +} + +func SaveImageAsOCILayout(image v1.Image, path string) error { // Save the image to the local filesystem - err := os.MkdirAll(path, os.FileMode(0744)) + err := os.MkdirAll(path, os.FileMode(0755)) if err != nil { return fmt.Errorf("failed to create directory: %w", err) } - switch image := image.(type) { - case v1.Image: - index := empty.Index - l, err := layout.Write(path, index) - if err != nil { - return fmt.Errorf("failed to create index: %w", err) - } - err = l.AppendImage(image) - if err != nil { - return fmt.Errorf("failed to append image to index: %w", err) - } - case v1.ImageIndex: - _, err := layout.Write(path, image) - if err != nil { - return fmt.Errorf("failed to create index: %w", err) - } - default: - return fmt.Errorf("unknown image type") + index := empty.Index + l, err := layout.Write(path, index) + if err != nil { + return fmt.Errorf("failed to create index: %w", err) + } + return l.AppendImage(image) +} + +func SaveIndexAsOCILayout(image v1.ImageIndex, path string) error { + // Save the index to the local filesystem + err := os.MkdirAll(path, os.FileMode(0755)) + if err != nil { + return fmt.Errorf("failed to create directory: %w", err) + } + + _, err = layout.Write(path, image) + if err != nil { + return fmt.Errorf("failed to create index: %w", err) } return nil } diff --git a/pkg/mirror/targets.go b/pkg/mirror/targets.go index 78c86d0..89a4fd2 100644 --- a/pkg/mirror/targets.go +++ b/pkg/mirror/targets.go @@ -42,7 +42,7 @@ func (m *TufMirror) GetTufTargetMirrors() ([]*MirrorImage, error) { if err != nil { return nil, fmt.Errorf("failed to append role layer to image: %w", err) } - targetMirrors = append(targetMirrors, &MirrorImage{Image: &img, Tag: name}) + targetMirrors = append(targetMirrors, &MirrorImage{Image: img, Tag: name}) } return targetMirrors, nil } @@ -103,7 +103,7 @@ func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) { }, }) } - mirror = append(mirror, &MirrorIndex{Index: &index, Tag: role.Name}) + mirror = append(mirror, &MirrorIndex{Index: index, Tag: role.Name}) } return mirror, nil } diff --git a/pkg/mirror/targets_test.go b/pkg/mirror/targets_test.go index e81ddaf..2ff296b 100644 --- a/pkg/mirror/targets_test.go +++ b/pkg/mirror/targets_test.go @@ -36,7 +36,7 @@ func TestGetTufTargetsMirror(t *testing.T) { // check for image layer annotations for _, target := range targets { - img := *target.Image + img := target.Image mf, err := img.RawManifest() assert.NoError(t, err) @@ -83,7 +83,7 @@ func TestGetDelegatedTargetMirrors(t *testing.T) { // check for index image annotations for _, mirror := range mirrors { - idx := *mirror.Index + idx := mirror.Index mf, err := idx.RawManifest() assert.NoError(t, err) diff --git a/pkg/mirror/types.go b/pkg/mirror/types.go index c93cc5d..694217e 100644 --- a/pkg/mirror/types.go +++ b/pkg/mirror/types.go @@ -32,12 +32,12 @@ type DelegatedTargetMetadata struct { } type MirrorImage struct { - Image *v1.Image + Image v1.Image Tag string } type MirrorIndex struct { - Index *v1.ImageIndex + Index v1.ImageIndex Tag string }