diff options
author | Maru Newby <mnewby@internap.com> | 2012-03-20 22:19:36 -0700 |
---|---|---|
committer | Maru Newby <mnewby@internap.com> | 2012-03-30 17:26:54 -0700 |
commit | 6ec1782dcc13b77eba14d7ff1ace6c9bca997dc5 (patch) | |
tree | 8141670f61b3985bf90a25d6b72c8a7012ed327a /keystone/middleware | |
parent | f9c787148747c75f739d9ca555fa26c541752344 (diff) | |
download | keystone-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.py | 106 |
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. |