Skip to content

Commit fab4a06

Browse files
authored
Merge pull request #1181 from docker/credstore-support
Add credentials store support
2 parents 545c5ac + 219a869 commit fab4a06

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

docker/auth/auth.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import logging
44
import os
55

6+
import dockerpycreds
67
import six
78

89
from .. import errors
@@ -11,6 +12,7 @@
1112
INDEX_URL = 'https://{0}/v1/'.format(INDEX_NAME)
1213
DOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json')
1314
LEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg'
15+
TOKEN_USERNAME = '<token>'
1416

1517
log = logging.getLogger(__name__)
1618

@@ -74,6 +76,13 @@ def resolve_authconfig(authconfig, registry=None):
7476
with full URLs are stripped down to hostnames before checking for a match.
7577
Returns None if no match was found.
7678
"""
79+
if 'credsStore' in authconfig:
80+
log.debug(
81+
'Using credentials store "{0}"'.format(authconfig['credsStore'])
82+
)
83+
return _resolve_authconfig_credstore(
84+
authconfig, registry, authconfig['credsStore']
85+
)
7786
# Default to the public index server
7887
registry = resolve_index_name(registry) if registry else INDEX_NAME
7988
log.debug("Looking for auth entry for {0}".format(repr(registry)))
@@ -91,6 +100,35 @@ def resolve_authconfig(authconfig, registry=None):
91100
return None
92101

93102

103+
def _resolve_authconfig_credstore(authconfig, registry, credstore_name):
104+
if not registry or registry == INDEX_NAME:
105+
# The ecosystem is a little schizophrenic with index.docker.io VS
106+
# docker.io - in that case, it seems the full URL is necessary.
107+
registry = 'https://index.docker.io/v1/'
108+
log.debug("Looking for auth entry for {0}".format(repr(registry)))
109+
store = dockerpycreds.Store(credstore_name)
110+
try:
111+
data = store.get(registry)
112+
res = {
113+
'ServerAddress': registry,
114+
}
115+
if data['Username'] == TOKEN_USERNAME:
116+
res['IdentityToken'] = data['Secret']
117+
else:
118+
res.update({
119+
'Username': data['Username'],
120+
'Password': data['Secret'],
121+
})
122+
return res
123+
except dockerpycreds.CredentialsNotFound as e:
124+
log.debug('No entry found')
125+
return None
126+
except dockerpycreds.StoreError as e:
127+
raise errors.DockerException(
128+
'Credentials store error: {0}'.format(repr(e))
129+
)
130+
131+
94132
def convert_to_hostname(url):
95133
return url.replace('http://', '').replace('https://', '').split('/', 1)[0]
96134

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ requests==2.5.3
22
six>=1.4.0
33
websocket-client==0.32.0
44
backports.ssl_match_hostname>=3.5 ; python_version < '3.5'
5-
ipaddress==1.0.16 ; python_version < '3.3'
5+
ipaddress==1.0.16 ; python_version < '3.3'
6+
docker-pycreds==0.2.0

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
'requests >= 2.5.2, < 2.11',
1313
'six >= 1.4.0',
1414
'websocket-client >= 0.32.0',
15+
'docker-pycreds >= 0.2.0'
1516
]
1617

1718
if sys.platform == 'win32':

0 commit comments

Comments
 (0)