v2: send proper scopes for authorization failures

Fixes #1278.
This commit is contained in:
Jimmy Zelinskie 2016-03-09 18:09:20 -05:00
parent bb46cc933d
commit ea2e17cc11
9 changed files with 91 additions and 71 deletions

View file

@ -157,13 +157,18 @@ def build_context_and_subject(user, token, oauthtoken):
return (context, ANONYMOUS_SUB)
def get_auth_headers():
def get_auth_headers(repository=None, scopes=None):
""" Returns a dictionary of headers for auth responses. """
headers = {}
realm_auth_path = url_for('v2.generate_registry_jwt')
authenticate = 'Bearer realm="{0}{1}",service="{2}"'.format(get_app_url(),
realm_auth_path,
app.config['SERVER_HOSTNAME'])
if repository:
authenticate += ',scope=repository:{0}'.format(repository)
if scopes:
authenticate += ':' + ','.join(scopes)
headers['WWW-Authenticate'] = authenticate
headers['Docker-Distribution-API-Version'] = 'registry/2.0'
return headers
@ -237,27 +242,34 @@ def load_public_key(certificate_file_path):
return cert_obj.public_key()
def process_registry_jwt_auth(func):
@wraps(func)
def wrapper(*args, **kwargs):
logger.debug('Called with params: %s, %s', args, kwargs)
auth = request.headers.get('authorization', '').strip()
if auth:
max_signature_seconds = app.config.get('JWT_AUTH_MAX_FRESH_S', 3660)
certificate_file_path = app.config['JWT_AUTH_CERTIFICATE_PATH']
public_key = load_public_key(certificate_file_path)
def process_registry_jwt_auth(scopes=None):
def inner(func):
@wraps(func)
def wrapper(*args, **kwargs):
logger.debug('Called with params: %s, %s', args, kwargs)
auth = request.headers.get('authorization', '').strip()
if auth:
max_signature_seconds = app.config.get('JWT_AUTH_MAX_FRESH_S', 3660)
certificate_file_path = app.config['JWT_AUTH_CERTIFICATE_PATH']
public_key = load_public_key(certificate_file_path)
try:
extracted_identity, context = identity_from_bearer_token(auth, max_signature_seconds,
public_key)
try:
extracted_identity, context = identity_from_bearer_token(auth, max_signature_seconds,
public_key)
identity_changed.send(app, identity=extracted_identity)
set_grant_context(context)
logger.debug('Identity changed to %s', extracted_identity.id)
except InvalidJWTException as ije:
abort(401, message=ije.message, headers=get_auth_headers())
else:
logger.debug('No auth header.')
identity_changed.send(app, identity=extracted_identity)
set_grant_context(context)
logger.debug('Identity changed to %s', extracted_identity.id)
except InvalidJWTException as ije:
repository = None
if 'namespace_name' in kwargs and 'repo_name' in kwargs:
repository = kwargs['namespace_name'] + '/' + kwargs['repo_name']
return func(*args, **kwargs)
return wrapper
abort(401, message=ije.message, headers=get_auth_headers(repository=repository,
scopes=scopes))
else:
logger.debug('No auth header.')
return func(*args, **kwargs)
return wrapper
return inner