Kaydet (Commit) bc5d7c8c authored tarafından Joffrey F's avatar Joffrey F

Modernize auth management

Signed-off-by: 's avatarJoffrey F <joffrey@docker.com>
üst 9a67e203
......@@ -293,31 +293,11 @@ class BuildApiMixin(object):
# Send the full auth configuration (if any exists), since the build
# could use any (or all) of the registries.
if self._auth_configs:
auth_cfgs = self._auth_configs
auth_data = {}
if auth_cfgs.get('credsStore'):
# Using a credentials store, we need to retrieve the
# credentials for each registry listed in the config.json file
# Matches CLI behavior: https://github.com/docker/docker/blob/
# 67b85f9d26f1b0b2b240f2d794748fac0f45243c/cliconfig/
# credentials/native_store.go#L68-L83
for registry in auth_cfgs.get('auths', {}).keys():
auth_data[registry] = auth.resolve_authconfig(
auth_cfgs, registry,
credstore_env=self.credstore_env,
)
else:
for registry in auth_cfgs.get('credHelpers', {}).keys():
auth_data[registry] = auth.resolve_authconfig(
auth_cfgs, registry,
credstore_env=self.credstore_env
)
for registry, creds in auth_cfgs.get('auths', {}).items():
if registry not in auth_data:
auth_data[registry] = creds
# See https://github.com/docker/docker-py/issues/1683
if auth.INDEX_NAME in auth_data:
auth_data[auth.INDEX_URL] = auth_data[auth.INDEX_NAME]
auth_data = self._auth_configs.get_all_credentials()
# See https://github.com/docker/docker-py/issues/1683
if auth.INDEX_URL not in auth_data and auth.INDEX_URL in auth_data:
auth_data[auth.INDEX_URL] = auth_data.get(auth.INDEX_NAME, {})
log.debug(
'Sending auth config ({0})'.format(
......@@ -325,9 +305,10 @@ class BuildApiMixin(object):
)
)
headers['X-Registry-Config'] = auth.encode_header(
auth_data
)
if auth_data:
headers['X-Registry-Config'] = auth.encode_header(
auth_data
)
else:
log.debug('No auth config found')
......
......@@ -124,13 +124,15 @@ class DaemonApiMixin(object):
# If dockercfg_path is passed check to see if the config file exists,
# if so load that config.
if dockercfg_path and os.path.exists(dockercfg_path):
self._auth_configs = auth.load_config(dockercfg_path)
self._auth_configs = auth.load_config(
dockercfg_path, credstore_env=self.credstore_env
)
elif not self._auth_configs:
self._auth_configs = auth.load_config()
self._auth_configs = auth.load_config(
credstore_env=self.credstore_env
)
authcfg = auth.resolve_authconfig(
self._auth_configs, registry, credstore_env=self.credstore_env,
)
authcfg = self._auth_configs.resolve_authconfig(registry)
# If we found an existing auth config for this registry and username
# combination, we can return it immediately unless reauth is requested.
if authcfg and authcfg.get('username', None) == username \
......@@ -146,9 +148,7 @@ class DaemonApiMixin(object):
response = self._post_json(self._url('/auth'), data=req_data)
if response.status_code == 200:
if 'auths' not in self._auth_configs:
self._auth_configs['auths'] = {}
self._auth_configs['auths'][registry or auth.INDEX_NAME] = req_data
self._auth_configs.add_auth(registry or auth.INDEX_NAME, req_data)
return self._result(response, json=True)
def ping(self):
......
This diff is collapsed.
......@@ -4,7 +4,7 @@ backports.ssl-match-hostname==3.5.0.1
cffi==1.10.0
cryptography==1.9; python_version == '3.3'
cryptography==2.3; python_version > '3.3'
docker-pycreds==0.3.0
docker-pycreds==0.4.0
enum34==1.1.6
idna==2.5
ipaddress==1.0.18
......
......@@ -12,7 +12,7 @@ SOURCE_DIR = os.path.join(ROOT_DIR)
requirements = [
'six >= 1.4.0',
'websocket-client >= 0.32.0',
'docker-pycreds >= 0.3.0',
'docker-pycreds >= 0.4.0',
'requests >= 2.14.2, != 2.18.0',
]
......
......@@ -65,7 +65,7 @@ class BuildTest(BaseAPIClientTest):
)
def test_build_remote_with_registry_auth(self):
self.client._auth_configs = {
self.client._auth_configs = auth.AuthConfig({
'auths': {
'https://example.com': {
'user': 'example',
......@@ -73,7 +73,7 @@ class BuildTest(BaseAPIClientTest):
'email': 'example@example.com'
}
}
}
})
expected_params = {'t': None, 'q': False, 'dockerfile': None,
'rm': False, 'nocache': False, 'pull': False,
......@@ -81,7 +81,7 @@ class BuildTest(BaseAPIClientTest):
'remote': 'https://github.com/docker-library/mongo'}
expected_headers = {
'X-Registry-Config': auth.encode_header(
self.client._auth_configs['auths']
self.client._auth_configs.auths
)
}
......@@ -115,7 +115,7 @@ class BuildTest(BaseAPIClientTest):
})
def test_set_auth_headers_with_empty_dict_and_auth_configs(self):
self.client._auth_configs = {
self.client._auth_configs = auth.AuthConfig({
'auths': {
'https://example.com': {
'user': 'example',
......@@ -123,12 +123,12 @@ class BuildTest(BaseAPIClientTest):
'email': 'example@example.com'
}
}
}
})
headers = {}
expected_headers = {
'X-Registry-Config': auth.encode_header(
self.client._auth_configs['auths']
self.client._auth_configs.auths
)
}
......@@ -136,7 +136,7 @@ class BuildTest(BaseAPIClientTest):
assert headers == expected_headers
def test_set_auth_headers_with_dict_and_auth_configs(self):
self.client._auth_configs = {
self.client._auth_configs = auth.AuthConfig({
'auths': {
'https://example.com': {
'user': 'example',
......@@ -144,12 +144,12 @@ class BuildTest(BaseAPIClientTest):
'email': 'example@example.com'
}
}
}
})
headers = {'foo': 'bar'}
expected_headers = {
'X-Registry-Config': auth.encode_header(
self.client._auth_configs['auths']
self.client._auth_configs.auths
),
'foo': 'bar'
}
......
......@@ -221,13 +221,11 @@ class DockerApiTest(BaseAPIClientTest):
'username': 'sakuya', 'password': 'izayoi'
}
assert args[1]['headers'] == {'Content-Type': 'application/json'}
assert self.client._auth_configs['auths'] == {
'docker.io': {
'email': None,
'password': 'izayoi',
'username': 'sakuya',
'serveraddress': None,
}
assert self.client._auth_configs.auths['docker.io'] == {
'email': None,
'password': 'izayoi',
'username': 'sakuya',
'serveraddress': None,
}
def test_events(self):
......
......@@ -106,13 +106,13 @@ class ResolveAuthTest(unittest.TestCase):
private_config = {'auth': encode_auth({'username': 'privateuser'})}
legacy_config = {'auth': encode_auth({'username': 'legacyauth'})}
auth_config = {
auth_config = auth.AuthConfig({
'auths': auth.parse_auth({
'https://index.docker.io/v1/': index_config,
'my.registry.net': private_config,
'http://legacy.registry.url/v1/': legacy_config,
})
}
})
def test_resolve_authconfig_hostname_only(self):
assert auth.resolve_authconfig(
......@@ -211,13 +211,15 @@ class ResolveAuthTest(unittest.TestCase):
) is None
def test_resolve_auth_with_empty_credstore_and_auth_dict(self):
auth_config = {
auth_config = auth.AuthConfig({
'auths': auth.parse_auth({
'https://index.docker.io/v1/': self.index_config,
}),
'credsStore': 'blackbox'
}
with mock.patch('docker.auth._resolve_authconfig_credstore') as m:
})
with mock.patch(
'docker.auth.AuthConfig._resolve_authconfig_credstore'
) as m:
m.return_value = None
assert 'indexuser' == auth.resolve_authconfig(
auth_config, None
......@@ -226,13 +228,13 @@ class ResolveAuthTest(unittest.TestCase):
class CredStoreTest(unittest.TestCase):
def test_get_credential_store(self):
auth_config = {
auth_config = auth.AuthConfig({
'credHelpers': {
'registry1.io': 'truesecret',
'registry2.io': 'powerlock'
},
'credsStore': 'blackbox',
}
})
assert auth.get_credential_store(
auth_config, 'registry1.io'
......@@ -245,12 +247,12 @@ class CredStoreTest(unittest.TestCase):
) == 'blackbox'
def test_get_credential_store_no_default(self):
auth_config = {
auth_config = auth.AuthConfig({
'credHelpers': {
'registry1.io': 'truesecret',
'registry2.io': 'powerlock'
},
}
})
assert auth.get_credential_store(
auth_config, 'registry2.io'
) == 'powerlock'
......@@ -259,12 +261,12 @@ class CredStoreTest(unittest.TestCase):
) is None
def test_get_credential_store_default_index(self):
auth_config = {
auth_config = auth.AuthConfig({
'credHelpers': {
'https://index.docker.io/v1/': 'powerlock'
},
'credsStore': 'truesecret'
}
})
assert auth.get_credential_store(auth_config, None) == 'powerlock'
assert auth.get_credential_store(
......@@ -293,8 +295,8 @@ class LoadConfigTest(unittest.TestCase):
cfg = auth.load_config(cfg_path)
assert auth.resolve_authconfig(cfg) is not None
assert cfg['auths'][auth.INDEX_NAME] is not None
cfg = cfg['auths'][auth.INDEX_NAME]
assert cfg.auths[auth.INDEX_NAME] is not None
cfg = cfg.auths[auth.INDEX_NAME]
assert cfg['username'] == 'sakuya'
assert cfg['password'] == 'izayoi'
assert cfg['email'] == 'sakuya@scarlet.net'
......@@ -312,8 +314,8 @@ class LoadConfigTest(unittest.TestCase):
)
cfg = auth.load_config(cfg_path)
assert auth.resolve_authconfig(cfg) is not None
assert cfg['auths'][auth.INDEX_URL] is not None
cfg = cfg['auths'][auth.INDEX_URL]
assert cfg.auths[auth.INDEX_URL] is not None
cfg = cfg.auths[auth.INDEX_URL]
assert cfg['username'] == 'sakuya'
assert cfg['password'] == 'izayoi'
assert cfg['email'] == email
......@@ -335,8 +337,8 @@ class LoadConfigTest(unittest.TestCase):
}, f)
cfg = auth.load_config(cfg_path)
assert auth.resolve_authconfig(cfg) is not None
assert cfg['auths'][auth.INDEX_URL] is not None
cfg = cfg['auths'][auth.INDEX_URL]
assert cfg.auths[auth.INDEX_URL] is not None
cfg = cfg.auths[auth.INDEX_URL]
assert cfg['username'] == 'sakuya'
assert cfg['password'] == 'izayoi'
assert cfg['email'] == email
......@@ -360,7 +362,7 @@ class LoadConfigTest(unittest.TestCase):
with open(dockercfg_path, 'w') as f:
json.dump(config, f)
cfg = auth.load_config(dockercfg_path)['auths']
cfg = auth.load_config(dockercfg_path).auths
assert registry in cfg
assert cfg[registry] is not None
cfg = cfg[registry]
......@@ -387,7 +389,7 @@ class LoadConfigTest(unittest.TestCase):
json.dump(config, f)
with mock.patch.dict(os.environ, {'DOCKER_CONFIG': folder}):
cfg = auth.load_config(None)['auths']
cfg = auth.load_config(None).auths
assert registry in cfg
assert cfg[registry] is not None
cfg = cfg[registry]
......@@ -417,8 +419,8 @@ class LoadConfigTest(unittest.TestCase):
with mock.patch.dict(os.environ, {'DOCKER_CONFIG': folder}):
cfg = auth.load_config(None)
assert registry in cfg['auths']
cfg = cfg['auths'][registry]
assert registry in cfg.auths
cfg = cfg.auths[registry]
assert cfg['username'] == 'sakuya'
assert cfg['password'] == 'izayoi'
assert cfg['email'] == 'sakuya@scarlet.net'
......@@ -446,8 +448,8 @@ class LoadConfigTest(unittest.TestCase):
with mock.patch.dict(os.environ, {'DOCKER_CONFIG': folder}):
cfg = auth.load_config(None)
assert registry in cfg['auths']
cfg = cfg['auths'][registry]
assert registry in cfg.auths
cfg = cfg.auths[registry]
assert cfg['username'] == b'sakuya\xc3\xa6'.decode('utf8')
assert cfg['password'] == b'izayoi\xc3\xa6'.decode('utf8')
assert cfg['email'] == 'sakuya@scarlet.net'
......@@ -464,7 +466,7 @@ class LoadConfigTest(unittest.TestCase):
json.dump(config, f)
cfg = auth.load_config(dockercfg_path)
assert cfg == {'auths': {}}
assert cfg._dct == {'auths': {}}
def test_load_config_invalid_auth_dict(self):
folder = tempfile.mkdtemp()
......@@ -479,7 +481,7 @@ class LoadConfigTest(unittest.TestCase):
json.dump(config, f)
cfg = auth.load_config(dockercfg_path)
assert cfg == {'auths': {'scarlet.net': {}}}
assert cfg._dct == {'auths': {'scarlet.net': {}}}
def test_load_config_identity_token(self):
folder = tempfile.mkdtemp()
......@@ -500,7 +502,7 @@ class LoadConfigTest(unittest.TestCase):
json.dump(config, f)
cfg = auth.load_config(dockercfg_path)
assert registry in cfg['auths']
cfg = cfg['auths'][registry]
assert registry in cfg.auths
cfg = cfg.auths[registry]
assert 'IdentityToken' in cfg
assert cfg['IdentityToken'] == token
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment