summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keystone/common/wsgi.py14
-rw-r--r--keystone/identity/backends/ldap/core.py2
-rw-r--r--keystone/middleware/auth_token.py196
-rw-r--r--keystone/middleware/core.py7
4 files changed, 122 insertions, 97 deletions
diff --git a/keystone/common/wsgi.py b/keystone/common/wsgi.py
index c75339f53..6279d4cc4 100644
--- a/keystone/common/wsgi.py
+++ b/keystone/common/wsgi.py
@@ -260,7 +260,7 @@ class Middleware(Application):
def __init__(self, application):
self.application = application
- def process_request(self, req):
+ def process_request(self, request):
"""Called on each request.
If this returns None, the next application down the stack will be
@@ -270,17 +270,17 @@ class Middleware(Application):
"""
return None
- def process_response(self, response):
- """Do whatever you'd like to the response."""
+ def process_response(self, request, response):
+ """Do whatever you'd like to the response, based on the request."""
return response
@webob.dec.wsgify(RequestClass=Request)
- def __call__(self, req):
- response = self.process_request(req)
+ def __call__(self, request):
+ response = self.process_request(request)
if response:
return response
- response = req.get_response(self.application)
- return self.process_response(response)
+ response = request.get_response(self.application)
+ return self.process_response(request, response)
class Debug(Middleware):
diff --git a/keystone/identity/backends/ldap/core.py b/keystone/identity/backends/ldap/core.py
index 84eb1ae62..409a384a0 100644
--- a/keystone/identity/backends/ldap/core.py
+++ b/keystone/identity/backends/ldap/core.py
@@ -356,7 +356,7 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
DEFAULT_ID_ATTRIBUTE = 'cn'
DEFAULT_MEMBER_ATTRIBUTE = 'member'
options_name = 'tenant'
- attribute_mapping = { 'description': 'desc', 'name': 'ou' }
+ attribute_mapping = {'description': 'desc', 'name': 'ou'}
model = models.Tenant
def __init__(self, conf):
diff --git a/keystone/middleware/auth_token.py b/keystone/middleware/auth_token.py
index 1dd437c82..c323565e2 100644
--- a/keystone/middleware/auth_token.py
+++ b/keystone/middleware/auth_token.py
@@ -120,9 +120,9 @@ class AuthProtocol(object):
# where to tell clients to find the auth service (default to url
# constructed based on endpoint we have for the service to use)
self.auth_location = conf.get('auth_uri',
- '%s://%s:%s' % (self.auth_protocol,
- self.auth_host,
- self.auth_port))
+ '%s://%s:%s' % (self.auth_protocol,
+ self.auth_host,
+ self.auth_port))
# Credentials used to verify this component with the Auth service since
# validating tokens is a privileged call
@@ -143,7 +143,7 @@ class AuthProtocol(object):
#Prep headers to forward request to local or remote downstream service
proxy_headers = env.copy()
for header in proxy_headers.iterkeys():
- if header[0:5] == 'HTTP_':
+ if header.startswith('HTTP_'):
proxy_headers[header[5:]] = proxy_headers[header]
del proxy_headers[header]
@@ -155,7 +155,9 @@ class AuthProtocol(object):
#Configured to allow downstream service to make final decision.
#So mark status as Invalid and forward the request downstream
self._decorate_request('X_IDENTITY_STATUS',
- 'Invalid', env, proxy_headers)
+ 'Invalid',
+ env,
+ proxy_headers)
else:
#Respond to client as appropriate for this auth protocol
return self._reject_request(env, start_response)
@@ -167,13 +169,17 @@ class AuthProtocol(object):
if self.delay_auth_decision:
# Downstream service will receive call still and decide
self._decorate_request('X_IDENTITY_STATUS',
- 'Invalid', env, proxy_headers)
+ 'Invalid',
+ env,
+ proxy_headers)
else:
#Respond to client as appropriate for this auth protocol
return self._reject_claims(env, start_response)
else:
self._decorate_request('X_IDENTITY_STATUS',
- 'Confirmed', env, proxy_headers)
+ 'Confirmed',
+ env,
+ proxy_headers)
#Collect information about valid claims
if valid:
@@ -181,34 +187,44 @@ class AuthProtocol(object):
# Store authentication data
if claims:
- self._decorate_request('X_AUTHORIZATION', 'Proxy %s' %
- claims['user'], env, proxy_headers)
+ self._decorate_request('X_AUTHORIZATION',
+ 'Proxy %s' % claims['user'],
+ env,
+ proxy_headers)
# For legacy compatibility before we had ID and Name
self._decorate_request('X_TENANT',
- claims['tenant'], env, proxy_headers)
+ claims['tenant'],
+ env,
+ proxy_headers)
# Services should use these
self._decorate_request('X_TENANT_NAME',
- claims.get('tenantName', claims['tenant']),
- env, proxy_headers)
+ claims.get('tenantName',
+ claims['tenant']),
+ env,
+ proxy_headers)
self._decorate_request('X_TENANT_ID',
- claims['tenant'], env, proxy_headers)
+ claims['tenant'],
+ env,
+ proxy_headers)
self._decorate_request('X_USER',
- claims['userName'], env, proxy_headers)
+ claims['userName'],
+ env,
+ proxy_headers)
self._decorate_request('X_USER_ID',
- claims['user'], env, proxy_headers)
-
- if 'roles' in claims and len(claims['roles']) > 0:
- if claims['roles'] != None:
- roles = ''
- for role in claims['roles']:
- if len(roles) > 0:
- roles += ','
- roles += role
- self._decorate_request('X_ROLE',
- roles, env, proxy_headers)
+ claims['user'],
+ env,
+ proxy_headers)
+
+ # NOTE(lzyeval): claims has a key 'roles' which is
+ # guaranteed to be a list (see note below)
+ roles = ','.join(filter(lambda x: x, claims['roles']))
+ self._decorate_request('X_ROLE',
+ roles,
+ env,
+ proxy_headers)
# NOTE(todd): unused
self.expanded = True
@@ -223,15 +239,15 @@ class AuthProtocol(object):
def _reject_request(self, env, start_response):
"""Redirect client to auth server"""
- return webob.exc.HTTPUnauthorized('Authentication required',
- [('WWW-Authenticate',
- "Keystone uri='%s'" % self.auth_location)])(env,
- start_response)
+ headers = [('WWW-Authenticate',
+ "Keystone uri='%s'" % self.auth_location)]
+ resp = webob.exc.HTTPUnauthorized('Authentication required', headers)
+ return resp(env, start_response)
def _reject_claims(self, env, start_response):
"""Client sent bad claims"""
- return webob.exc.HTTPUnauthorized()(env,
- start_response)
+ resp = webob.exc.HTTPUnauthorized()
+ return resp(env, start_response)
def _get_admin_auth_token(self, username, password):
"""
@@ -241,23 +257,27 @@ class AuthProtocol(object):
"""
headers = {
"Content-type": "application/json",
- "Accept": "application/json"}
+ "Accept": "application/json",
+ }
params = {
- "auth": {
- "passwordCredentials": {
+ "auth": {
+ "passwordCredentials": {
"username": username,
"password": password,
},
- "tenantName": ADMIN_TENANTNAME,
- }
- }
+ "tenantName": ADMIN_TENANTNAME,
+ }
+ }
if self.auth_protocol == "http":
conn = httplib.HTTPConnection(self.auth_host, self.auth_port)
else:
- conn = httplib.HTTPSConnection(self.auth_host, self.auth_port,
- cert_file=self.cert_file)
- conn.request("POST", '/v2.0/tokens', json.dumps(params),
- headers=headers)
+ conn = httplib.HTTPSConnection(self.auth_host,
+ self.auth_port,
+ cert_file=self.cert_file)
+ conn.request("POST",
+ '/v2.0/tokens',
+ json.dumps(params),
+ headers=headers)
response = conn.getresponse()
data = response.read()
conn.close()
@@ -278,16 +298,21 @@ class AuthProtocol(object):
# Step 2: validate the user's token with the auth service
# since this is a priviledged op,m we need to auth ourselves
# by using an admin token
- headers = {'Content-type': 'application/json',
- 'Accept': 'application/json',
- 'X-Auth-Token': self.admin_token}
- ##TODO(ziad):we need to figure out how to auth to keystone
- #since validate_token is a priviledged call
- #Khaled's version uses creds to get a token
- # 'X-Auth-Token': admin_token}
- # we're using a test token from the ini file for now
- conn = http_connect(self.auth_host, self.auth_port, 'GET',
- '/v2.0/tokens/%s' % claims, headers=headers)
+ headers = {
+ 'Content-type': 'application/json',
+ 'Accept': 'application/json',
+ 'X-Auth-Token': self.admin_token,
+ }
+ ##TODO(ziad):we need to figure out how to auth to keystone
+ #since validate_token is a priviledged call
+ #Khaled's version uses creds to get a token
+ # 'X-Auth-Token': admin_token}
+ # we're using a test token from the ini file for now
+ conn = http_connect(self.auth_host,
+ self.auth_port,
+ 'GET',
+ '/v2.0/tokens/%s' % claims,
+ headers=headers)
resp = conn.getresponse()
# data = resp.read()
conn.close()
@@ -307,16 +332,21 @@ class AuthProtocol(object):
def _expound_claims(self, claims):
# Valid token. Get user data and put it in to the call
# so the downstream service can use it
- headers = {'Content-type': 'application/json',
- 'Accept': 'application/json',
- 'X-Auth-Token': self.admin_token}
- ##TODO(ziad):we need to figure out how to auth to keystone
- #since validate_token is a priviledged call
- #Khaled's version uses creds to get a token
- # 'X-Auth-Token': admin_token}
- # we're using a test token from the ini file for now
- conn = http_connect(self.auth_host, self.auth_port, 'GET',
- '/v2.0/tokens/%s' % claims, headers=headers)
+ headers = {
+ 'Content-type': 'application/json',
+ 'Accept': 'application/json',
+ 'X-Auth-Token': self.admin_token,
+ }
+ ##TODO(ziad):we need to figure out how to auth to keystone
+ #since validate_token is a priviledged call
+ #Khaled's version uses creds to get a token
+ # 'X-Auth-Token': admin_token}
+ # we're using a test token from the ini file for now
+ conn = http_connect(self.auth_host,
+ self.auth_port,
+ 'GET',
+ '/v2.0/tokens/%s' % claims,
+ headers=headers)
resp = conn.getresponse()
data = resp.read()
conn.close()
@@ -325,28 +355,28 @@ class AuthProtocol(object):
raise LookupError('Unable to locate claims: %s' % resp.status)
token_info = json.loads(data)
- roles = []
- role_refs = token_info['access']['user']['roles']
- if role_refs != None:
- for role_ref in role_refs:
- # Nova looks for the non case-sensitive role 'admin'
- # to determine admin-ness
- roles.append(role_ref['name'])
+ access_user = token_info['access']['user']
+ access_token = token_info['access']['token']
+ # Nova looks for the non case-sensitive role 'admin'
+ # to determine admin-ness
+ # NOTE(lzyeval): roles is always a list
+ roles = map(lambda y: y['name'], access_user.get('roles', []))
try:
- tenant = token_info['access']['token']['tenant']['id']
- tenant_name = token_info['access']['token']['tenant']['name']
+ tenant = access_token['tenant']['id']
+ tenant_name = access_token['tenant']['name']
except:
tenant = None
tenant_name = None
if not tenant:
- tenant = token_info['access']['user'].get('tenantId')
- tenant_name = token_info['access']['user'].get('tenantName')
+ tenant = access_user.get('tenantId')
+ tenant_name = access_user.get('tenantName')
verified_claims = {
- 'user': token_info['access']['user']['id'],
- 'userName': token_info['access']['user']['username'],
- 'tenant': tenant,
- 'roles': roles}
+ 'user': access_user['id'],
+ 'userName': access_user['username'],
+ 'tenant': tenant,
+ 'roles': roles,
+ }
if tenant_name:
verified_claims['tenantName'] = tenant_name
return verified_claims
@@ -385,7 +415,7 @@ class AuthProtocol(object):
if resp.status == 401 or resp.status == 305:
# Add our own headers to the list
headers = [('WWW_AUTHENTICATE',
- "Keystone uri='%s'" % self.auth_location)]
+ "Keystone uri='%s'" % self.auth_location)]
return webob.Response(status=resp.status,
body=data,
headerlist=headers)(env, start_response)
@@ -410,10 +440,10 @@ def app_factory(global_conf, **local_conf):
return AuthProtocol(None, conf)
if __name__ == '__main__':
- app = deploy.loadapp('config:' + \
- os.path.join(os.path.abspath(os.path.dirname(__file__)),
- os.pardir,
- os.pardir,
- 'examples/paste/auth_token.ini'),
- global_conf={'log_name': 'auth_token.log'})
+ app_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
+ os.pardir,
+ os.pardir,
+ 'examples/paste/auth_token.ini')
+ app = deploy.loadapp('config:%s' % app_path,
+ global_conf={'log_name': 'auth_token.log'})
wsgi.server(eventlet.listen(('', 8090)), app)
diff --git a/keystone/middleware/core.py b/keystone/middleware/core.py
index 19212e0c9..7faa3f013 100644
--- a/keystone/middleware/core.py
+++ b/keystone/middleware/core.py
@@ -130,12 +130,6 @@ class JsonBodyMiddleware(wsgi.Middleware):
class XmlBodyMiddleware(wsgi.Middleware):
"""De/serializes XML to/from JSON."""
- @webob.dec.wsgify(RequestClass=wsgi.Request)
- def __call__(self, request):
- self.process_request(request)
- response = request.get_response(self.application)
- self.process_response(request, response)
- return response
def process_request(self, request):
"""Transform the request from XML to JSON."""
@@ -153,3 +147,4 @@ class XmlBodyMiddleware(wsgi.Middleware):
response.body = serializer.to_xml(json.loads(response.body))
except:
raise exception.Error(message=response.body)
+ return response