package storage import ( "regexp" "testing" "github.com/docker/distribution" "github.com/docker/distribution/context" "github.com/docker/distribution/manifest" "github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/registry/storage/driver/inmemory" ) func TestVerifyManifestForeignLayer(t *testing.T) { ctx := context.Background() inmemoryDriver := inmemory.New() registry := createRegistry(t, inmemoryDriver, ManifestURLsAllowRegexp(regexp.MustCompile("^https?://foo")), ManifestURLsDenyRegexp(regexp.MustCompile("^https?://foo/nope"))) repo := makeRepository(t, registry, "test") manifestService := makeManifestService(t, repo) config, err := repo.Blobs(ctx).Put(ctx, schema2.MediaTypeImageConfig, nil) if err != nil { t.Fatal(err) } layer, err := repo.Blobs(ctx).Put(ctx, schema2.MediaTypeLayer, nil) if err != nil { t.Fatal(err) } foreignLayer := distribution.Descriptor{ Digest: "sha256:463435349086340864309863409683460843608348608934092322395278926a", Size: 6323, MediaType: schema2.MediaTypeForeignLayer, } template := schema2.Manifest{ Versioned: manifest.Versioned{ SchemaVersion: 2, MediaType: schema2.MediaTypeManifest, }, Config: config, } type testcase struct { BaseLayer distribution.Descriptor URLs []string Err error } cases := []testcase{ { foreignLayer, nil, errMissingURL, }, { // regular layers may have foreign urls layer, []string{"http://foo/bar"}, nil, }, { foreignLayer, []string{"file:///local/file"}, errInvalidURL, }, { foreignLayer, []string{"http://foo/bar#baz"}, errInvalidURL, }, { foreignLayer, []string{""}, errInvalidURL, }, { foreignLayer, []string{"https://foo/bar", ""}, errInvalidURL, }, { foreignLayer, []string{"", "https://foo/bar"}, errInvalidURL, }, { foreignLayer, []string{"http://nope/bar"}, errInvalidURL, }, { foreignLayer, []string{"http://foo/nope"}, errInvalidURL, }, { foreignLayer, []string{"http://foo/bar"}, nil, }, { foreignLayer, []string{"https://foo/bar"}, nil, }, } for _, c := range cases { m := template l := c.BaseLayer l.URLs = c.URLs m.Layers = []distribution.Descriptor{l} dm, err := schema2.FromStruct(m) if err != nil { t.Error(err) continue } _, err = manifestService.Put(ctx, dm) if verr, ok := err.(distribution.ErrManifestVerification); ok { // Extract the first error if len(verr) == 2 { if _, ok = verr[1].(distribution.ErrManifestBlobUnknown); ok { err = verr[0] } } } if err != c.Err { t.Errorf("%#v: expected %v, got %v", l, c.Err, err) } } }