getting pep8-y with it

This commit is contained in:
Jesse Andrews 2011-04-30 09:18:15 -07:00
parent 4006479c24
commit f606f6b4f5
4 changed files with 45 additions and 42 deletions

View File

@ -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. Echo: a dummy service for OpenStack auth testing. It returns request info.
""" """
class EchoApp(object): class EchoApp(object):
def __init__(self, environ, start_response): def __init__(self, environ, start_response):
self.envr = environ self.envr = environ
@ -57,9 +58,10 @@ class EchoApp(object):
# We assume the request is coming from a trusted source. Middleware # We assume the request is coming from a trusted source. Middleware
# is used to perform that validation. # is used to perform that validation.
if 'HTTP_X_AUTHORIZATION' not in self.envr: 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"]) return iter(["401 Unauthorized"])
if 'HTTP_X_IDENTITY_STATUS' not in self.envr: if 'HTTP_X_IDENTITY_STATUS' not in self.envr:
identity_status = "Unknown" identity_status = "Unknown"
else: else:

View File

@ -47,11 +47,13 @@ def call_service(token):
ret = data ret = data
return ret return ret
def hack_attempt(token): def hack_attempt(token):
# Injecting headers in the request # Injecting headers in the request
headers = {"X-Auth-Token": token, headers = {"X-Auth-Token": token,
"Content-type": "application/json", "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"}' params = '{"ping": "abcdefg"}'
conn = httplib.HTTPConnection("localhost:8090") conn = httplib.HTTPConnection("localhost:8090")
print headers print headers
@ -70,24 +72,24 @@ if __name__ == '__main__':
obj = json.loads(auth) obj = json.loads(auth)
token = obj["auth"]["token"]["id"] token = obj["auth"]["token"]["id"]
print "Token obtained:", token print "Token obtained:", token
# Use that token to call an OpenStack service (echo) # Use that token to call an OpenStack service (echo)
data = call_service(token) data = call_service(token)
print "Response received:", data print "Response received:", data
print print
# Use the valid token, but inject some headers # Use the valid token, but inject some headers
print "\033[91mInjecting some headers >:-/ \033[0m" print "\033[91mInjecting some headers >:-/ \033[0m"
data = hack_attempt(token) data = hack_attempt(token)
print "Response received:", data print "Response received:", data
print print
# Use bad token to call an OpenStack service (echo) # Use bad token to call an OpenStack service (echo)
print "\033[91mTrying with bad token...\033[0m" print "\033[91mTrying with bad token...\033[0m"
data = call_service("xxxx_invalid_token_xxxx") data = call_service("xxxx_invalid_token_xxxx")
print "Response received:", data print "Response received:", data
print print
#Supply bad credentials #Supply bad credentials
print "\033[91mTrying with bad credentials...\033[0m" print "\033[91mTrying with bad credentials...\033[0m"
auth = get_auth_token("joeuser", "wrongpass", "1") auth = get_auth_token("joeuser", "wrongpass", "1")

View File

@ -75,7 +75,8 @@ class AuthProtocol(object):
def __call__(self, env, start_response): def __call__(self, env, start_response):
def custom_start_response(status, headers): def custom_start_response(status, headers):
if self.delay_auth_decision: 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) return start_response(status, headers)
#Prep headers to proxy request to remote service #Prep headers to proxy request to remote service
@ -91,16 +92,16 @@ class AuthProtocol(object):
else: else:
# If the user isn't authenticated, we reject the request and # If the user isn't authenticated, we reject the request and
# return 401 indicating we need Basic Auth credentials. # return 401 indicating we need Basic Auth credentials.
return HTTPUnauthorized( return HTTPUnauthorized("Authentication required",
"Authentication required", [('WWW-Authenticate',
[('WWW-Authenticate', 'Basic realm="Use guest/guest"')] 'Basic realm="Use guest/guest"')]
)(env,start_response) )(env, start_response)
else: else:
# Claims were provided - validate them # Claims were provided - validate them
import base64 import base64
auth_header = env['HTTP_AUTHORIZATION'] auth_header = env['HTTP_AUTHORIZATION']
auth_type, encoded_creds = auth_header.split(None, 1) 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): if not self.validateCreds(user, password):
#Claims were rejected #Claims were rejected
if not self.delay_auth_decision: if not self.delay_auth_decision:
@ -125,13 +126,12 @@ class AuthProtocol(object):
_decorate_request_headers('X_GROUP', 'Blank', _decorate_request_headers('X_GROUP', 'Blank',
proxy_headers, env) proxy_headers, env)
#Auth processed, headers added now decide how to pass on the call #Auth processed, headers added now decide how to pass on the call
if self.app: if self.app:
# Pass to downstream WSGI component # Pass to downstream WSGI component
env['HTTP_AUTHORIZATION'] = "Basic %s" % self.service_pass env['HTTP_AUTHORIZATION'] = "Basic %s" % self.service_pass
return self.app(env, custom_start_response) return self.app(env, custom_start_response)
proxy_headers['AUTHORIZATION'] = "Basic %s" % self.service_pass proxy_headers['AUTHORIZATION'] = "Basic %s" % self.service_pass
# We are forwarding to a remote service (no downstream WSGI app) # We are forwarding to a remote service (no downstream WSGI app)
req = Request(proxy_headers) req = Request(proxy_headers)
@ -146,9 +146,6 @@ class AuthProtocol(object):
# we are rewriting the headers now # we are rewriting the headers now
return Response(status=resp.status, body=data)(env, start_response) return Response(status=resp.status, body=data)(env, start_response)
def validateCreds(self, username, password): def validateCreds(self, username, password):
#stub for password validation. #stub for password validation.
import ConfigParser import ConfigParser
@ -163,6 +160,7 @@ class AuthProtocol(object):
return True return True
return False return False
def filter_factory(global_conf, ** local_conf): def filter_factory(global_conf, ** local_conf):
"""Returns a WSGI filter app for use with paste.deploy.""" """Returns a WSGI filter app for use with paste.deploy."""
conf = global_conf.copy() conf = global_conf.copy()

View File

@ -117,14 +117,13 @@ class AuthProtocol(object):
self._init_protocol_common(app, conf) # Applies to all protocols self._init_protocol_common(app, conf) # Applies to all protocols
self._init_protocol(app, conf) # Specific to this protocol self._init_protocol(app, conf) # Specific to this protocol
def __call__(self, env, start_response): def __call__(self, env, start_response):
""" Handle incoming request. Authenticate. And send downstream. """ """ Handle incoming request. Authenticate. And send downstream. """
self.start_response = start_response self.start_response = start_response
self.env = env 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() self.proxy_headers = env.copy()
for header in self.proxy_headers.iterkeys(): for header in self.proxy_headers.iterkeys():
if header[0:5] == 'HTTP_': if header[0:5] == 'HTTP_':
@ -158,23 +157,21 @@ class AuthProtocol(object):
#Collect information about valid claims #Collect information about valid claims
if valid: if valid:
verified_claims = self._expound_claims() claims = self._expound_claims()
if verified_claims: if claims:
# TODO(Ziad): add additional details we may need, # TODO(Ziad): add additional details we may need,
# like tenant and group info # like tenant and group info
self._decorate_request('X_AUTHORIZATION', self._decorate_request('X_AUTHORIZATION',
"Proxy %s" % verified_claims['user']) "Proxy %s" % claims['user'])
self._decorate_request('X_TENANT', self._decorate_request('X_TENANT',
verified_claims['tenant']) claims['tenant'])
self._decorate_request('X_GROUP', self._decorate_request('X_GROUP',
verified_claims['group']) claims['group'])
self.expanded = True self.expanded = True
#Send request downstream #Send request downstream
return self._forward_request() return self._forward_request()
def get_admin_auth_token(self, username, password, tenant): def get_admin_auth_token(self, username, password, tenant):
""" """
This function gets an admin auth token to be used by this service to This function gets an admin auth token to be used by this service to
@ -198,25 +195,25 @@ class AuthProtocol(object):
return claims return claims
def _reject_request(self): def _reject_request(self):
# Redirect client to auth server # Redirect client to auth server
return HTTPUseProxy(location=self.auth_location)(self.env, return HTTPUseProxy(location=self.auth_location)(self.env,
self.start_response) self.start_response)
def _reject_claims(self): def _reject_claims(self):
# Client sent bad claims # Client sent bad claims
return HTTPUnauthorized()(self.env, return HTTPUnauthorized()(self.env,
self.start_response) self.start_response)
def _validate_claims(self, claims): def _validate_claims(self, claims):
"""Validate claims, and provide identity information isf applicable """ """Validate claims, and provide identity information isf 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
#TODO: Need to properly implement this, where to store creds #TODO: Need to properly implement this, where to store creds
# for now using token from ini # for now using token from ini
#auth = self.get_admin_auth_token("admin", "secrete", "1") #auth = self.get_admin_auth_token("admin", "secrete", "1")
#admin_token = json.loads(auth)["auth"]["token"]["id"] #admin_token = json.loads(auth)["auth"]["token"]["id"]
# Step 2: validate the user's token with the auth service # Step 2: validate the user's token with the auth service
# since this is a priviledged op,m we need to auth ourselves # since this is a priviledged op,m we need to auth ourselves
# by using an admin token # by using an admin token
@ -268,10 +265,11 @@ class AuthProtocol(object):
first_group = token_info['auth']['user']['groups']['group'][0] first_group = token_info['auth']['user']['groups']['group'][0]
verified_claims = {'user': token_info['auth']['user']['username'], verified_claims = {'user': token_info['auth']['user']['username'],
'tenant': token_info['auth']['user']['tenantId'], '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 return verified_claims
def _decorate_request(self, index, value): def _decorate_request(self, index, value):
self.proxy_headers[index] = value self.proxy_headers[index] = value
self.env["HTTP_%s" % index] = value self.env["HTTP_%s" % index] = value
@ -282,15 +280,18 @@ class AuthProtocol(object):
#now decide how to pass on the call #now decide how to pass on the call
if self.app: if self.app:
# Pass to downstream WSGI component # 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: else:
# We are forwarding to a remote service (no downstream WSGI app) # We are forwarding to a remote service (no downstream WSGI app)
req = Request(self.proxy_headers) req = Request(self.proxy_headers)
parsed = urlparse(req.url) parsed = urlparse(req.url)
conn = http_connect(self.service_host, self.service_port, \ conn = http_connect(self.service_host,
req.method, parsed.path, \ self.service_port,
self.proxy_headers,\ req.method,
ssl=(self.service_protocol == 'https')) parsed.path,
self.proxy_headers,
ssl=(self.service_protocol == 'https'))
resp = conn.getresponse() resp = conn.getresponse()
data = resp.read() data = resp.read()
#TODO: use a more sophisticated proxy #TODO: use a more sophisticated proxy