Merge "Use requests library in S3 middleware"

This commit is contained in:
Jenkins
2014-02-06 08:15:00 +00:00
committed by Gerrit Code Review
2 changed files with 52 additions and 33 deletions

View File

@@ -33,11 +33,12 @@ This WSGI component:
""" """
import httplib
import logging import logging
import urllib import urllib
import webob import webob
import requests
from keystoneclient.openstack.common import jsonutils from keystoneclient.openstack.common import jsonutils
@@ -105,16 +106,26 @@ class S3Token(object):
self.logger.debug('Starting the %s component' % PROTOCOL_NAME) self.logger.debug('Starting the %s component' % PROTOCOL_NAME)
self.reseller_prefix = conf.get('reseller_prefix', 'AUTH_') self.reseller_prefix = conf.get('reseller_prefix', 'AUTH_')
# where to find the auth service (we use this to validate tokens) # where to find the auth service (we use this to validate tokens)
self.auth_host = conf.get('auth_host')
self.auth_port = int(conf.get('auth_port', 35357)) auth_host = conf.get('auth_host')
self.auth_protocol = conf.get('auth_protocol', 'https') auth_port = int(conf.get('auth_port', 35357))
if self.auth_protocol == 'http': auth_protocol = conf.get('auth_protocol', 'https')
self.http_client_class = httplib.HTTPConnection
else: self.request_uri = '%s://%s:%s' % (auth_protocol, auth_host, auth_port)
self.http_client_class = httplib.HTTPSConnection
# SSL # SSL
self.cert_file = conf.get('certfile') insecure = conf.get('insecure', False)
self.key_file = conf.get('keyfile') cert_file = conf.get('certfile')
key_file = conf.get('keyfile')
if insecure:
self.verify = False
elif cert_file and key_file:
self.verify = (cert_file, key_file)
elif cert_file:
self.verify = cert_file
else:
self.verify = None
def deny_request(self, code): def deny_request(self, code):
error_table = { error_table = {
@@ -132,33 +143,22 @@ class S3Token(object):
def _json_request(self, creds_json): def _json_request(self, creds_json):
headers = {'Content-Type': 'application/json'} headers = {'Content-Type': 'application/json'}
if self.auth_protocol == 'http':
conn = self.http_client_class(self.auth_host, self.auth_port)
else:
conn = self.http_client_class(self.auth_host,
self.auth_port,
self.key_file,
self.cert_file)
try: try:
conn.request('POST', '/v2.0/s3tokens', response = requests.post('%s/v2.0/s3tokens' % self.request_uri,
body=creds_json, headers=headers, data=creds_json,
headers=headers) verify=self.verify)
response = conn.getresponse() except requests.exceptions.RequestException as e:
output = response.read()
except Exception as e:
self.logger.info('HTTP connection exception: %s' % e) self.logger.info('HTTP connection exception: %s' % e)
resp = self.deny_request('InvalidURI') resp = self.deny_request('InvalidURI')
raise ServiceError(resp) raise ServiceError(resp)
finally:
conn.close()
if response.status < 200 or response.status >= 300: if response.status_code < 200 or response.status_code >= 300:
self.logger.debug('Keystone reply error: status=%s reason=%s' % self.logger.debug('Keystone reply error: status=%s reason=%s' %
(response.status, response.reason)) (response.status_code, response.reason))
resp = self.deny_request('AccessDenied') resp = self.deny_request('AccessDenied')
raise ServiceError(resp) raise ServiceError(resp)
return (response, output) return response
def __call__(self, environ, start_response): def __call__(self, environ, start_response):
"""Handle incoming request. authenticate and send downstream.""" """Handle incoming request. authenticate and send downstream."""
@@ -225,23 +225,23 @@ class S3Token(object):
# identified and not doing a second query and just # identified and not doing a second query and just
# pass it through to swiftauth in this case. # pass it through to swiftauth in this case.
try: try:
resp, output = self._json_request(creds_json) resp = self._json_request(creds_json)
except ServiceError as e: except ServiceError as e:
resp = e.args[0] resp = e.args[0]
msg = 'Received error, exiting middleware with error: %s' msg = 'Received error, exiting middleware with error: %s'
self.logger.debug(msg % (resp.status)) self.logger.debug(msg % (resp.status_code))
return resp(environ, start_response) return resp(environ, start_response)
self.logger.debug('Keystone Reply: Status: %d, Output: %s' % ( self.logger.debug('Keystone Reply: Status: %d, Output: %s' % (
resp.status, output)) resp.status_code, resp.content))
try: try:
identity_info = jsonutils.loads(output) identity_info = resp.json()
token_id = str(identity_info['access']['token']['id']) token_id = str(identity_info['access']['token']['id'])
tenant = identity_info['access']['token']['tenant'] tenant = identity_info['access']['token']['tenant']
except (ValueError, KeyError): except (ValueError, KeyError):
error = 'Error on keystone reply: %d %s' error = 'Error on keystone reply: %d %s'
self.logger.debug(error % (resp.status, str(output))) self.logger.debug(error % (resp.status_code, str(resp.content)))
return self.deny_request('InvalidURI')(environ, start_response) return self.deny_request('InvalidURI')(environ, start_response)
req.headers['X-Auth-Token'] = token_id req.headers['X-Auth-Token'] = token_id

View File

@@ -16,6 +16,7 @@
import httpretty import httpretty
import mock import mock
import requests
import testtools import testtools
import webob import webob
@@ -120,6 +121,24 @@ class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase):
path = req.environ['PATH_INFO'] path = req.environ['PATH_INFO']
self.assertTrue(path.startswith('/v1/AUTH_FORCED_TENANT_ID')) self.assertTrue(path.startswith('/v1/AUTH_FORCED_TENANT_ID'))
@mock.patch.object(requests, 'post')
def test_insecure(self, MOCK_REQUEST):
self.middleware = (
s3_token.filter_factory({'insecure': True})(FakeApp()))
MOCK_REQUEST.return_value = utils.TestResponse({
'status_code': 201,
'text': jsonutils.dumps(GOOD_RESPONSE)})
req = webob.Request.blank('/v1/AUTH_cfa/c/o')
req.headers['Authorization'] = 'access:signature'
req.headers['X-Storage-Token'] = 'token'
req.get_response(self.middleware)
self.assertTrue(MOCK_REQUEST.called)
mock_args, mock_kwargs = MOCK_REQUEST.call_args
self.assertIs(mock_kwargs['verify'], False)
class S3TokenMiddlewareTestBad(S3TokenMiddlewareTestBase): class S3TokenMiddlewareTestBad(S3TokenMiddlewareTestBase):
def setUp(self): def setUp(self):