Skip to content

Commit

Permalink
Update embedded Docker reference, if any, in copy.Image
Browse files Browse the repository at this point in the history
Add EmbbeddedDockerReference to types.ManifestUpdateOptions, and use it
in copy.Image.  Pushing signed schema1 images to a different location
is impossible (skopeo users can use --remove-signatures), but signing an
unsigned schema1 image while pushing it does work.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
  • Loading branch information
mtrmac committed Oct 12, 2016
1 parent 8599c55 commit f679c9e
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 3 deletions.
35 changes: 33 additions & 2 deletions copy/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,13 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
return fmt.Errorf("Can not copy signatures: %v", err)
}
}

canModifyManifest := len(sigs) == 0
manifestUpdates := types.ManifestUpdateOptions{}

if err := updateEmbeddedDockerReference(&manifestUpdates, dest, src, canModifyManifest); err != nil {
return err
}

srcConfigInfo := src.ConfigInfo()
if srcConfigInfo.Digest != "" {
Expand Down Expand Up @@ -177,8 +183,6 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
}
destLayerInfos = append(destLayerInfos, destLayer)
}

manifestUpdates := types.ManifestUpdateOptions{}
if layerDigestsDiffer(srcLayerInfos, destLayerInfos) {
manifestUpdates.LayerInfos = destLayerInfos
}
Expand Down Expand Up @@ -233,6 +237,33 @@ func Image(ctx *types.SystemContext, policyContext *signature.PolicyContext, des
return nil
}

// updateEmbeddedDockerReference handles the Docker reference embedded in Docker schema1 manifests.
func updateEmbeddedDockerReference(manifestUpdates *types.ManifestUpdateOptions, dest types.ImageDestination, src types.Image, canModifyManifest bool) error {
manifestRef, err := src.EmbeddedDockerReference()
if err != nil {
return fmt.Errorf("Error parsing source image for embedded Docker reference: %v", err)
}
if manifestRef == nil {
return nil // No embedded manifest
}

destRef := dest.Reference().DockerReference()
if destRef == nil {
return nil // Destination does not care about Docker references
}

if destRef.String() == manifestRef.String() {
return nil // The reference matches
}

if !canModifyManifest {
return fmt.Errorf("Copying a schema1 image with embedded Docker reference %s to %s (Docker reference %s) would invalidate existing signatures. Explicitly enable signature removal to proceed anyway",
manifestRef.String(), transports.ImageName(dest.Reference()), destRef.String())
}
manifestUpdates.EmbeddedDockerReference = destRef
return nil
}

// layerDigestsDiffer return true iff the digests in a and b differ (ignoring sizes and possible other fields)
func layerDigestsDiffer(a, b []types.BlobInfo) bool {
if len(a) != len(b) {
Expand Down
8 changes: 8 additions & 0 deletions image/docker_schema1.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ func (m *manifestSchema1) UpdatedImage(options types.ManifestUpdateOptions) (typ
copy.FSLayers[(len(options.LayerInfos)-1)-i].BlobSum = info.Digest
}
}
if options.EmbeddedDockerReference != nil {
copy.Name = options.EmbeddedDockerReference.Name()
if tagged, isTagged := options.EmbeddedDockerReference.(reference.NamedTagged); isTagged {
copy.Tag = tagged.Tag()
} else {
copy.Tag = ""
}
}
return memoryImageFromManifest(&copy), nil
}

Expand Down
4 changes: 4 additions & 0 deletions image/docker_schema2.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package image

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"

Expand Down Expand Up @@ -102,5 +103,8 @@ func (m *manifestSchema2) UpdatedImage(options types.ManifestUpdateOptions) (typ
copy.LayersDescriptors[i].Size = info.Size
}
}
if options.EmbeddedDockerReference != nil {
return nil, errors.New("ManifestUpdateOptions.EmbeddedDockerReference is not supported for schema2 images")
}
return memoryImageFromManifest(&copy), nil
}
3 changes: 2 additions & 1 deletion types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ type Image interface {

// ManifestUpdateOptions is a way to pass named optional arguments to Image.UpdatedManifest
type ManifestUpdateOptions struct {
LayerInfos []BlobInfo // Complete BlobInfos (size+digest) which should replace the originals, in order (the root layer first, and then successive layered layers)
LayerInfos []BlobInfo // Complete BlobInfos (size+digest) which should replace the originals, in order (the root layer first, and then successive layered layers)
EmbeddedDockerReference reference.Named
}

// ImageInspectInfo is a set of metadata describing Docker images, primarily their manifest and configuration.
Expand Down

0 comments on commit f679c9e

Please sign in to comment.