Merge "Unpythonic code in redux in auth_token.py"

This commit is contained in:
Jenkins 2012-02-29 02:47:14 +00:00 committed by Gerrit Code Review
commit 7c2ad0a583
1 changed files with 112 additions and 82 deletions

View File

@ -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)
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)
# 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)