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())
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
    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
Beispiel #6
0
    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