Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable registry fallback for repository credentials #1304

Merged
merged 1 commit into from
Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 16 additions & 18 deletions pkg/docker/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -665,10 +665,10 @@ func findAuthentication(ref reference.Named, registry, path string, legacyFormat
// those entries even in non-legacyFormat ~/.docker/config.json.
// The docker.io registry still uses the /v1/ key with a special host name,
// so account for that as well.
registry = normalizeRegistry(registry)
registry = normalizeAuthFileKey(registry, legacyFormat)
mtrmac marked this conversation as resolved.
Show resolved Hide resolved
normalizedAuths := map[string]dockerAuthConfig{}
for k, v := range auths.AuthConfigs {
normalizedAuths[normalizeRegistry(k)] = v
normalizedAuths[normalizeAuthFileKey(k, legacyFormat)] = v
}

if val, exists := normalizedAuths[registry]; exists {
Expand Down Expand Up @@ -723,29 +723,27 @@ func decodeDockerAuth(conf dockerAuthConfig) (types.DockerAuthConfig, error) {
}, nil
}

// convertToHostname converts a registry url which has http|https prepended
// to just an hostname.
// Copied from github.com/docker/docker/registry/auth.go
func convertToHostname(url string) string {
stripped := stripScheme(url)
nameParts := strings.SplitN(stripped, "/", 2)
return nameParts[0]
}

// stripScheme striped the http|https scheme from the provided URL.
func stripScheme(url string) string {
stripped := strings.TrimPrefix(url, "http://")
// normalizeAuthFileKey takes a key, converts it to a host name and normalizes
// the resulting registry.
func normalizeAuthFileKey(key string, legacyFormat bool) string {
stripped := strings.TrimPrefix(key, "http://")
stripped = strings.TrimPrefix(stripped, "https://")
return stripped

if legacyFormat || stripped != key {
stripped = strings.SplitN(stripped, "/", 2)[0]
}

return normalizeRegistry(stripped)
}

// normalizeRegistry converts the provided registry if a known docker.io host
// is provided.
func normalizeRegistry(registry string) string {
normalized := convertToHostname(registry)
switch normalized {
switch registry {
case "registry-1.docker.io", "docker.io":
return "index.docker.io"
}
return normalized
return registry
}

// validateKey verifies that the input key does not have a prefix that is not
Expand Down
91 changes: 91 additions & 0 deletions pkg/docker/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -886,3 +886,94 @@ func TestValidateKey(t *testing.T) {
assert.Equal(t, tc.isNamespaced, isNamespaced)
}
}

func TestSetGetCredentials(t *testing.T) {
const (
username = "username"
password = "password"
)

tmpDir, err := ioutil.TempDir("", "auth-test-")
require.NoError(t, err)
defer os.RemoveAll(tmpDir)

for _, tc := range []struct {
name string
set string
get string
useLegacyAPI bool
shouldAuth bool
}{
{
name: "Should match namespace",
set: "quay.io/foo",
get: "quay.io/foo/a",
shouldAuth: true,
},
{
name: "Should match registry if repository provided",
set: "quay.io",
get: "quay.io/foo",
shouldAuth: true,
},
{
name: "Should not match different repository",
set: "quay.io/foo",
get: "quay.io/bar",
shouldAuth: false,
},
{
name: "Should match legacy registry entry (new API)",
set: "https://quay.io/v1/",
get: "quay.io/foo",
shouldAuth: true,
},
{
name: "Should match legacy registry entry (legacy API)",
set: "https://quay.io/v1/",
get: "quay.io",
shouldAuth: true,
useLegacyAPI: true,
},
} {

// Create a new empty SystemContext referring an empty auth.json
tmpFile, err := ioutil.TempFile("", "auth.json-")
require.NoError(t, err)
defer os.RemoveAll(tmpFile.Name())

sys := &types.SystemContext{}
if tc.useLegacyAPI {
sys.LegacyFormatAuthFilePath = tmpFile.Name()
_, err = tmpFile.WriteString(fmt.Sprintf(
`{"%s":{"auth":"dXNlcm5hbWU6cGFzc3dvcmQ="}}`, tc.set,
))
} else {
sys.AuthFilePath = tmpFile.Name()
_, err = tmpFile.WriteString(fmt.Sprintf(
`{"auths":{"%s":{"auth":"dXNlcm5hbWU6cGFzc3dvcmQ="}}}`, tc.set,
))
}
require.NoError(t, err)

// Try to authenticate against them
var auth types.DockerAuthConfig
if !tc.useLegacyAPI {
ref, err := reference.ParseNamed(tc.get)
require.NoError(t, err)
auth, err = getCredentialsWithHomeDir(sys, ref, reference.Domain(ref), tmpDir)
require.NoError(t, err)
} else {
auth, err = getCredentialsWithHomeDir(sys, nil, tc.get, tmpDir)
require.NoError(t, err)
}

if tc.shouldAuth {
assert.Equal(t, username, auth.Username, tc.name)
assert.Equal(t, password, auth.Password, tc.name)
} else {
assert.Empty(t, auth.Username, tc.name)
assert.Empty(t, auth.Password, tc.name)
}
}
}