vendor c/common@main

Update the `--filter reference=...` tests to reflect recent changes in
c/common.  The reference values now match as specified without
implicitly adding wildcards arounds.

Fixes: #11905
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2021-12-06 08:34:50 +01:00
parent e79c47bc0c
commit 76f5100be5
12 changed files with 228 additions and 167 deletions

View File

@@ -110,7 +110,8 @@ func GuessMIMEType(manifest []byte) string {
}
switch meta.MediaType {
case DockerV2Schema2MediaType, DockerV2ListMediaType: // A recognized type.
case DockerV2Schema2MediaType, DockerV2ListMediaType,
imgspecv1.MediaTypeImageManifest, imgspecv1.MediaTypeImageIndex: // A recognized type.
return meta.MediaType
}
// this is the only way the function can return DockerV2Schema1MediaType, and recognizing that is essential for stripping the JWS signatures = computing the correct manifest digest.
@@ -121,9 +122,9 @@ func GuessMIMEType(manifest []byte) string {
}
return DockerV2Schema1MediaType
case 2:
// best effort to understand if this is an OCI image since mediaType
// isn't in the manifest for OCI anymore
// for docker v2s2 meta.MediaType should have been set. But given the data, this is our best guess.
// Best effort to understand if this is an OCI image since mediaType
// wasn't in the manifest for OCI image-spec < 1.0.2.
// For docker v2s2 meta.MediaType should have been set. But given the data, this is our best guess.
ociMan := struct {
Config struct {
MediaType string `json:"mediaType"`

View File

@@ -66,6 +66,7 @@ func OCI1FromComponents(config imgspecv1.Descriptor, layers []imgspecv1.Descript
return &OCI1{
imgspecv1.Manifest{
Versioned: specs.Versioned{SchemaVersion: 2},
MediaType: imgspecv1.MediaTypeImageManifest,
Config: config,
Layers: layers,
},

View File

@@ -119,6 +119,7 @@ func OCI1IndexFromComponents(components []imgspecv1.Descriptor, annotations map[
index := OCI1Index{
imgspecv1.Index{
Versioned: imgspec.Versioned{SchemaVersion: 2},
MediaType: imgspecv1.MediaTypeImageIndex,
Manifests: make([]imgspecv1.Descriptor, len(components)),
Annotations: dupStringStringMap(annotations),
},
@@ -195,6 +196,7 @@ func OCI1IndexFromManifest(manifest []byte) (*OCI1Index, error) {
index := OCI1Index{
Index: imgspecv1.Index{
Versioned: imgspec.Versioned{SchemaVersion: 2},
MediaType: imgspecv1.MediaTypeImageIndex,
Manifests: []imgspecv1.Descriptor{},
Annotations: make(map[string]string),
},

View File

@@ -54,8 +54,8 @@ var (
// SetCredentials stores the username and password in a location
// appropriate for sys and the users configuration.
// A valid key can be either a registry hostname or additionally a namespace if
// the AuthenticationFileHelper is being unsed.
// A valid key is a repository, a namespace within a registry, or a registry hostname;
// using forms other than just a registry may fail depending on configuration.
// Returns a human-redable description of the location that was updated.
// NOTE: The return value is only intended to be read by humans; its form is not an API,
// it may change (or new forms can be added) any time.
@@ -128,11 +128,15 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
// possible sources, and then call `GetCredentials` on them. That
// prevents us from having to reverse engineer the logic in
// `GetCredentials`.
allRegistries := make(map[string]bool)
addRegistry := func(s string) {
allRegistries[s] = true
allKeys := make(map[string]bool)
addKey := func(s string) {
allKeys[s] = true
}
// To use GetCredentials, we must at least convert the URL forms into host names.
// While we're at it, well also canonicalize docker.io to the standard format.
normalizedDockerIORegistry := normalizeRegistry("docker.io")
helpers, err := sysregistriesv2.CredentialHelpers(sys)
if err != nil {
return nil, err
@@ -151,10 +155,14 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
// direct mapping to a registry, so we can just
// walk the map.
for registry := range auths.CredHelpers {
addRegistry(registry)
addKey(registry)
}
for registry := range auths.AuthConfigs {
addRegistry(registry)
for key := range auths.AuthConfigs {
key := normalizeAuthFileKey(key, path.legacyFormat)
if key == normalizedDockerIORegistry {
key = "docker.io"
}
addKey(key)
}
}
// External helpers.
@@ -166,7 +174,7 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
switch errors.Cause(err) {
case nil:
for registry := range creds {
addRegistry(registry)
addKey(registry)
}
case exec.ErrNotFound:
// It's okay if the helper doesn't exist.
@@ -179,8 +187,8 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
// Now use `GetCredentials` to the specific auth configs for each
// previously listed registry.
authConfigs := make(map[string]types.DockerAuthConfig)
for registry := range allRegistries {
authConf, err := GetCredentials(sys, registry)
for key := range allKeys {
authConf, err := GetCredentials(sys, key)
if err != nil {
if credentials.IsErrCredentialsNotFoundMessage(err.Error()) {
// Ignore if the credentials could not be found (anymore).
@@ -189,7 +197,7 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
// Note: we rely on the logging in `GetCredentials`.
return nil, err
}
authConfigs[registry] = authConf
authConfigs[key] = authConf
}
return authConfigs, nil
@@ -230,16 +238,14 @@ func getAuthFilePaths(sys *types.SystemContext, homeDir string) []authPath {
return paths
}
// GetCredentials returns the registry credentials stored in the
// registry-specific credential helpers or in the default global credentials
// helpers with falling back to using either auth.json
// file or .docker/config.json, including support for OAuth2 and IdentityToken.
// GetCredentials returns the registry credentials matching key, appropriate for
// sys and the users configuration.
// If an entry is not found, an empty struct is returned.
// A valid key is a repository, a namespace within a registry, or a registry hostname.
//
// GetCredentialsForRef should almost always be used in favor of this API to
// allow different credentials for different repositories on the same registry.
func GetCredentials(sys *types.SystemContext, registry string) (types.DockerAuthConfig, error) {
return getCredentialsWithHomeDir(sys, nil, registry, homedir.Get())
// GetCredentialsForRef should almost always be used in favor of this API.
func GetCredentials(sys *types.SystemContext, key string) (types.DockerAuthConfig, error) {
return getCredentialsWithHomeDir(sys, key, homedir.Get())
}
// GetCredentialsForRef returns the registry credentials necessary for
@@ -247,30 +253,34 @@ func GetCredentials(sys *types.SystemContext, registry string) (types.DockerAuth
// appropriate for sys and the users configuration.
// If an entry is not found, an empty struct is returned.
func GetCredentialsForRef(sys *types.SystemContext, ref reference.Named) (types.DockerAuthConfig, error) {
return getCredentialsWithHomeDir(sys, ref, reference.Domain(ref), homedir.Get())
return getCredentialsWithHomeDir(sys, ref.Name(), homedir.Get())
}
// getCredentialsWithHomeDir is an internal implementation detail of
// GetCredentialsForRef and GetCredentials. It exists only to allow testing it
// with an artificial home directory.
func getCredentialsWithHomeDir(sys *types.SystemContext, ref reference.Named, registry, homeDir string) (types.DockerAuthConfig, error) {
// consistency check of the ref and registry arguments
if ref != nil && reference.Domain(ref) != registry {
return types.DockerAuthConfig{}, errors.Errorf(
"internal error: provided reference domain %q name does not match registry %q",
reference.Domain(ref), registry,
)
func getCredentialsWithHomeDir(sys *types.SystemContext, key, homeDir string) (types.DockerAuthConfig, error) {
_, err := validateKey(key)
if err != nil {
return types.DockerAuthConfig{}, err
}
if sys != nil && sys.DockerAuthConfig != nil {
logrus.Debugf("Returning credentials for %s from DockerAuthConfig", registry)
logrus.Debugf("Returning credentials for %s from DockerAuthConfig", key)
return *sys.DockerAuthConfig, nil
}
var registry string // We compute this once because it is used in several places.
if firstSlash := strings.IndexRune(key, '/'); firstSlash != -1 {
registry = key[:firstSlash]
} else {
registry = key
}
// Anonymous function to query credentials from auth files.
getCredentialsFromAuthFiles := func() (types.DockerAuthConfig, string, error) {
for _, path := range getAuthFilePaths(sys, homeDir) {
authConfig, err := findAuthentication(ref, registry, path.path, path.legacyFormat)
authConfig, err := findCredentialsInFile(key, registry, path.path, path.legacyFormat)
if err != nil {
return types.DockerAuthConfig{}, "", err
}
@@ -291,57 +301,61 @@ func getCredentialsWithHomeDir(sys *types.SystemContext, ref reference.Named, re
for _, helper := range helpers {
var (
creds types.DockerAuthConfig
helperKey string
credHelperPath string
err error
)
switch helper {
// Special-case the built-in helper for auth files.
case sysregistriesv2.AuthenticationFileHelper:
helperKey = key
creds, credHelperPath, err = getCredentialsFromAuthFiles()
// External helpers.
default:
// This intentionally uses "registry", not "key"; we don't support namespaced
// credentials in helpers, but a "registry" is a valid parent of "key".
helperKey = registry
creds, err = getAuthFromCredHelper(helper, registry)
}
if err != nil {
logrus.Debugf("Error looking up credentials for %s in credential helper %s: %v", registry, helper, err)
logrus.Debugf("Error looking up credentials for %s in credential helper %s: %v", helperKey, helper, err)
multiErr = multierror.Append(multiErr, err)
continue
}
if len(creds.Username)+len(creds.Password)+len(creds.IdentityToken) == 0 {
continue
if creds != (types.DockerAuthConfig{}) {
msg := fmt.Sprintf("Found credentials for %s in credential helper %s", helperKey, helper)
if credHelperPath != "" {
msg = fmt.Sprintf("%s in file %s", msg, credHelperPath)
}
logrus.Debug(msg)
return creds, nil
}
msg := fmt.Sprintf("Found credentials for %s in credential helper %s", registry, helper)
if credHelperPath != "" {
msg = fmt.Sprintf("%s in file %s", msg, credHelperPath)
}
logrus.Debug(msg)
return creds, nil
}
if multiErr != nil {
return types.DockerAuthConfig{}, multiErr
}
logrus.Debugf("No credentials for %s found", registry)
logrus.Debugf("No credentials for %s found", key)
return types.DockerAuthConfig{}, nil
}
// GetAuthentication returns the registry credentials stored in the
// registry-specific credential helpers or in the default global credentials
// helpers with falling back to using either auth.json file or
// .docker/config.json
// GetAuthentication returns the registry credentials matching key, appropriate for
// sys and the users configuration.
// If an entry is not found, an empty struct is returned.
// A valid key is a repository, a namespace within a registry, or a registry hostname.
//
// Deprecated: This API only has support for username and password. To get the
// support for oauth2 in container registry authentication, we added the new
// GetCredentials API. The new API should be used and this API is kept to
// GetCredentialsForRef and GetCredentials API. The new API should be used and this API is kept to
// maintain backward compatibility.
func GetAuthentication(sys *types.SystemContext, registry string) (string, string, error) {
return getAuthenticationWithHomeDir(sys, registry, homedir.Get())
func GetAuthentication(sys *types.SystemContext, key string) (string, string, error) {
return getAuthenticationWithHomeDir(sys, key, homedir.Get())
}
// getAuthenticationWithHomeDir is an internal implementation detail of GetAuthentication,
// it exists only to allow testing it with an artificial home directory.
func getAuthenticationWithHomeDir(sys *types.SystemContext, registry, homeDir string) (string, string, error) {
auth, err := getCredentialsWithHomeDir(sys, nil, registry, homeDir)
func getAuthenticationWithHomeDir(sys *types.SystemContext, key, homeDir string) (string, string, error) {
auth, err := getCredentialsWithHomeDir(sys, key, homeDir)
if err != nil {
return "", "", err
}
@@ -353,8 +367,8 @@ func getAuthenticationWithHomeDir(sys *types.SystemContext, registry, homeDir st
// RemoveAuthentication removes credentials for `key` from all possible
// sources such as credential helpers and auth files.
// A valid key can be either a registry hostname or additionally a namespace if
// the AuthenticationFileHelper is being unsed.
// A valid key is a repository, a namespace within a registry, or a registry hostname;
// using forms other than just a registry may fail depending on configuration.
func RemoveAuthentication(sys *types.SystemContext, key string) error {
isNamespaced, err := validateKey(key)
if err != nil {
@@ -639,26 +653,27 @@ func deleteAuthFromCredHelper(credHelper, registry string) error {
return helperclient.Erase(p, registry)
}
// findAuthentication looks for auth of registry in path. If ref is
// not nil, then it will be taken into account when looking up the
// authentication credentials.
func findAuthentication(ref reference.Named, registry, path string, legacyFormat bool) (types.DockerAuthConfig, error) {
// findCredentialsInFile looks for credentials matching "key"
// (which is "registry" or a namespace in "registry") in "path".
func findCredentialsInFile(key, registry, path string, legacyFormat bool) (types.DockerAuthConfig, error) {
auths, err := readJSONFile(path, legacyFormat)
if err != nil {
return types.DockerAuthConfig{}, errors.Wrapf(err, "reading JSON file %q", path)
}
// First try cred helpers. They should always be normalized.
// This intentionally uses "registry", not "key"; we don't support namespaced
// credentials in helpers.
if ch, exists := auths.CredHelpers[registry]; exists {
return getAuthFromCredHelper(ch, registry)
}
// Support for different paths in auth.
// Support sub-registry namespaces in auth.
// (This is not a feature of ~/.docker/config.json; we support it even for
// those files as an extension.)
var keys []string
if !legacyFormat && ref != nil {
keys = authKeysForRef(ref)
if !legacyFormat {
keys = authKeysForKey(key)
} else {
keys = []string{registry}
}
@@ -689,23 +704,22 @@ func findAuthentication(ref reference.Named, registry, path string, legacyFormat
return types.DockerAuthConfig{}, nil
}
// authKeysForRef returns the valid paths for a provided reference. For example,
// when given a reference "quay.io/repo/ns/image:tag", then it would return
// authKeysForKey returns the keys matching a provided auth file key, in order
// from the best match to worst. For example,
// when given a repository key "quay.io/repo/ns/image", it returns
// - quay.io/repo/ns/image
// - quay.io/repo/ns
// - quay.io/repo
// - quay.io
func authKeysForRef(ref reference.Named) (res []string) {
name := ref.Name()
func authKeysForKey(key string) (res []string) {
for {
res = append(res, name)
res = append(res, key)
lastSlash := strings.LastIndex(name, "/")
lastSlash := strings.LastIndex(key, "/")
if lastSlash == -1 {
break
}
name = name[:lastSlash]
key = key[:lastSlash]
}
return res
@@ -759,11 +773,24 @@ func normalizeRegistry(registry string) string {
// validateKey verifies that the input key does not have a prefix that is not
// allowed and returns an indicator if the key is namespaced.
func validateKey(key string) (isNamespaced bool, err error) {
func validateKey(key string) (bool, error) {
if strings.HasPrefix(key, "http://") || strings.HasPrefix(key, "https://") {
return isNamespaced, errors.Errorf("key %s contains http[s]:// prefix", key)
return false, errors.Errorf("key %s contains http[s]:// prefix", key)
}
// Ideally this should only accept explicitly valid keys, compare
// validateIdentityRemappingPrefix. For now, just reject values that look
// like tagged or digested values.
if strings.ContainsRune(key, '@') {
return false, fmt.Errorf(`key %s contains a '@' character`, key)
}
firstSlash := strings.IndexRune(key, '/')
isNamespaced := firstSlash != -1
// Reject host/repo:tag, but allow localhost:5000 and localhost:5000/foo.
if isNamespaced && strings.ContainsRune(key[firstSlash+1:], ':') {
return false, fmt.Errorf(`key %s contains a ':' character after host[:port]`, key)
}
// check if the provided key contains one or more subpaths.
return strings.ContainsRune(key, '/'), nil
return isNamespaced, nil
}