diff --git a/keystoneclient/middleware/s3_token.py b/keystoneclient/middleware/s3_token.py index f35b1545e..59dd331b5 100644 --- a/keystoneclient/middleware/s3_token.py +++ b/keystoneclient/middleware/s3_token.py @@ -33,11 +33,12 @@ This WSGI component: """ -import httplib import logging import urllib import webob +import requests + from keystoneclient.openstack.common import jsonutils @@ -105,16 +106,26 @@ class S3Token(object): self.logger.debug('Starting the %s component' % PROTOCOL_NAME) self.reseller_prefix = conf.get('reseller_prefix', 'AUTH_') # 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)) - self.auth_protocol = conf.get('auth_protocol', 'https') - if self.auth_protocol == 'http': - self.http_client_class = httplib.HTTPConnection - else: - self.http_client_class = httplib.HTTPSConnection + + auth_host = conf.get('auth_host') + auth_port = int(conf.get('auth_port', 35357)) + auth_protocol = conf.get('auth_protocol', 'https') + + self.request_uri = '%s://%s:%s' % (auth_protocol, auth_host, auth_port) + # SSL - self.cert_file = conf.get('certfile') - self.key_file = conf.get('keyfile') + insecure = conf.get('insecure', False) + 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): error_table = { @@ -132,33 +143,22 @@ class S3Token(object): def _json_request(self, creds_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: - conn.request('POST', '/v2.0/s3tokens', - body=creds_json, - headers=headers) - response = conn.getresponse() - output = response.read() - except Exception as e: + response = requests.post('%s/v2.0/s3tokens' % self.request_uri, + headers=headers, data=creds_json, + verify=self.verify) + except requests.exceptions.RequestException as e: self.logger.info('HTTP connection exception: %s' % e) resp = self.deny_request('InvalidURI') 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' % - (response.status, response.reason)) + (response.status_code, response.reason)) resp = self.deny_request('AccessDenied') raise ServiceError(resp) - return (response, output) + return response def __call__(self, environ, start_response): """Handle incoming request. authenticate and send downstream.""" @@ -225,23 +225,23 @@ class S3Token(object): # identified and not doing a second query and just # pass it through to swiftauth in this case. try: - resp, output = self._json_request(creds_json) + resp = self._json_request(creds_json) except ServiceError as e: resp = e.args[0] 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) self.logger.debug('Keystone Reply: Status: %d, Output: %s' % ( - resp.status, output)) + resp.status_code, resp.content)) try: - identity_info = jsonutils.loads(output) + identity_info = resp.json() token_id = str(identity_info['access']['token']['id']) tenant = identity_info['access']['token']['tenant'] except (ValueError, KeyError): 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) req.headers['X-Auth-Token'] = token_id diff --git a/keystoneclient/tests/test_s3_token_middleware.py b/keystoneclient/tests/test_s3_token_middleware.py index 1f550d060..7362f84eb 100644 --- a/keystoneclient/tests/test_s3_token_middleware.py +++ b/keystoneclient/tests/test_s3_token_middleware.py @@ -16,6 +16,7 @@ import httpretty import mock +import requests import testtools import webob @@ -120,6 +121,24 @@ class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase): path = req.environ['PATH_INFO'] 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): def setUp(self):