def setUp(self): super(DbApiTestCase, self).setUp() engine = session.get_engine() engine.dispose() conn = engine.connect() conn.connection.executescript(self.DB_SCHEMA) self.context = ec2_context.RequestContext(fakes.ID_OS_USER, fakes.ID_OS_PROJECT) self.other_context = ec2_context.RequestContext( fakes.random_os_id(), fakes.random_os_id())
def test_get_os_admin_context(self, password_plugin): imp.reload(ec2_context) # NOTE(ft): initialize a regular context to populate oslo_context's # local storage to prevent admin context to populate it. # Used to implicitly validate overwrite=False argument of the call # RequestContext constructor from inside get_os_admin_context if not context.get_current(): ec2_context.RequestContext(None, None) ctx = ec2_context.get_os_admin_context() conf = cfg.CONF password_plugin.assert_called_once_with( username=conf.admin_user, password=conf.admin_password, tenant_name=conf.admin_tenant_name, project_name=conf.admin_tenant_name, auth_url=conf.keystone_url) self.assertIsNone(ctx.user_id) self.assertIsNone(ctx.project_id) self.assertIsNone(ctx.auth_token) self.assertEqual([], ctx.service_catalog) self.assertTrue(ctx.is_os_admin) self.assertIsNotNone(ctx.session) self.assertIsNotNone(ctx.session.auth) self.assertNotEqual(context.get_current(), ctx) password_plugin.reset_mock() ec2_context.get_os_admin_context() self.assertFalse(password_plugin.called)
def test_get_os_admin_context(self, session, auth): conf = config_fixture.Config() clients._admin_session = None conf.config(auth_type='fake', group=GROUP_AUTHTOKEN) imp.reload(ec2_context) # NOTE(ft): initialize a regular context to populate oslo_context's # local storage to prevent admin context to populate it. # Used to implicitly validate overwrite=False argument of the call # RequestContext constructor from inside get_os_admin_context if not context.get_current(): ec2_context.RequestContext(None, None) ctx = ec2_context.get_os_admin_context() conf = cfg.CONF auth.assert_called_once_with(conf, GROUP_AUTHTOKEN) auth_plugin = auth.return_value session.assert_called_once_with(conf, GROUP_AUTHTOKEN, auth=auth_plugin) self.assertIsNone(ctx.user_id) self.assertIsNone(ctx.project_id) self.assertIsNone(ctx.auth_token) self.assertEqual([], ctx.service_catalog) self.assertTrue(ctx.is_os_admin) self.assertIsNotNone(ctx.session) self.assertIsNotNone(ctx.session.auth) self.assertNotEqual(context.get_current(), ctx) session.reset_mock() ec2_context.get_os_admin_context() self.assertFalse(session.called)
def __call__(self, req): request_id = common_context.generate_request_id() # NOTE(alevine) We need to calculate the hash here because # subsequent access to request modifies the req.body so the hash # calculation will yield invalid results. body_hash = hashlib.sha256(req.body).hexdigest() signature = self._get_signature(req) if not signature: msg = _("Signature not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) access = self._get_access(req) if not access: msg = _("Access key not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) if 'X-Amz-Signature' in req.params or 'Authorization' in req.headers: params = {} else: # Make a copy of args for authentication and signature verification params = dict(req.params) # Not part of authentication args params.pop('Signature', None) cred_dict = { 'access': access, 'signature': signature, 'host': req.host, 'verb': req.method, 'path': req.path, 'params': params, # python3 takes only keys for json from headers object 'headers': {k: req.headers[k] for k in req.headers}, 'body_hash': body_hash } token_url = CONF.keystone_ec2_tokens_url if "ec2" in token_url: creds = {'ec2Credentials': cred_dict} else: creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}} creds_json = jsonutils.dumps(creds) headers = {'Content-Type': 'application/json'} params = {'data': creds_json, 'headers': headers} clients.update_request_params_with_ssl(params) response = requests.request('POST', token_url, **params) status_code = response.status_code if status_code != 200: msg = response.reason return faults.ec2_error_response(request_id, "AuthFailure", msg, status=status_code) try: auth_ref = keystone_access.AccessInfo.factory(resp=response, body=response.json()) except (NotImplementedError, KeyError): LOG.exception("Keystone failure") msg = _("Failure communicating with keystone") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) auth = keystone_identity_access.AccessInfoPlugin(auth_ref) params = {'auth': auth} clients.update_request_params_with_ssl(params) session = keystone_session.Session(**params) remote_address = req.remote_addr if CONF.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) ctxt = context.RequestContext(auth_ref.user_id, auth_ref.project_id, request_id=request_id, user_name=auth_ref.username, project_name=auth_ref.project_name, remote_address=remote_address, session=session, api_version=req.params.get('Version')) req.environ['ec2api.context'] = ctxt return self.application
def __call__(self, req): metric_logger.startTime() request_id = context.generate_request_id() # NOTE(alevine) We need to calculate the hash here because # subsequent access to request modifies the req.body so the hash # calculation will yield invalid results. body_hash = hashlib.sha256(req.body).hexdigest() # Verify the version is as expected from config file req_version = req.params.get('Version') if not req_version or req_version not in CONF.supported_api_versions: _msg = ("Unsupported Version used in the request.") return faults.ec2_error_response(request_id, 'BadRequest', _msg, status=400) if CONF.enable_policy_engine: try: rsrc_action_list = self.policy_engine.handle_params( dict(req.params)) except Exception as e: exc_type, exc_obj, exc_tb = sys.exc_info() LOG.exception(str(e)) if isinstance(exc_obj, webob.exc.HTTPUnauthorized): return faults.ec2_error_response(request_id, 'AuthFailure', str(e), status=403) elif isinstance(exc_obj, webob.exc.HTTPInternalServerError): return faults.ec2_error_response(request_id, 'InternalError', str(e), status=500) else: return faults.ec2_error_response(request_id, 'BadRequest', str(e), status=400) keystone_validation_url = "" data = {} headers = {'Content-Type': 'application/json'} auth_token = self._get_auth_token(req) if auth_token: headers['X-Auth-Token'] = auth_token data['action_resource_list'] = rsrc_action_list data = jsonutils.dumps(data) keystone_validation_url = CONF.keystone_token_url else: signature = self._get_signature(req) if not signature: msg = _("Signature not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) access = self._get_access(req) if not access: msg = _("Access key not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) if 'X-Amz-Signature' in req.params or 'Authorization' in req.headers: params = {} else: # Make a copy of args for authentication and signature verification params = dict(req.params) # Not part of authentication args params.pop('Signature', None) cred_dict = { 'access': access, 'signature': signature, 'host': req.host, 'verb': req.method, 'path': req.path, 'params': params, 'headers': req.headers, 'body_hash': body_hash } if CONF.enable_policy_engine: cred_dict['action_resource_list'] = rsrc_action_list keystone_validation_url = CONF.keystone_sig_url if "ec2" in keystone_validation_url: creds = {'ec2Credentials': cred_dict} else: creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}} data = jsonutils.dumps(creds) verify = CONF.ssl_ca_file or not CONF.ssl_insecure response = requests.request('POST', keystone_validation_url, verify=verify, data=data, headers=headers) status_code = response.status_code if status_code != 200: msg = response.text return faults.ec2_error_response(request_id, "AuthFailure", msg, status=status_code) result = response.json() try: user_id = result.get('user_id') project_id = result.get('account_id') if auth_token: token_id = auth_token else: token_id = result.get('token_id') if not user_id or not project_id: raise KeyError except (AttributeError, KeyError): LOG.exception(_("Keystone failure")) msg = _("Failure communicating with keystone") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) remote_address = req.remote_addr if CONF.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) # Fill in default values user_name = project_name = 'default' roles = catalog = [] ctxt = context.RequestContext(user_id, project_id, user_name=user_name, project_name=project_name, roles=roles, auth_token=token_id, remote_address=remote_address, service_catalog=catalog, api_version=req.params.get('Version')) req.environ['ec2api.context'] = ctxt compute_request_id = ctxt.request_id appendRequestDict = {'requestid': compute_request_id} actionName = ec2utils.camelcase_to_underscore(req.params.get('Action')) actionName = actionName + "-auth" metric_logger.reportTime(actionName, addOnInfoPairs=appendRequestDict) return self.application
def __call__(self, req): request_id = context.generate_request_id() # NOTE(alevine) We need to calculate the hash here because # subsequent access to request modifies the req.body so the hash # calculation will yield invalid results. body_hash = hashlib.sha256(req.body).hexdigest() signature = self._get_signature(req) if not signature: msg = _("Signature not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) access = self._get_access(req) if not access: msg = _("Access key not provided") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) if 'X-Amz-Signature' in req.params or 'Authorization' in req.headers: params = {} else: # Make a copy of args for authentication and signature verification params = dict(req.params) # Not part of authentication args params.pop('Signature', None) cred_dict = { 'access': access, 'signature': signature, 'host': req.host, 'verb': req.method, 'path': req.path, 'params': params, 'headers': req.headers, 'body_hash': body_hash } token_url = CONF.keystone_ec2_tokens_url if "ec2" in token_url: creds = {'ec2Credentials': cred_dict} else: creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}} creds_json = jsonutils.dumps(creds) headers = {'Content-Type': 'application/json'} response = requests.request('POST', token_url, data=creds_json, headers=headers) status_code = response.status_code if status_code != 200: msg = response.reason return faults.ec2_error_response(request_id, "AuthFailure", msg, status=status_code) result = response.json() try: if 'token' in result: # NOTE(andrey-mp): response from keystone v3 token_id = response.headers['x-subject-token'] user_id = result['token']['user']['id'] project_id = result['token']['project']['id'] user_name = result['token']['user'].get('name') project_name = result['token']['project'].get('name') catalog = result['token']['catalog'] else: token_id = result['access']['token']['id'] user_id = result['access']['user']['id'] project_id = result['access']['token']['tenant']['id'] user_name = result['access']['user'].get('name') project_name = result['access']['token']['tenant'].get('name') catalog = result['access']['serviceCatalog'] except (AttributeError, KeyError): LOG.exception(_("Keystone failure")) msg = _("Failure communicating with keystone") return faults.ec2_error_response(request_id, "AuthFailure", msg, status=400) remote_address = req.remote_addr if CONF.use_forwarded_for: remote_address = req.headers.get('X-Forwarded-For', remote_address) ctxt = context.RequestContext(user_id, project_id, request_id=request_id, user_name=user_name, project_name=project_name, auth_token=token_id, remote_address=remote_address, service_catalog=catalog, api_version=req.params.get('Version')) req.environ['ec2api.context'] = ctxt return self.application