Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions docker/auth/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

from .. import errors

INDEX_NAME = 'index.docker.io'
INDEX_NAME = 'docker.io'
INDEX_URL = 'https://{0}/v1/'.format(INDEX_NAME)
DOCKER_CONFIG_FILENAME = os.path.join('.docker', 'config.json')
LEGACY_DOCKER_CONFIG_FILENAME = '.dockercfg'
Expand All @@ -41,7 +41,14 @@ def resolve_repository_name(repo_name):
'Invalid index name ({0}). Cannot begin or end with a'
' hyphen.'.format(index_name)
)
return index_name, remote_name
return resolve_index_name(index_name), remote_name


def resolve_index_name(index_name):
index_name = convert_to_hostname(index_name)
if index_name == 'index.'+INDEX_NAME:
index_name = INDEX_NAME
return index_name


def split_repo_name(repo_name):
Expand All @@ -62,15 +69,15 @@ def resolve_authconfig(authconfig, registry=None):
Returns None if no match was found.
"""
# Default to the public index server
registry = convert_to_hostname(registry) if registry else INDEX_NAME
registry = resolve_index_name(registry) if registry else INDEX_NAME
log.debug("Looking for auth entry for {0}".format(repr(registry)))

if registry in authconfig:
log.debug("Found {0}".format(repr(registry)))
return authconfig[registry]

for key, config in six.iteritems(authconfig):
if convert_to_hostname(key) == registry:
if resolve_index_name(key) == registry:
log.debug("Found {0}".format(repr(key)))
return config

Expand All @@ -82,11 +89,6 @@ def convert_to_hostname(url):
return url.replace('http://', '').replace('https://', '').split('/', 1)[0]


def encode_auth(auth_info):
return base64.b64encode(auth_info.get('username', '') + b':' +
auth_info.get('password', ''))


def decode_auth(auth):
if isinstance(auth, six.string_types):
auth = auth.encode('ascii')
Expand Down Expand Up @@ -121,7 +123,7 @@ def parse_auth(entries):
conf[registry] = {
'username': username,
'password': password,
'email': entry['email'],
'email': entry.get('email'),
'serveraddress': registry,
}
return conf
Expand Down
114 changes: 78 additions & 36 deletions tests/unit/auth_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import tempfile

from docker import auth
from docker.auth.auth import parse_auth
from docker import errors

from .. import base
Expand All @@ -34,25 +35,31 @@ class ResolveRepositoryNameTest(base.BaseTestCase):
def test_resolve_repository_name_hub_library_image(self):
self.assertEqual(
auth.resolve_repository_name('image'),
('index.docker.io', 'image'),
('docker.io', 'image'),
)

def test_resolve_repository_name_dotted_hub_library_image(self):
self.assertEqual(
auth.resolve_repository_name('image.valid'),
('index.docker.io', 'image.valid')
('docker.io', 'image.valid')
)

def test_resolve_repository_name_hub_image(self):
self.assertEqual(
auth.resolve_repository_name('username/image'),
('index.docker.io', 'username/image'),
('docker.io', 'username/image'),
)

def test_explicit_hub_index_library_image(self):
self.assertEqual(
auth.resolve_repository_name('docker.io/image'),
('docker.io', 'image')
)

def test_explicit_legacy_hub_index_library_image(self):
self.assertEqual(
auth.resolve_repository_name('index.docker.io/image'),
('index.docker.io', 'image')
('docker.io', 'image')
)

def test_resolve_repository_name_private_registry(self):
Expand Down Expand Up @@ -104,88 +111,105 @@ def test_invalid_index_name(self):
)


def encode_auth(auth_info):
return base64.b64encode(
auth_info.get('username', '').encode('utf-8') + b':' +
auth_info.get('password', '').encode('utf-8'))


class ResolveAuthTest(base.BaseTestCase):
auth_config = {
'https://index.docker.io/v1/': {'auth': 'indexuser'},
'my.registry.net': {'auth': 'privateuser'},
'http://legacy.registry.url/v1/': {'auth': 'legacyauth'}
}
index_config = {'auth': encode_auth({'username': 'indexuser'})}
private_config = {'auth': encode_auth({'username': 'privateuser'})}
legacy_config = {'auth': encode_auth({'username': 'legacyauth'})}

auth_config = 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):
self.assertEqual(
auth.resolve_authconfig(self.auth_config, 'my.registry.net'),
{'auth': 'privateuser'}
auth.resolve_authconfig(
self.auth_config, 'my.registry.net'
)['username'],
'privateuser'
)

def test_resolve_authconfig_no_protocol(self):
self.assertEqual(
auth.resolve_authconfig(self.auth_config, 'my.registry.net/v1/'),
{'auth': 'privateuser'}
auth.resolve_authconfig(
self.auth_config, 'my.registry.net/v1/'
)['username'],
'privateuser'
)

def test_resolve_authconfig_no_path(self):
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, 'http://my.registry.net'
),
{'auth': 'privateuser'}
)['username'],
'privateuser'
)

def test_resolve_authconfig_no_path_trailing_slash(self):
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, 'http://my.registry.net/'
),
{'auth': 'privateuser'}
)['username'],
'privateuser'
)

def test_resolve_authconfig_no_path_wrong_secure_proto(self):
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, 'https://my.registry.net'
),
{'auth': 'privateuser'}
)['username'],
'privateuser'
)

def test_resolve_authconfig_no_path_wrong_insecure_proto(self):
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, 'http://index.docker.io'
),
{'auth': 'indexuser'}
)['username'],
'indexuser'
)

def test_resolve_authconfig_path_wrong_proto(self):
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, 'https://my.registry.net/v1/'
),
{'auth': 'privateuser'}
)['username'],
'privateuser'
)

def test_resolve_authconfig_default_registry(self):
self.assertEqual(
auth.resolve_authconfig(self.auth_config), {'auth': 'indexuser'}
auth.resolve_authconfig(self.auth_config)['username'],
'indexuser'
)

def test_resolve_authconfig_default_explicit_none(self):
self.assertEqual(
auth.resolve_authconfig(self.auth_config, None),
{'auth': 'indexuser'}
auth.resolve_authconfig(self.auth_config, None)['username'],
'indexuser'
)

def test_resolve_authconfig_fully_explicit(self):
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, 'http://my.registry.net/v1/'
),
{'auth': 'privateuser'}
)['username'],
'privateuser'
)

def test_resolve_authconfig_legacy_config(self):
self.assertEqual(
auth.resolve_authconfig(self.auth_config, 'legacy.registry.url'),
{'auth': 'legacyauth'}
auth.resolve_authconfig(
self.auth_config, 'legacy.registry.url'
)['username'],
'legacyauth'
)

def test_resolve_authconfig_no_match(self):
Expand All @@ -198,26 +222,44 @@ def test_resolve_registry_and_auth_library_image(self):
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, auth.resolve_repository_name(image)[0]
),
{'auth': 'indexuser'},
)['username'],
'indexuser',
)

def test_resolve_registry_and_auth_hub_image(self):
image = 'username/image'
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, auth.resolve_repository_name(image)[0]
),
{'auth': 'indexuser'},
)['username'],
'indexuser',
)

def test_resolve_registry_and_auth_explicit_hub(self):
image = 'docker.io/username/image'
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, auth.resolve_repository_name(image)[0]
)['username'],
'indexuser',
)

def test_resolve_registry_and_auth_explicit_legacy_hub(self):
image = 'index.docker.io/username/image'
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, auth.resolve_repository_name(image)[0]
)['username'],
'indexuser',
)

def test_resolve_registry_and_auth_private_registry(self):
image = 'my.registry.net/image'
self.assertEqual(
auth.resolve_authconfig(
self.auth_config, auth.resolve_repository_name(image)[0]
),
{'auth': 'privateuser'},
)['username'],
'privateuser',
)

def test_resolve_registry_and_auth_unauthenticated_registry(self):
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ skipsdist=True
[testenv]
usedevelop=True
commands =
py.test --cov=docker tests/unit/
py.test --cov=docker {posargs:tests/unit}
deps =
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
Expand Down