Return "scope" in auth challenge

Containerd requires a "scope" in the www-authenticate header.
See https://github.com/containerd/containerd/issues/3556

Change-Id: I3f438c3595b8b864d47a735e736d309525d30a41
This commit is contained in:
James E. Blair 2021-07-31 18:09:19 -07:00
parent 720d091653
commit 0c03e1e054

View File

@ -71,9 +71,10 @@ class Authorization(cherrypy.Tool):
return False
return store[user] == password
def unauthorized(self):
def unauthorized(self, scope):
cherrypy.response.headers['www-authenticate'] = (
'Bearer realm="%s/auth/token"' % (self.public_url,)
'Bearer realm="%s/auth/token",scope="%s"' % (
self.public_url, scope)
)
raise cherrypy.HTTPError(401, 'Authentication required')
@ -86,7 +87,7 @@ class Authorization(cherrypy.Tool):
self.log.debug('Auth ok %s', level)
return
self.log.debug('Unauthorized %s', level)
self.unauthorized()
self.unauthorized(level)
def _get_level(self, scope):
level = None
@ -132,9 +133,9 @@ class Authorization(cherrypy.Tool):
level = self._get_level(kw.get('scope', ''))
self.log.info('Authenticate level %s', level)
if level == self.WRITE:
self._check_creds(auth_header, [self.rw])
self._check_creds(auth_header, [self.rw], level)
elif level == self.READ and not self.anonymous_read:
self._check_creds(auth_header, [self.rw, self.ro])
self._check_creds(auth_header, [self.rw, self.ro], level)
# If we permit anonymous read and we're requesting read, no
# check is performed.
self.log.debug('Generate %s token', level)
@ -142,7 +143,7 @@ class Authorization(cherrypy.Tool):
return {'token': token,
'access_token': token}
def _check_creds(self, auth_header, credstores):
def _check_creds(self, auth_header, credstores, level):
# If the password is okay, fall through; otherwise call
# unauthorized for the side effect of raising an exception.
if auth_header and 'Basic' in auth_header:
@ -152,9 +153,9 @@ class Authorization(cherrypy.Tool):
# Return true on the first credstore with the user, false otherwise
if not next(filter(
lambda cs: self.check(cs, user, pw), credstores), False):
self.unauthorized()
self.unauthorized(level)
else:
self.unauthorized()
self.unauthorized(level)
class RegistryAPI: