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.
"""
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:

View File

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

View File

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

View File

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