forked from TrueCloudLab/distribution
61e5803b56
Until we have some experience hosting foreign layer manifests, the Hub operators wish to limit foreign layers on Hub. To that end, this change adds registry configuration options to restrict the URLs that may appear in pushed manifests. Signed-off-by: Noah Treuhaft <noah.treuhaft@docker.com>
135 lines
2.6 KiB
Go
135 lines
2.6 KiB
Go
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.MediaTypeConfig, 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,
|
|
},
|
|
{
|
|
layer,
|
|
[]string{"http://foo/bar"},
|
|
errUnexpectedURL,
|
|
},
|
|
{
|
|
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)
|
|
}
|
|
}
|
|
}
|