summaryrefslogtreecommitdiffstats
path: root/keystone/middleware
diff options
context:
space:
mode:
authorMaru Newby <mnewby@internap.com>2012-03-20 22:19:36 -0700
committerMaru Newby <mnewby@internap.com>2012-03-30 17:26:54 -0700
commit6ec1782dcc13b77eba14d7ff1ace6c9bca997dc5 (patch)
tree8141670f61b3985bf90a25d6b72c8a7012ed327a /keystone/middleware
parentf9c787148747c75f739d9ca555fa26c541752344 (diff)
downloadkeystone-6ec1782dcc13b77eba14d7ff1ace6c9bca997dc5.tar.gz
keystone-6ec1782dcc13b77eba14d7ff1ace6c9bca997dc5.tar.xz
keystone-6ec1782dcc13b77eba14d7ff1ace6c9bca997dc5.zip
Add support to swift_auth for tokenless authz
* Updates keystone.middleware.swift_auth to allow token-less (unauthenticated) access for container sync (bug 954030) and permitted referrers (bug 924578). Change-Id: Ieccf458c44dfe55f546dc15c79704800dad59ac0
Diffstat (limited to 'keystone/middleware')
-rw-r--r--keystone/middleware/swift_auth.py106
1 files changed, 76 insertions, 30 deletions
diff --git a/keystone/middleware/swift_auth.py b/keystone/middleware/swift_auth.py
index df62a834..b5f0a9b1 100644
--- a/keystone/middleware/swift_auth.py
+++ b/keystone/middleware/swift_auth.py
@@ -44,9 +44,12 @@ class SwiftAuth(object):
pipeline = catch_errors cache authtoken swiftauth proxy-server
Make sure you have the authtoken middleware before the swiftauth
- middleware. The authtoken will take care of validating the user
- and swiftauth middleware will authorize it. See the documentation
- about how to configure the authtoken middleware.
+ middleware. authtoken will take care of validating the user and
+ swiftauth will authorize access. If support is required for
+ unvalidated users (as with anonymous access), authtoken will need
+ to be configured with delay_auth_decision set to true. See the
+ documentation for more detail on how to configure the authtoken
+ middleware.
Set account auto creation to true::
@@ -95,15 +98,17 @@ class SwiftAuth(object):
def __call__(self, environ, start_response):
identity = self._keystone_identity(environ)
- if not identity:
- environ['swift.authorize'] = self.denied_response
- return self.app(environ, start_response)
+ if identity:
+ self.logger.debug('Using identity: %r' % (identity))
+ environ['keystone.identity'] = identity
+ environ['REMOTE_USER'] = identity.get('tenant')
+ environ['swift.authorize'] = self.authorize
+ else:
+ self.logger.debug('Authorizing as anonymous')
+ environ['swift.authorize'] = self.authorize_anonymous
- self.logger.debug("Using identity: %r" % (identity))
- environ['keystone.identity'] = identity
- environ['REMOTE_USER'] = identity.get('tenant')
- environ['swift.authorize'] = self.authorize
environ['swift.clean_acl'] = swift_acl.clean_acl
+
return self.app(environ, start_response)
def _keystone_identity(self, environ):
@@ -119,9 +124,12 @@ class SwiftAuth(object):
'roles': roles}
return identity
+ def _get_account_for_tenant(self, tenant_id):
+ return '%s%s' % (self.reseller_prefix, tenant_id)
+
def _reseller_check(self, account, tenant_id):
"""Check reseller prefix."""
- return account == '%s%s' % (self.reseller_prefix, tenant_id)
+ return account == self._get_account_for_tenant(tenant_id)
def authorize(self, req):
env = req.environ
@@ -169,26 +177,13 @@ class SwiftAuth(object):
req.environ['swift_owner'] = True
return
- # Allow container sync.
- if (req.environ.get('swift_sync_key')
- and req.environ['swift_sync_key'] ==
- req.headers.get('x-container-sync-key', None)
- and 'x-timestamp' in req.headers
- and (req.remote_addr in self.allowed_sync_hosts
- or swift_utils.get_remote_client(req)
- in self.allowed_sync_hosts)):
- log_msg = 'allowing proxy %s for container-sync' % req.remote_addr
- self.logger.debug(log_msg)
- return
-
- # Check if referrer is allowed.
referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None))
- if swift_acl.referrer_allowed(req.referer, referrers):
- #TODO(chmou): convert .rlistings to Keystone type role.
- if obj or '.rlistings' in roles:
- log_msg = 'authorizing %s via referer ACL' % req.referrer
- self.logger.debug(log_msg)
- return
+
+ authorized = self._authorize_unconfirmed_identity(req, obj, referrers,
+ roles)
+ if authorized:
+ return
+ elif authorized is not None:
return self.denied_response(req)
# Allow ACL at individual user level (tenant:user format)
@@ -206,6 +201,57 @@ class SwiftAuth(object):
return self.denied_response(req)
+ def authorize_anonymous(self, req):
+ """
+ Authorize an anonymous request.
+
+ :returns: None if authorization is granted, an error page otherwise.
+ """
+ try:
+ part = swift_utils.split_path(req.path, 1, 4, True)
+ version, account, container, obj = part
+ except ValueError:
+ return webob.exc.HTTPNotFound(request=req)
+
+ is_authoritative_authz = (account and
+ account.startswith(self.reseller_prefix))
+ if not is_authoritative_authz:
+ return self.denied_response(req)
+
+ referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None))
+ authorized = self._authorize_unconfirmed_identity(req, obj, referrers,
+ roles)
+ if not authorized:
+ return self.denied_response(req)
+
+ def _authorize_unconfirmed_identity(self, req, obj, referrers, roles):
+ """"
+ Perform authorization for access that does not require a
+ confirmed identity.
+
+ :returns: A boolean if authorization is granted or denied. None if
+ a determination could not be made.
+ """
+ # Allow container sync.
+ if (req.environ.get('swift_sync_key')
+ and req.environ['swift_sync_key'] ==
+ req.headers.get('x-container-sync-key', None)
+ and 'x-timestamp' in req.headers
+ and (req.remote_addr in self.allowed_sync_hosts
+ or swift_utils.get_remote_client(req)
+ in self.allowed_sync_hosts)):
+ log_msg = 'allowing proxy %s for container-sync' % req.remote_addr
+ self.logger.debug(log_msg)
+ return True
+
+ # Check if referrer is allowed.
+ if swift_acl.referrer_allowed(req.referer, referrers):
+ if obj or '.rlistings' in roles:
+ log_msg = 'authorizing %s via referer ACL' % req.referrer
+ self.logger.debug(log_msg)
+ return True
+ return False
+
def denied_response(self, req):
"""Deny WSGI Response.