Redefine Policy.Specific scopes to use fully expanded hostname/namespace/repo format

Using the canonical minimized format of Docker references introduces too
many ambiguities.

This also removes some validation of the scope string, but all that was
really doing was rejecting completely invalid input like uppercase.

Sadly it is not qutie obvious that we can detect and reject mistakes like
using "busybox" as a scope instead of the correct
"docker.io/library/busybox".  Perhaps require at least one dot or port
number in the host name?
This commit is contained in:
Miloslav Trmač
2016-05-31 02:12:28 +02:00
parent 488a535aa0
commit 677f711c6c
3 changed files with 8 additions and 10 deletions

View File

@@ -88,10 +88,9 @@ func (m *policySpecificMap) UnmarshalJSON(data []byte) error {
// So, use a temporary map of pointers-to-slices and convert. // So, use a temporary map of pointers-to-slices and convert.
tmpMap := map[string]*PolicyRequirements{} tmpMap := map[string]*PolicyRequirements{}
if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} { if err := paranoidUnmarshalJSONObject(data, func(key string) interface{} {
// Check that the scope format is at least plausible. // FIXME? We might want to validate the scope format.
if _, err := reference.ParseNamed(key); err != nil { // Note that reference.ParseNamed is unsuitable; it would understand "example.com" as
return nil // FIXME? This returns an "Unknown key" error instead of saying that the format is invalid. // "docker.io/library/example.com"
}
// paranoidUnmarshalJSONObject detects key duplication for us, check just to be safe. // paranoidUnmarshalJSONObject detects key duplication for us, check just to be safe.
if _, ok := tmpMap[key]; ok { if _, ok := tmpMap[key]; ok {
return nil return nil

View File

@@ -160,7 +160,7 @@ func TestPolicyUnmarshalJSON(t *testing.T) {
xNewPRSignedByKeyData(SBKeyTypeGPGKeys, []byte("abc"), NewPRMMatchExact()), xNewPRSignedByKeyData(SBKeyTypeGPGKeys, []byte("abc"), NewPRMMatchExact()),
}, },
Specific: map[string]PolicyRequirements{ Specific: map[string]PolicyRequirements{
"library/busybox": []PolicyRequirement{ "docker.io/library/busybox": []PolicyRequirement{
xNewPRSignedByKeyData(SBKeyTypeGPGKeys, []byte("def"), NewPRMMatchExact()), xNewPRSignedByKeyData(SBKeyTypeGPGKeys, []byte("def"), NewPRMMatchExact()),
}, },
"registry.access.redhat.com": []PolicyRequirement{ "registry.access.redhat.com": []PolicyRequirement{
@@ -191,11 +191,8 @@ func TestPolicyUnmarshalJSON(t *testing.T) {
func(v mSI) { v["specific"] = []string{} }, func(v mSI) { v["specific"] = []string{} },
// "default" is an invalid PolicyRequirements // "default" is an invalid PolicyRequirements
func(v mSI) { v["default"] = PolicyRequirements{} }, func(v mSI) { v["default"] = PolicyRequirements{} },
// Invalid scope name in "specific". Uppercase is invalid in Docker reference components.
// Get valid PolicyRequirements by copying them from "library/buxybox".
func(v mSI) { x(v, "specific")["INVALIDUPPERCASE"] = x(v, "specific")["library/busybox"] },
// A field in "specific" is an invalid PolicyRequirements // A field in "specific" is an invalid PolicyRequirements
func(v mSI) { x(v, "specific")["library/busybox"] = PolicyRequirements{} }, func(v mSI) { x(v, "specific")["docker.io/library/busybox"] = PolicyRequirements{} },
} }
for _, fn := range breakFns { for _, fn := range breakFns {
err = tryUnmarshalModifiedPolicy(t, &p, validJSON, fn) err = tryUnmarshalModifiedPolicy(t, &p, validJSON, fn)

View File

@@ -11,7 +11,9 @@ type Policy struct {
// Default applies to any image which does not have a matching policy in Specific. // Default applies to any image which does not have a matching policy in Specific.
Default PolicyRequirements `json:"default"` Default PolicyRequirements `json:"default"`
// Specific applies to images matching scope, the map key. // Specific applies to images matching scope, the map key.
// Scope is registry/server, namespace in a registry, single repository. // Scope is hostname[/zero/or/more/namespaces[/repository[:tag|@digest]]]; note that in order to be
// unambiguous, this must use a fully expanded format, e.g. "docker.io/library/busybox" or
// "docker.io/library", not "busybox" or "library".
// FIXME: Scope syntax - should it be namespaced docker:something ? Or, in the worst case, a composite object (we couldn't use a JSON map) // FIXME: Scope syntax - should it be namespaced docker:something ? Or, in the worst case, a composite object (we couldn't use a JSON map)
// Most specific scope wins, duplication is prohibited (hard failure). // Most specific scope wins, duplication is prohibited (hard failure).
// Defaults to an empty map if not specified. // Defaults to an empty map if not specified.