getting pep8-y with it
This commit is contained in:
parent
4006479c24
commit
f606f6b4f5
|
@ -43,6 +43,7 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'echo', '__init__.py')):
|
|||
Echo: a dummy service for OpenStack auth testing. It returns request info.
|
||||
"""
|
||||
|
||||
|
||||
class EchoApp(object):
|
||||
def __init__(self, environ, start_response):
|
||||
self.envr = environ
|
||||
|
@ -57,9 +58,10 @@ class EchoApp(object):
|
|||
# We assume the request is coming from a trusted source. Middleware
|
||||
# is used to perform that validation.
|
||||
if 'HTTP_X_AUTHORIZATION' not in self.envr:
|
||||
self.start('401 Unauthorized', [('Content-Type', 'application/json')])
|
||||
self.start('401 Unauthorized', [('Content-Type',
|
||||
'application/json')])
|
||||
return iter(["401 Unauthorized"])
|
||||
|
||||
|
||||
if 'HTTP_X_IDENTITY_STATUS' not in self.envr:
|
||||
identity_status = "Unknown"
|
||||
else:
|
||||
|
|
|
@ -47,11 +47,13 @@ def call_service(token):
|
|||
ret = data
|
||||
return ret
|
||||
|
||||
|
||||
def hack_attempt(token):
|
||||
# Injecting headers in the request
|
||||
headers = {"X-Auth-Token": token,
|
||||
"Content-type": "application/json",
|
||||
"Accept": "text/json\nX_AUTHORIZATION: someone else\nX_IDENTITY_STATUS: Confirmed\nINJECTED_HEADER: aha!"}
|
||||
"Accept": "text/json\nX_AUTHORIZATION: someone else\n"
|
||||
"X_IDENTITY_STATUS: Confirmed\nINJECTED_HEADER: aha!"}
|
||||
params = '{"ping": "abcdefg"}'
|
||||
conn = httplib.HTTPConnection("localhost:8090")
|
||||
print headers
|
||||
|
@ -70,24 +72,24 @@ if __name__ == '__main__':
|
|||
obj = json.loads(auth)
|
||||
token = obj["auth"]["token"]["id"]
|
||||
print "Token obtained:", token
|
||||
|
||||
|
||||
# Use that token to call an OpenStack service (echo)
|
||||
data = call_service(token)
|
||||
print "Response received:", data
|
||||
print
|
||||
|
||||
|
||||
# Use the valid token, but inject some headers
|
||||
print "\033[91mInjecting some headers >:-/ \033[0m"
|
||||
data = hack_attempt(token)
|
||||
print "Response received:", data
|
||||
print
|
||||
|
||||
|
||||
# Use bad token to call an OpenStack service (echo)
|
||||
print "\033[91mTrying with bad token...\033[0m"
|
||||
data = call_service("xxxx_invalid_token_xxxx")
|
||||
print "Response received:", data
|
||||
print
|
||||
|
||||
|
||||
#Supply bad credentials
|
||||
print "\033[91mTrying with bad credentials...\033[0m"
|
||||
auth = get_auth_token("joeuser", "wrongpass", "1")
|
||||
|
|
|
@ -75,7 +75,8 @@ class AuthProtocol(object):
|
|||
def __call__(self, env, start_response):
|
||||
def custom_start_response(status, headers):
|
||||
if self.delay_auth_decision:
|
||||
headers.append(('WWW-Authenticate', "Basic realm='Use guest/guest'"))
|
||||
headers.append(('WWW-Authenticate',
|
||||
"Basic realm='Use guest/guest'"))
|
||||
return start_response(status, headers)
|
||||
|
||||
#Prep headers to proxy request to remote service
|
||||
|
@ -91,16 +92,16 @@ class AuthProtocol(object):
|
|||
else:
|
||||
# If the user isn't authenticated, we reject the request and
|
||||
# return 401 indicating we need Basic Auth credentials.
|
||||
return HTTPUnauthorized(
|
||||
"Authentication required",
|
||||
[('WWW-Authenticate', 'Basic realm="Use guest/guest"')]
|
||||
)(env,start_response)
|
||||
return HTTPUnauthorized("Authentication required",
|
||||
[('WWW-Authenticate',
|
||||
'Basic realm="Use guest/guest"')]
|
||||
)(env, start_response)
|
||||
else:
|
||||
# Claims were provided - validate them
|
||||
import base64
|
||||
auth_header = env['HTTP_AUTHORIZATION']
|
||||
auth_type, encoded_creds = auth_header.split(None, 1)
|
||||
user, password = base64.b64decode(encoded_creds).split(':', 1)
|
||||
user, password = base64.b64decode(encoded_creds).split(':', 1)
|
||||
if not self.validateCreds(user, password):
|
||||
#Claims were rejected
|
||||
if not self.delay_auth_decision:
|
||||
|
@ -125,13 +126,12 @@ class AuthProtocol(object):
|
|||
_decorate_request_headers('X_GROUP', 'Blank',
|
||||
proxy_headers, env)
|
||||
|
||||
|
||||
#Auth processed, headers added now decide how to pass on the call
|
||||
if self.app:
|
||||
# Pass to downstream WSGI component
|
||||
env['HTTP_AUTHORIZATION'] = "Basic %s" % self.service_pass
|
||||
return self.app(env, custom_start_response)
|
||||
|
||||
|
||||
proxy_headers['AUTHORIZATION'] = "Basic %s" % self.service_pass
|
||||
# We are forwarding to a remote service (no downstream WSGI app)
|
||||
req = Request(proxy_headers)
|
||||
|
@ -146,9 +146,6 @@ class AuthProtocol(object):
|
|||
# we are rewriting the headers now
|
||||
return Response(status=resp.status, body=data)(env, start_response)
|
||||
|
||||
|
||||
|
||||
|
||||
def validateCreds(self, username, password):
|
||||
#stub for password validation.
|
||||
import ConfigParser
|
||||
|
@ -163,6 +160,7 @@ class AuthProtocol(object):
|
|||
return True
|
||||
return False
|
||||
|
||||
|
||||
def filter_factory(global_conf, ** local_conf):
|
||||
"""Returns a WSGI filter app for use with paste.deploy."""
|
||||
conf = global_conf.copy()
|
||||
|
|
|
@ -117,14 +117,13 @@ class AuthProtocol(object):
|
|||
self._init_protocol_common(app, conf) # Applies to all protocols
|
||||
self._init_protocol(app, conf) # Specific to this protocol
|
||||
|
||||
|
||||
def __call__(self, env, start_response):
|
||||
""" Handle incoming request. Authenticate. And send downstream. """
|
||||
|
||||
self.start_response = start_response
|
||||
self.env = env
|
||||
|
||||
#Prep headers to forward request to downstream service (local or remote)
|
||||
#Prep headers to forward request to local or remote downstream service
|
||||
self.proxy_headers = env.copy()
|
||||
for header in self.proxy_headers.iterkeys():
|
||||
if header[0:5] == 'HTTP_':
|
||||
|
@ -158,23 +157,21 @@ class AuthProtocol(object):
|
|||
|
||||
#Collect information about valid claims
|
||||
if valid:
|
||||
verified_claims = self._expound_claims()
|
||||
if verified_claims:
|
||||
claims = self._expound_claims()
|
||||
if claims:
|
||||
# TODO(Ziad): add additional details we may need,
|
||||
# like tenant and group info
|
||||
self._decorate_request('X_AUTHORIZATION',
|
||||
"Proxy %s" % verified_claims['user'])
|
||||
"Proxy %s" % claims['user'])
|
||||
self._decorate_request('X_TENANT',
|
||||
verified_claims['tenant'])
|
||||
claims['tenant'])
|
||||
self._decorate_request('X_GROUP',
|
||||
verified_claims['group'])
|
||||
claims['group'])
|
||||
self.expanded = True
|
||||
|
||||
|
||||
#Send request downstream
|
||||
return self._forward_request()
|
||||
|
||||
|
||||
def get_admin_auth_token(self, username, password, tenant):
|
||||
"""
|
||||
This function gets an admin auth token to be used by this service to
|
||||
|
@ -198,25 +195,25 @@ class AuthProtocol(object):
|
|||
return claims
|
||||
|
||||
def _reject_request(self):
|
||||
# Redirect client to auth server
|
||||
return HTTPUseProxy(location=self.auth_location)(self.env,
|
||||
self.start_response)
|
||||
# Redirect client to auth server
|
||||
return HTTPUseProxy(location=self.auth_location)(self.env,
|
||||
self.start_response)
|
||||
|
||||
def _reject_claims(self):
|
||||
# Client sent bad claims
|
||||
return HTTPUnauthorized()(self.env,
|
||||
self.start_response)
|
||||
# Client sent bad claims
|
||||
return HTTPUnauthorized()(self.env,
|
||||
self.start_response)
|
||||
|
||||
def _validate_claims(self, claims):
|
||||
"""Validate claims, and provide identity information isf applicable """
|
||||
|
||||
|
||||
# Step 1: We need to auth with the keystone service, so get an
|
||||
# admin token
|
||||
#TODO: Need to properly implement this, where to store creds
|
||||
# for now using token from ini
|
||||
#auth = self.get_admin_auth_token("admin", "secrete", "1")
|
||||
#admin_token = json.loads(auth)["auth"]["token"]["id"]
|
||||
|
||||
|
||||
# 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
|
||||
|
@ -268,10 +265,11 @@ class AuthProtocol(object):
|
|||
first_group = token_info['auth']['user']['groups']['group'][0]
|
||||
verified_claims = {'user': token_info['auth']['user']['username'],
|
||||
'tenant': token_info['auth']['user']['tenantId'],
|
||||
'group': '%s/%s' % (first_group['id'], first_group['tenantId'])}
|
||||
'group': '%s/%s' % (first_group['id'],
|
||||
first_group['tenantId'])}
|
||||
return verified_claims
|
||||
|
||||
def _decorate_request(self, index, value):
|
||||
def _decorate_request(self, index, value):
|
||||
self.proxy_headers[index] = value
|
||||
self.env["HTTP_%s" % index] = value
|
||||
|
||||
|
@ -282,15 +280,18 @@ class AuthProtocol(object):
|
|||
#now decide how to pass on the call
|
||||
if self.app:
|
||||
# Pass to downstream WSGI component
|
||||
return self.app(self.env, self.start_response) #.custom_start_response)
|
||||
return self.app(self.env, self.start_response)
|
||||
#.custom_start_response)
|
||||
else:
|
||||
# We are forwarding to a remote service (no downstream WSGI app)
|
||||
req = Request(self.proxy_headers)
|
||||
parsed = urlparse(req.url)
|
||||
conn = http_connect(self.service_host, self.service_port, \
|
||||
req.method, parsed.path, \
|
||||
self.proxy_headers,\
|
||||
ssl=(self.service_protocol == 'https'))
|
||||
conn = http_connect(self.service_host,
|
||||
self.service_port,
|
||||
req.method,
|
||||
parsed.path,
|
||||
self.proxy_headers,
|
||||
ssl=(self.service_protocol == 'https'))
|
||||
resp = conn.getresponse()
|
||||
data = resp.read()
|
||||
#TODO: use a more sophisticated proxy
|
||||
|
|
Loading…
Reference in New Issue