Refactor auth_token.py to only call out to Keystone once.
Fixes bug 890881. Change-Id: I096d2c63e8f2c996dc1e5dd7315f57e2303d24cb
This commit is contained in:
parent
e74ad8ad71
commit
316e2bca9f
|
@ -112,6 +112,10 @@ from keystone.common.bufferedhttp import http_connect_raw as http_connect
|
||||||
PROTOCOL_NAME = "Token Authentication"
|
PROTOCOL_NAME = "Token Authentication"
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationFailed(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class AuthProtocol(object):
|
class AuthProtocol(object):
|
||||||
"""Auth Middleware that handles authenticating client calls"""
|
"""Auth Middleware that handles authenticating client calls"""
|
||||||
|
|
||||||
|
@ -211,8 +215,9 @@ class AuthProtocol(object):
|
||||||
return self._reject_request(env, start_response)
|
return self._reject_request(env, start_response)
|
||||||
else:
|
else:
|
||||||
# this request is presenting claims. Let's validate them
|
# this request is presenting claims. Let's validate them
|
||||||
valid = self._validate_claims(claims)
|
try:
|
||||||
if not valid:
|
claims = self._verify_claims(claims)
|
||||||
|
except ValidationFailed:
|
||||||
# Keystone rejected claim
|
# Keystone rejected claim
|
||||||
if self.delay_auth_decision:
|
if self.delay_auth_decision:
|
||||||
# Downstream service will receive call still and decide
|
# Downstream service will receive call still and decide
|
||||||
|
@ -225,10 +230,6 @@ class AuthProtocol(object):
|
||||||
self._decorate_request("X_IDENTITY_STATUS",
|
self._decorate_request("X_IDENTITY_STATUS",
|
||||||
"Confirmed", env, proxy_headers)
|
"Confirmed", env, proxy_headers)
|
||||||
|
|
||||||
#Collect information about valid claims
|
|
||||||
if valid:
|
|
||||||
claims = self._expound_claims(claims)
|
|
||||||
|
|
||||||
# Store authentication data
|
# Store authentication data
|
||||||
if claims:
|
if claims:
|
||||||
self._decorate_request('X_AUTHORIZATION', "Proxy %s" %
|
self._decorate_request('X_AUTHORIZATION', "Proxy %s" %
|
||||||
|
@ -280,8 +281,8 @@ class AuthProtocol(object):
|
||||||
return HTTPUnauthorized()(env,
|
return HTTPUnauthorized()(env,
|
||||||
start_response)
|
start_response)
|
||||||
|
|
||||||
def _validate_claims(self, claims):
|
def _verify_claims(self, claims):
|
||||||
"""Validate claims, and provide identity information if applicable """
|
"""Verify claims and extract identity information, if applicable."""
|
||||||
|
|
||||||
# Step 1: We need to auth with the keystone service, so get an
|
# Step 1: We need to auth with the keystone service, so get an
|
||||||
# admin token
|
# admin token
|
||||||
|
@ -301,44 +302,17 @@ class AuthProtocol(object):
|
||||||
#Khaled's version uses creds to get a token
|
#Khaled's version uses creds to get a token
|
||||||
# "X-Auth-Token": admin_token}
|
# "X-Auth-Token": admin_token}
|
||||||
# we're using a test token from the ini file for now
|
# we're using a test token from the ini file for now
|
||||||
conn = http_connect(self.auth_host, self.auth_port, 'HEAD',
|
conn = http_connect(self.auth_host, self.auth_port, 'GET',
|
||||||
'/v2.0/tokens/%s' % claims, headers=headers,
|
'/v2.0/tokens/%s' % claims, headers=headers,
|
||||||
ssl=(self.auth_protocol == 'https'),
|
ssl=(self.auth_protocol == 'https'),
|
||||||
key_file=self.key_file, cert_file=self.cert_file)
|
key_file=self.key_file, cert_file=self.cert_file)
|
||||||
resp = conn.getresponse()
|
resp = conn.getresponse()
|
||||||
|
data = resp.read()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
if not str(resp.status).startswith('20'):
|
if not str(resp.status).startswith('20'):
|
||||||
# Keystone rejected claim
|
# Keystone rejected claim
|
||||||
return False
|
raise ValidationFailed()
|
||||||
else:
|
|
||||||
#TODO(Ziad): there is an optimization we can do here. We can make
|
|
||||||
#one call and reuse the data instead of calling again
|
|
||||||
#in _expound_claims
|
|
||||||
return True
|
|
||||||
|
|
||||||
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,
|
|
||||||
ssl=(self.auth_protocol == 'https'),
|
|
||||||
key_file=self.key_file, cert_file=self.cert_file)
|
|
||||||
resp = conn.getresponse()
|
|
||||||
data = resp.read()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
if not (resp.status >= 200 and resp.status <= 209):
|
|
||||||
raise LookupError('Unable to locate claims: %s' % resp.status)
|
|
||||||
|
|
||||||
token_info = json.loads(data)
|
token_info = json.loads(data)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue