Support basic auth for image registry
If you stand up a docker-distribution registry, basic auth can be
configured with tls to lock down the registry. Currently the only auth
method that is supported is the bearer tokens used by the public
registries. This change checks the www-authentication header to see if
we should try basic auth or the bearer token auth.
Change-Id: I57599ab3cd8773ae3312930145b9e84244940f41
Closes-Bug: #1893826
(cherry picked from commit 0c73e4f3eb
)
This commit is contained in:
parent
974b967531
commit
a023e2a776
|
@ -667,31 +667,48 @@ class BaseImageUploader(object):
|
|||
raise ImageUploaderException(
|
||||
'Unknown authentication method for headers: %s' % r.headers)
|
||||
|
||||
auth = None
|
||||
www_auth = r.headers['www-authenticate']
|
||||
if not www_auth.startswith('Bearer '):
|
||||
raise ImageUploaderException(
|
||||
'Unknown www-authenticate value: %s' % www_auth)
|
||||
token_param = {}
|
||||
|
||||
realm = re.search('realm="(.*?)"', www_auth).group(1)
|
||||
if 'service=' in www_auth:
|
||||
token_param['service'] = re.search(
|
||||
'service="(.*?)"', www_auth).group(1)
|
||||
token_param['scope'] = 'repository:%s:pull' % image[1:]
|
||||
if www_auth.startswith('Bearer '):
|
||||
LOG.debug('Using bearer token auth')
|
||||
realm = re.search('realm="(.*?)"', www_auth).group(1)
|
||||
if 'service=' in www_auth:
|
||||
token_param['service'] = re.search(
|
||||
'service="(.*?)"', www_auth).group(1)
|
||||
token_param['scope'] = 'repository:%s:pull' % image[1:]
|
||||
|
||||
auth = None
|
||||
if username:
|
||||
if username:
|
||||
auth = requests_auth.HTTPBasicAuth(username, password)
|
||||
LOG.debug('Token parameters: params {}'.format(token_param))
|
||||
rauth = session.get(realm, params=token_param, auth=auth,
|
||||
timeout=30)
|
||||
rauth.raise_for_status()
|
||||
auth_header = 'Bearer %s' % rauth.json()['token']
|
||||
elif www_auth.startswith('Basic '):
|
||||
LOG.debug('Using basic auth')
|
||||
if not username or not password:
|
||||
raise Exception('Authentication credentials required for '
|
||||
'basic auth: %s' % url)
|
||||
auth = requests_auth.HTTPBasicAuth(username, password)
|
||||
LOG.debug('Token parameters: params {}'.format(token_param))
|
||||
rauth = session.get(realm, params=token_param, auth=auth, timeout=30)
|
||||
rauth.raise_for_status()
|
||||
session.headers['Authorization'] = 'Bearer %s' % rauth.json()['token']
|
||||
rauth = session.get(url, params=token_param, auth=auth, timeout=30)
|
||||
rauth.raise_for_status()
|
||||
auth_header = (
|
||||
'Basic %s' % base64.b64encode(
|
||||
six.b(username + ':' + password)).decode('ascii')
|
||||
)
|
||||
else:
|
||||
raise ImageUploaderException(
|
||||
'Unknown www-authenticate value: %s' % www_auth)
|
||||
hash_request_id = hashlib.sha1(str(rauth.url).encode())
|
||||
LOG.debug(
|
||||
'Session authenticated: id {}'.format(
|
||||
hash_request_id.hexdigest()
|
||||
)
|
||||
)
|
||||
session.headers['Authorization'] = auth_header
|
||||
|
||||
setattr(session, 'reauthenticate', self.authenticate)
|
||||
setattr(
|
||||
session,
|
||||
|
|
|
@ -800,6 +800,31 @@ class TestBaseImageUploader(base.TestCase):
|
|||
auth(url1).headers['Authorization']
|
||||
)
|
||||
|
||||
def test_authenticate_basic_auth(self):
|
||||
req = self.requests
|
||||
auth = self.uploader.authenticate
|
||||
url1 = urlparse('docker://myrepo.com/t/nova-api:latest')
|
||||
|
||||
# successful auth requests
|
||||
headers = {
|
||||
'www-authenticate': 'Basic realm="Some Realm"'
|
||||
}
|
||||
|
||||
def req_match(request):
|
||||
resp = requests.Response()
|
||||
resp.headers = headers
|
||||
resp.status_code = 401
|
||||
# if we got sent an user/password, return 200
|
||||
if 'Authorization' in request.headers:
|
||||
resp.status_code = 200
|
||||
return resp
|
||||
|
||||
req.add_matcher(req_match)
|
||||
self.assertEqual(
|
||||
'Basic Zm9vOmJhcg==',
|
||||
auth(url1, username='foo', password='bar').headers['Authorization']
|
||||
)
|
||||
|
||||
def test_authenticate_with_no_service(self):
|
||||
req = self.requests
|
||||
auth = self.uploader.authenticate
|
||||
|
|
Loading…
Reference in New Issue