Merge pull request #2499 from coreos-inc/docker-400
Better error messages for Docker errors
This commit is contained in:
commit
3f0f8159b7
2 changed files with 25 additions and 14 deletions
|
@ -80,9 +80,9 @@ class ManifestUnverified(V2RegistryException):
|
||||||
|
|
||||||
|
|
||||||
class NameInvalid(V2RegistryException):
|
class NameInvalid(V2RegistryException):
|
||||||
def __init__(self, detail=None):
|
def __init__(self, detail=None, message=None):
|
||||||
super(NameInvalid, self).__init__('NAME_INVALID',
|
super(NameInvalid, self).__init__('NAME_INVALID',
|
||||||
'invalid repository name',
|
message or 'invalid repository name',
|
||||||
detail)
|
detail)
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,9 +141,9 @@ class Unauthorized(V2RegistryException):
|
||||||
|
|
||||||
|
|
||||||
class Unsupported(V2RegistryException):
|
class Unsupported(V2RegistryException):
|
||||||
def __init__(self, detail=None):
|
def __init__(self, detail=None, message=None):
|
||||||
super(Unsupported, self).__init__('UNSUPPORTED',
|
super(Unsupported, self).__init__('UNSUPPORTED',
|
||||||
'The operation is unsupported.',
|
message or 'The operation is unsupported.',
|
||||||
detail,
|
detail,
|
||||||
405)
|
405)
|
||||||
|
|
||||||
|
@ -155,3 +155,11 @@ class InvalidLogin(V2RegistryException):
|
||||||
{},
|
{},
|
||||||
401)
|
401)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidRequest(V2RegistryException):
|
||||||
|
def __init__(self, message=None):
|
||||||
|
super(InvalidRequest, self).__init__('INVALID_REQUEST',
|
||||||
|
message or 'Invalid request',
|
||||||
|
{},
|
||||||
|
400)
|
|
@ -11,7 +11,7 @@ from auth.permissions import (ModifyRepositoryPermission, ReadRepositoryPermissi
|
||||||
CreateRepositoryPermission, AdministerRepositoryPermission)
|
CreateRepositoryPermission, AdministerRepositoryPermission)
|
||||||
from endpoints.decorators import anon_protect
|
from endpoints.decorators import anon_protect
|
||||||
from endpoints.v2 import v2_bp
|
from endpoints.v2 import v2_bp
|
||||||
from endpoints.v2.errors import InvalidLogin
|
from endpoints.v2.errors import InvalidLogin, NameInvalid, InvalidRequest, Unsupported, Unauthorized
|
||||||
from data.interfaces.v2 import pre_oci_model as model
|
from data.interfaces.v2 import pre_oci_model as model
|
||||||
from util.cache import no_cache
|
from util.cache import no_cache
|
||||||
from util.names import parse_namespace_repository, REPOSITORY_NAME_REGEX
|
from util.names import parse_namespace_repository, REPOSITORY_NAME_REGEX
|
||||||
|
@ -21,8 +21,7 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
TOKEN_VALIDITY_LIFETIME_S = 60 * 60 # 1 hour
|
TOKEN_VALIDITY_LIFETIME_S = 60 * 60 # 1 hour
|
||||||
SCOPE_REGEX_TEMPLATE = r'^repository:((?:{}\/)?((?:[\.a-zA-Z0-9_\-]+\/)?[\.a-zA-Z0-9_\-]+)):((?:push|pull|\*)(?:,(?:push|pull|\*))*)$'
|
SCOPE_REGEX_TEMPLATE = r'^repository:((?:{}\/)?((?:[\.a-zA-Z0-9_\-]+\/)*[\.a-zA-Z0-9_\-]+)):((?:push|pull|\*)(?:,(?:push|pull|\*))*)$'
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=1)
|
@lru_cache(maxsize=1)
|
||||||
def get_scope_regex():
|
def get_scope_regex():
|
||||||
|
@ -73,7 +72,7 @@ def generate_registry_jwt(auth_result):
|
||||||
logger.debug('Match: %s', match)
|
logger.debug('Match: %s', match)
|
||||||
logger.debug('len: %s', len(scope_param))
|
logger.debug('len: %s', len(scope_param))
|
||||||
logger.warning('Unable to decode repository and actions: %s', scope_param)
|
logger.warning('Unable to decode repository and actions: %s', scope_param)
|
||||||
abort(400)
|
raise InvalidRequest('Unable to decode repository and actions: %s' % scope_param)
|
||||||
|
|
||||||
logger.debug('Match: %s', match.groups())
|
logger.debug('Match: %s', match.groups())
|
||||||
|
|
||||||
|
@ -87,7 +86,11 @@ def generate_registry_jwt(auth_result):
|
||||||
# Ensure that we are never creating an invalid repository.
|
# Ensure that we are never creating an invalid repository.
|
||||||
if not REPOSITORY_NAME_REGEX.match(reponame):
|
if not REPOSITORY_NAME_REGEX.match(reponame):
|
||||||
logger.debug('Found invalid repository name in auth flow: %s', reponame)
|
logger.debug('Found invalid repository name in auth flow: %s', reponame)
|
||||||
abort(400)
|
if len(namespace_and_repo.split('/')) > 1:
|
||||||
|
msg = 'Nested repositories are not supported. Found: %s' % namespace_and_repo
|
||||||
|
raise NameInvalid(message=msg)
|
||||||
|
|
||||||
|
raise NameInvalid(message='Invalid repository name: %s' % namespace_and_repo)
|
||||||
|
|
||||||
final_actions = []
|
final_actions = []
|
||||||
|
|
||||||
|
@ -108,7 +111,7 @@ def generate_registry_jwt(auth_result):
|
||||||
if repo:
|
if repo:
|
||||||
if ModifyRepositoryPermission(namespace, reponame).can():
|
if ModifyRepositoryPermission(namespace, reponame).can():
|
||||||
if repo.kind != 'image':
|
if repo.kind != 'image':
|
||||||
abort(405, invalid_repo_message)
|
raise Unsupported(message=invalid_repo_message)
|
||||||
|
|
||||||
final_actions.append('push')
|
final_actions.append('push')
|
||||||
else:
|
else:
|
||||||
|
@ -125,7 +128,7 @@ def generate_registry_jwt(auth_result):
|
||||||
# Grant pull if the user can read the repo or it is public.
|
# Grant pull if the user can read the repo or it is public.
|
||||||
if ReadRepositoryPermission(namespace, reponame).can() or repo_is_public:
|
if ReadRepositoryPermission(namespace, reponame).can() or repo_is_public:
|
||||||
if repo is not None and repo.kind != 'image':
|
if repo is not None and repo.kind != 'image':
|
||||||
abort(405, invalid_repo_message)
|
raise Unsupported(message=invalid_repo_message)
|
||||||
|
|
||||||
final_actions.append('pull')
|
final_actions.append('pull')
|
||||||
else:
|
else:
|
||||||
|
@ -135,7 +138,7 @@ def generate_registry_jwt(auth_result):
|
||||||
# Grant * user is admin
|
# Grant * user is admin
|
||||||
if AdministerRepositoryPermission(namespace, reponame).can():
|
if AdministerRepositoryPermission(namespace, reponame).can():
|
||||||
if repo is not None and repo.kind != 'image':
|
if repo is not None and repo.kind != 'image':
|
||||||
abort(405, invalid_repo_message)
|
raise Unsupported(message=invalid_repo_message)
|
||||||
|
|
||||||
final_actions.append('*')
|
final_actions.append('*')
|
||||||
else:
|
else:
|
||||||
|
@ -161,13 +164,13 @@ def generate_registry_jwt(auth_result):
|
||||||
'repository': reponame,
|
'repository': reponame,
|
||||||
'namespace': namespace,
|
'namespace': namespace,
|
||||||
}
|
}
|
||||||
|
|
||||||
tuf_root = get_tuf_root(namespace, reponame)
|
tuf_root = get_tuf_root(namespace, reponame)
|
||||||
|
|
||||||
elif user is None and token is None:
|
elif user is None and token is None:
|
||||||
# In this case, we are doing an auth flow, and it's not an anonymous pull
|
# In this case, we are doing an auth flow, and it's not an anonymous pull
|
||||||
logger.debug('No user and no token sent for empty scope list')
|
logger.debug('No user and no token sent for empty scope list')
|
||||||
abort(401)
|
raise Unauthorized()
|
||||||
|
|
||||||
# Send the user event.
|
# Send the user event.
|
||||||
if user is not None:
|
if user is not None:
|
||||||
|
|
Reference in a new issue