mirror of https://github.com/containers/image.git
/authentication/credential/g
"authentication" refers to a process, not to username:password; "authentications" is not a thing. So, use "credential" where appropriate, and make similar related adjustments. Leave the existing public API of pkg/docker/config, and types.DockerAuthConfig, unchanged, though. Should not change behavior. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
This commit is contained in:
parent
72e00bc1ce
commit
c2ea2dd458
|
|
@ -27,7 +27,7 @@ and an auth token in the form of a base64 encoded string as value of `auth`. The
|
||||||
token is built from the concatenation of the username, a colon, and the
|
token is built from the concatenation of the username, a colon, and the
|
||||||
password. The registry name can additionally contain a repository name (an image
|
password. The registry name can additionally contain a repository name (an image
|
||||||
name without tag or digest) and namespaces. The path (or namespace) is matched
|
name without tag or digest) and namespaces. The path (or namespace) is matched
|
||||||
in its hierarchical order when checking for available authentications. For
|
in its hierarchical order when checking for available credentials. For
|
||||||
example, an image pull for `my-registry.local/namespace/user/image:latest` will
|
example, an image pull for `my-registry.local/namespace/user/image:latest` will
|
||||||
result in a lookup in `auth.json` in the following order:
|
result in a lookup in `auth.json` in the following order:
|
||||||
|
|
||||||
|
|
@ -78,8 +78,8 @@ An entry can be removed by using a `logout` command from a container
|
||||||
tool such as `podman logout` or `buildah logout`.
|
tool such as `podman logout` or `buildah logout`.
|
||||||
|
|
||||||
In addition, credential helpers can be configured for specific registries and the credentials-helper
|
In addition, credential helpers can be configured for specific registries and the credentials-helper
|
||||||
software can be used to manage the credentials in a more secure way than depending on the base64 encoded authentication
|
software can be used to manage the credentials in a more secure way than depending on the base64 encoded credentials
|
||||||
provided by `login`. If the credential helpers are configured for specific registries, the base64 encoded authentication will not be used
|
provided by `login`. If the credential helpers are configured for specific registries, the base64 encoded credentials will not be used
|
||||||
for operations concerning credentials of the specified registries.
|
for operations concerning credentials of the specified registries.
|
||||||
|
|
||||||
When the credential helper is in use on a Linux platform, the auth.json file would contain keys that specify the registry domain, and values that specify the suffix of the program to use (i.e. everything after docker-credential-). For example:
|
When the credential helper is in use on a Linux platform, the auth.json file would contain keys that specify the registry domain, and values that specify the suffix of the program to use (i.e. everything after docker-credential-). For example:
|
||||||
|
|
|
||||||
|
|
@ -48,9 +48,9 @@ var (
|
||||||
ErrNotSupported = errors.New("not supported")
|
ErrNotSupported = errors.New("not supported")
|
||||||
)
|
)
|
||||||
|
|
||||||
// authPath combines a path to a file with container registry access keys,
|
// authPath combines a path to a file with container registry credentials,
|
||||||
// along with expected properties of that path (currently just whether it's)
|
// along with expected properties of that path (currently just whether it's
|
||||||
// legacy format or not.
|
// legacy format or not).
|
||||||
type authPath struct {
|
type authPath struct {
|
||||||
path string
|
path string
|
||||||
legacyFormat bool
|
legacyFormat bool
|
||||||
|
|
@ -92,7 +92,7 @@ func SetCredentials(sys *types.SystemContext, key, username, password string) (s
|
||||||
if isNamespaced {
|
if isNamespaced {
|
||||||
return false, "", unsupportedNamespaceErr(ch)
|
return false, "", unsupportedNamespaceErr(ch)
|
||||||
}
|
}
|
||||||
desc, err := setAuthToCredHelper(ch, key, username, password)
|
desc, err := setCredsInCredHelper(ch, key, username, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, "", err
|
return false, "", err
|
||||||
}
|
}
|
||||||
|
|
@ -108,7 +108,7 @@ func SetCredentials(sys *types.SystemContext, key, username, password string) (s
|
||||||
if isNamespaced {
|
if isNamespaced {
|
||||||
err = unsupportedNamespaceErr(helper)
|
err = unsupportedNamespaceErr(helper)
|
||||||
} else {
|
} else {
|
||||||
desc, err = setAuthToCredHelper(helper, key, username, password)
|
desc, err = setCredsInCredHelper(helper, key, username, password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -176,7 +176,7 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
|
||||||
}
|
}
|
||||||
// External helpers.
|
// External helpers.
|
||||||
default:
|
default:
|
||||||
creds, err := listAuthsFromCredHelper(helper)
|
creds, err := listCredsInCredHelper(helper)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Debugf("Error listing credentials stored in credential helper %s: %v", helper, err)
|
logrus.Debugf("Error listing credentials stored in credential helper %s: %v", helper, err)
|
||||||
if errors.Is(err, exec.ErrNotFound) {
|
if errors.Is(err, exec.ErrNotFound) {
|
||||||
|
|
@ -193,19 +193,19 @@ func GetAllCredentials(sys *types.SystemContext) (map[string]types.DockerAuthCon
|
||||||
|
|
||||||
// Now use `GetCredentials` to the specific auth configs for each
|
// Now use `GetCredentials` to the specific auth configs for each
|
||||||
// previously listed registry.
|
// previously listed registry.
|
||||||
authConfigs := make(map[string]types.DockerAuthConfig)
|
allCreds := make(map[string]types.DockerAuthConfig)
|
||||||
for _, key := range allKeys.Values() {
|
for _, key := range allKeys.Values() {
|
||||||
authConf, err := GetCredentials(sys, key)
|
creds, err := GetCredentials(sys, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Note: we rely on the logging in `GetCredentials`.
|
// Note: we rely on the logging in `GetCredentials`.
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if authConf != (types.DockerAuthConfig{}) {
|
if creds != (types.DockerAuthConfig{}) {
|
||||||
authConfigs[key] = authConf
|
allCreds[key] = creds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return authConfigs, nil
|
return allCreds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAuthFilePaths returns a slice of authPaths based on the system context
|
// getAuthFilePaths returns a slice of authPaths based on the system context
|
||||||
|
|
@ -285,13 +285,13 @@ func getCredentialsWithHomeDir(sys *types.SystemContext, key, homeDir string) (t
|
||||||
// Anonymous function to query credentials from auth files.
|
// Anonymous function to query credentials from auth files.
|
||||||
getCredentialsFromAuthFiles := func() (types.DockerAuthConfig, string, error) {
|
getCredentialsFromAuthFiles := func() (types.DockerAuthConfig, string, error) {
|
||||||
for _, path := range getAuthFilePaths(sys, homeDir) {
|
for _, path := range getAuthFilePaths(sys, homeDir) {
|
||||||
authConfig, err := findCredentialsInFile(key, registry, path)
|
creds, err := findCredentialsInFile(key, registry, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.DockerAuthConfig{}, "", err
|
return types.DockerAuthConfig{}, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if authConfig != (types.DockerAuthConfig{}) {
|
if creds != (types.DockerAuthConfig{}) {
|
||||||
return authConfig, path.path, nil
|
return creds, path.path, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return types.DockerAuthConfig{}, "", nil
|
return types.DockerAuthConfig{}, "", nil
|
||||||
|
|
@ -320,7 +320,7 @@ func getCredentialsWithHomeDir(sys *types.SystemContext, key, homeDir string) (t
|
||||||
// This intentionally uses "registry", not "key"; we don't support namespaced
|
// This intentionally uses "registry", not "key"; we don't support namespaced
|
||||||
// credentials in helpers, but a "registry" is a valid parent of "key".
|
// credentials in helpers, but a "registry" is a valid parent of "key".
|
||||||
helperKey = registry
|
helperKey = registry
|
||||||
creds, err = getAuthFromCredHelper(helper, registry)
|
creds, err = getCredsFromCredHelper(helper, registry)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Debugf("Error looking up credentials for %s in credential helper %s: %v", helperKey, helper, err)
|
logrus.Debugf("Error looking up credentials for %s in credential helper %s: %v", helperKey, helper, err)
|
||||||
|
|
@ -360,14 +360,14 @@ func GetAuthentication(sys *types.SystemContext, key string) (string, string, er
|
||||||
// getAuthenticationWithHomeDir is an internal implementation detail of GetAuthentication,
|
// getAuthenticationWithHomeDir is an internal implementation detail of GetAuthentication,
|
||||||
// it exists only to allow testing it with an artificial home directory.
|
// it exists only to allow testing it with an artificial home directory.
|
||||||
func getAuthenticationWithHomeDir(sys *types.SystemContext, key, homeDir string) (string, string, error) {
|
func getAuthenticationWithHomeDir(sys *types.SystemContext, key, homeDir string) (string, string, error) {
|
||||||
auth, err := getCredentialsWithHomeDir(sys, key, homeDir)
|
creds, err := getCredentialsWithHomeDir(sys, key, homeDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
if auth.IdentityToken != "" {
|
if creds.IdentityToken != "" {
|
||||||
return "", "", fmt.Errorf("non-empty identity token found and this API doesn't support it: %w", ErrNotSupported)
|
return "", "", fmt.Errorf("non-empty identity token found and this API doesn't support it: %w", ErrNotSupported)
|
||||||
}
|
}
|
||||||
return auth.Username, auth.Password, nil
|
return creds.Username, creds.Password, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAuthentication removes credentials for `key` from all possible
|
// RemoveAuthentication removes credentials for `key` from all possible
|
||||||
|
|
@ -393,7 +393,7 @@ func RemoveAuthentication(sys *types.SystemContext, key string) error {
|
||||||
logrus.Debugf("Not removing credentials because namespaced keys are not supported for the credential helper: %s", helper)
|
logrus.Debugf("Not removing credentials because namespaced keys are not supported for the credential helper: %s", helper)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := deleteAuthFromCredHelper(helper, key)
|
err := deleteCredsFromCredHelper(helper, key)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logrus.Debugf("Credentials for %q were deleted from credential helper %s", key, helper)
|
logrus.Debugf("Credentials for %q were deleted from credential helper %s", key, helper)
|
||||||
isLoggedIn = true
|
isLoggedIn = true
|
||||||
|
|
@ -459,7 +459,7 @@ func RemoveAllAuthentication(sys *types.SystemContext) error {
|
||||||
// Helpers in auth files are expected
|
// Helpers in auth files are expected
|
||||||
// to exist, so no special treatment
|
// to exist, so no special treatment
|
||||||
// for them.
|
// for them.
|
||||||
if err := deleteAuthFromCredHelper(helper, registry); err != nil {
|
if err := deleteCredsFromCredHelper(helper, registry); err != nil {
|
||||||
return false, "", err
|
return false, "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -470,7 +470,7 @@ func RemoveAllAuthentication(sys *types.SystemContext) error {
|
||||||
// External helpers.
|
// External helpers.
|
||||||
default:
|
default:
|
||||||
var creds map[string]string
|
var creds map[string]string
|
||||||
creds, err = listAuthsFromCredHelper(helper)
|
creds, err = listCredsInCredHelper(helper)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, exec.ErrNotFound) {
|
if errors.Is(err, exec.ErrNotFound) {
|
||||||
// It's okay if the helper doesn't exist.
|
// It's okay if the helper doesn't exist.
|
||||||
|
|
@ -480,7 +480,7 @@ func RemoveAllAuthentication(sys *types.SystemContext) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for registry := range creds {
|
for registry := range creds {
|
||||||
err = deleteAuthFromCredHelper(helper, registry)
|
err = deleteCredsFromCredHelper(helper, registry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -497,7 +497,7 @@ func RemoveAllAuthentication(sys *types.SystemContext) error {
|
||||||
return multiErr
|
return multiErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func listAuthsFromCredHelper(credHelper string) (map[string]string, error) {
|
func listCredsInCredHelper(credHelper string) (map[string]string, error) {
|
||||||
helperName := fmt.Sprintf("docker-credential-%s", credHelper)
|
helperName := fmt.Sprintf("docker-credential-%s", credHelper)
|
||||||
p := helperclient.NewShellProgramFunc(helperName)
|
p := helperclient.NewShellProgramFunc(helperName)
|
||||||
return helperclient.List(p)
|
return helperclient.List(p)
|
||||||
|
|
@ -543,7 +543,7 @@ func getPathToAuthWithOS(sys *types.SystemContext, goOS string) (authPath, bool,
|
||||||
return newAuthPathDefault(fmt.Sprintf(defaultPerUIDPathFormat, os.Getuid())), false, nil
|
return newAuthPathDefault(fmt.Sprintf(defaultPerUIDPathFormat, os.Getuid())), false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse unmarshals the authentications stored in the auth.json file and returns it
|
// parse unmarshals the credentials stored in the auth.json file and returns it
|
||||||
// or returns an empty dockerConfigFile data structure if auth.json does not exist
|
// or returns an empty dockerConfigFile data structure if auth.json does not exist
|
||||||
// if the file exists and is empty, this function returns an error.
|
// if the file exists and is empty, this function returns an error.
|
||||||
func (path authPath) parse() (dockerConfigFile, error) {
|
func (path authPath) parse() (dockerConfigFile, error) {
|
||||||
|
|
@ -625,7 +625,7 @@ func modifyJSON(sys *types.SystemContext, editor func(auths *dockerConfigFile) (
|
||||||
return description, nil
|
return description, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAuthFromCredHelper(credHelper, registry string) (types.DockerAuthConfig, error) {
|
func getCredsFromCredHelper(credHelper, registry string) (types.DockerAuthConfig, error) {
|
||||||
helperName := fmt.Sprintf("docker-credential-%s", credHelper)
|
helperName := fmt.Sprintf("docker-credential-%s", credHelper)
|
||||||
p := helperclient.NewShellProgramFunc(helperName)
|
p := helperclient.NewShellProgramFunc(helperName)
|
||||||
creds, err := helperclient.Get(p, registry)
|
creds, err := helperclient.Get(p, registry)
|
||||||
|
|
@ -650,9 +650,9 @@ func getAuthFromCredHelper(credHelper, registry string) (types.DockerAuthConfig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setAuthToCredHelper stores (username, password) for registry in credHelper.
|
// setCredsInCredHelper stores (username, password) for registry in credHelper.
|
||||||
// Returns a human-readable description of the destination, to be returned by SetCredentials.
|
// Returns a human-readable description of the destination, to be returned by SetCredentials.
|
||||||
func setAuthToCredHelper(credHelper, registry, username, password string) (string, error) {
|
func setCredsInCredHelper(credHelper, registry, username, password string) (string, error) {
|
||||||
helperName := fmt.Sprintf("docker-credential-%s", credHelper)
|
helperName := fmt.Sprintf("docker-credential-%s", credHelper)
|
||||||
p := helperclient.NewShellProgramFunc(helperName)
|
p := helperclient.NewShellProgramFunc(helperName)
|
||||||
creds := &credentials.Credentials{
|
creds := &credentials.Credentials{
|
||||||
|
|
@ -666,7 +666,7 @@ func setAuthToCredHelper(credHelper, registry, username, password string) (strin
|
||||||
return fmt.Sprintf("credential helper: %s", credHelper), nil
|
return fmt.Sprintf("credential helper: %s", credHelper), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteAuthFromCredHelper(credHelper, registry string) error {
|
func deleteCredsFromCredHelper(credHelper, registry string) error {
|
||||||
helperName := fmt.Sprintf("docker-credential-%s", credHelper)
|
helperName := fmt.Sprintf("docker-credential-%s", credHelper)
|
||||||
p := helperclient.NewShellProgramFunc(helperName)
|
p := helperclient.NewShellProgramFunc(helperName)
|
||||||
return helperclient.Erase(p, registry)
|
return helperclient.Erase(p, registry)
|
||||||
|
|
@ -685,7 +685,7 @@ func findCredentialsInFile(key, registry string, path authPath) (types.DockerAut
|
||||||
// credentials in helpers.
|
// credentials in helpers.
|
||||||
if ch, exists := auths.CredHelpers[registry]; exists {
|
if ch, exists := auths.CredHelpers[registry]; exists {
|
||||||
logrus.Debugf("Looking up in credential helper %s based on credHelpers entry in %s", ch, path.path)
|
logrus.Debugf("Looking up in credential helper %s based on credHelpers entry in %s", ch, path.path)
|
||||||
return getAuthFromCredHelper(ch, registry)
|
return getCredsFromCredHelper(ch, registry)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support sub-registry namespaces in auth.
|
// Support sub-registry namespaces in auth.
|
||||||
|
|
|
||||||
|
|
@ -585,9 +585,9 @@ type SystemContext struct {
|
||||||
// resolving to Docker Hub in the Docker-compatible REST API of Podman; it should never be used outside this
|
// resolving to Docker Hub in the Docker-compatible REST API of Podman; it should never be used outside this
|
||||||
// specific context.
|
// specific context.
|
||||||
PodmanOnlyShortNamesIgnoreRegistriesConfAndForceDockerHub bool
|
PodmanOnlyShortNamesIgnoreRegistriesConfAndForceDockerHub bool
|
||||||
// If not "", overrides the default path for the authentication file, but only new format files
|
// If not "", overrides the default path for the registry authentication file, but only new format files
|
||||||
AuthFilePath string
|
AuthFilePath string
|
||||||
// if not "", overrides the default path for the authentication file, but with the legacy format;
|
// if not "", overrides the default path for the registry authentication file, but with the legacy format;
|
||||||
// the code currently will by default look for legacy format files like .dockercfg in the $HOME dir;
|
// the code currently will by default look for legacy format files like .dockercfg in the $HOME dir;
|
||||||
// but in addition to the home dir, openshift may mount .dockercfg files (via secret mount)
|
// but in addition to the home dir, openshift may mount .dockercfg files (via secret mount)
|
||||||
// in locations other than the home dir; openshift components should then set this field in those cases;
|
// in locations other than the home dir; openshift components should then set this field in those cases;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue