Skip to content

Commit

Permalink
Trust the registry for signed schema1 digests (#470)
Browse files Browse the repository at this point in the history
Trading one hack for another -- instead of calculating the digest for
signed schema 1 images, we'll just trust the registry's
Docker-Content-Digest header, since calculating them correctly would
require us to do string surgery with signatures.

This allows clients to do tag -> digest resolution for schema 1 images
even though we don't explicitly handle them.
  • Loading branch information
jonjohnsonjr committed Jun 19, 2019
1 parent 876b885 commit abf9ef0
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 4 deletions.
10 changes: 7 additions & 3 deletions pkg/v1/remote/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,16 @@ func (f *fetcher) fetchManifest(ref name.Reference, acceptable []types.MediaType
}

mediaType := types.MediaType(resp.Header.Get("Content-Type"))
contentDigest, err := v1.NewHash(resp.Header.Get("Docker-Content-Digest"))
if err == nil && mediaType == types.DockerManifestSchema1Signed {
// If we can parse the digest from the header, and it's a signed schema 1
// manifest, let's use that for the digest to appease older registries.
digest = contentDigest
}

// Validate the digest matches what we asked for, if pulling by digest.
if dgst, ok := ref.(name.Digest); ok {
if mediaType == types.DockerManifestSchema1Signed {
// Digests for this are stupid to calculate, ignore it.
} else if digest.String() != dgst.DigestStr() {
if digest.String() != dgst.DigestStr() {
return nil, nil, fmt.Errorf("manifest digest: %q does not match requested digest: %q for %q", digest, dgst.DigestStr(), f.Ref)
}
} else {
Expand Down
8 changes: 7 additions & 1 deletion pkg/v1/remote/descriptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (

func TestGetSchema1(t *testing.T) {
expectedRepo := "foo/bar"
fakeDigest := "sha256:0000000000000000000000000000000000000000000000000000000000000000"
manifestPath := fmt.Sprintf("/v2/%s/manifests/latest", expectedRepo)

server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -36,7 +37,8 @@ func TestGetSchema1(t *testing.T) {
if r.Method != http.MethodGet {
t.Errorf("Method; got %v, want %v", r.Method, http.MethodGet)
}
w.Header().Set("Content-Type", string(types.DockerManifestSchema1))
w.Header().Set("Content-Type", string(types.DockerManifestSchema1Signed))
w.Header().Set("Docker-Content-Digest", fakeDigest)
w.Write([]byte("doesn't matter"))
default:
t.Fatalf("Unexpected path: %v", r.URL.Path)
Expand All @@ -56,6 +58,10 @@ func TestGetSchema1(t *testing.T) {
t.Fatalf("Get(%s) = %v", tag, err)
}

if desc.Digest.String() != fakeDigest {
t.Errorf("Descriptor.Digest = %q, expected %q", desc.Digest, fakeDigest)
}

// Should fail based on media type.
if _, err := desc.Image(); err != ErrSchema1 {
t.Errorf("Image() = %v, expected remote.ErrSchema1", err)
Expand Down

0 comments on commit abf9ef0

Please sign in to comment.