diff --git a/docker/auth/auth.py b/docker/auth/auth.py index 50f86f63c8..ea15def80a 100644 --- a/docker/auth/auth.py +++ b/docker/auth/auth.py @@ -3,6 +3,7 @@ import logging import os +import dockerpycreds import six from .. import errors @@ -11,6 +12,7 @@ INDEX_URL = 'https://{0}/v1/'.format(INDEX_NAME) DOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json') LEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg' +TOKEN_USERNAME = '' log = logging.getLogger(__name__) @@ -74,6 +76,13 @@ def resolve_authconfig(authconfig, registry=None): with full URLs are stripped down to hostnames before checking for a match. Returns None if no match was found. """ + if 'credsStore' in authconfig: + log.debug( + 'Using credentials store "{0}"'.format(authconfig['credsStore']) + ) + return _resolve_authconfig_credstore( + authconfig, registry, authconfig['credsStore'] + ) # Default to the public index server registry = resolve_index_name(registry) if registry else INDEX_NAME log.debug("Looking for auth entry for {0}".format(repr(registry))) @@ -91,6 +100,35 @@ def resolve_authconfig(authconfig, registry=None): return None +def _resolve_authconfig_credstore(authconfig, registry, credstore_name): + if not registry or registry == INDEX_NAME: + # The ecosystem is a little schizophrenic with index.docker.io VS + # docker.io - in that case, it seems the full URL is necessary. + registry = 'https://index.docker.io/v1/' + log.debug("Looking for auth entry for {0}".format(repr(registry))) + store = dockerpycreds.Store(credstore_name) + try: + data = store.get(registry) + res = { + 'ServerAddress': registry, + } + if data['Username'] == TOKEN_USERNAME: + res['IdentityToken'] = data['Secret'] + else: + res.update({ + 'Username': data['Username'], + 'Password': data['Secret'], + }) + return res + except dockerpycreds.CredentialsNotFound as e: + log.debug('No entry found') + return None + except dockerpycreds.StoreError as e: + raise errors.DockerException( + 'Credentials store error: {0}'.format(repr(e)) + ) + + def convert_to_hostname(url): return url.replace('http://', '').replace('https://', '').split('/', 1)[0] diff --git a/requirements.txt b/requirements.txt index a79b7bf8a6..4c0d5c203a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ requests==2.5.3 six>=1.4.0 websocket-client==0.32.0 backports.ssl_match_hostname>=3.5 ; python_version < '3.5' -ipaddress==1.0.16 ; python_version < '3.3' \ No newline at end of file +ipaddress==1.0.16 ; python_version < '3.3' +docker-pycreds==0.2.0 \ No newline at end of file diff --git a/setup.py b/setup.py index c809321e7d..1afd873b50 100644 --- a/setup.py +++ b/setup.py @@ -12,6 +12,7 @@ 'requests >= 2.5.2, < 2.11', 'six >= 1.4.0', 'websocket-client >= 0.32.0', + 'docker-pycreds >= 0.2.0' ] if sys.platform == 'win32':