Ejemplo n.º 1
0
    def __init__(self, user_id, project_id, is_admin=None, read_deleted="no",
                 roles=None, remote_address=None, timestamp=None,
                 request_id=None, auth_token=None, overwrite=True,
                 quota_class=None, user_name=None, project_name=None,
                 service_catalog=None, instance_lock_checked=False,
                 user_auth_plugin=None, **kwargs):
        """:param read_deleted: 'no' indicates deleted records are hidden,
                'yes' indicates deleted records are visible,
                'only' indicates that *only* deleted records are visible.

           :param overwrite: Set to False to ensure that the greenthread local
                copy of the index is not overwritten.

           :param user_auth_plugin: The auth plugin for the current request's
                authentication data.

           :param kwargs: Extra arguments that might be present, but we ignore
                because they possibly came in from older rpc messages.
        """
        if kwargs:
            LOG.warning(_LW('Arguments dropped when creating context: %s') %
                        str(kwargs))

        self.user_id = user_id
        self.project_id = project_id
        self.roles = roles or []
        self.read_deleted = read_deleted
        self.remote_address = remote_address
        if not timestamp:
            timestamp = timeutils.utcnow()
        if isinstance(timestamp, six.string_types):
            timestamp = timeutils.parse_strtime(timestamp)
        self.timestamp = timestamp
        if not request_id:
            request_id = context.generate_request_id()
        self.request_id = request_id
        self.auth_token = auth_token

        if service_catalog:
            # Only include required parts of service_catalog
            self.service_catalog = [s for s in service_catalog
                if s.get('type') in ('volume', 'volumev2', 'key-manager')]
        else:
            # if list is empty or none
            self.service_catalog = []

        self.instance_lock_checked = instance_lock_checked

        # NOTE(markmc): this attribute is currently only used by the
        # rs_limits turnstile pre-processor.
        # See https://lists.launchpad.net/openstack/msg12200.html
        self.quota_class = quota_class
        self.user_name = user_name
        self.project_name = project_name
        self.is_admin = is_admin
        self.user_auth_plugin = user_auth_plugin
        if self.is_admin is None:
            self.is_admin = policy.check_is_admin(self)
        if overwrite or not hasattr(local.store, 'context'):
            self.update_store()
Ejemplo n.º 2
0
    def __init__(self,
                 user_id,
                 project_id,
                 is_admin=None,
                 read_deleted="no",
                 roles=None,
                 remote_address=None,
                 timestamp=None,
                 request_id=None,
                 auth_token=None,
                 overwrite=True,
                 quota_class=None,
                 service_catalog=None,
                 **kwargs):
        """Initialize RequestContext.

        :param read_deleted: 'no' indicates deleted records are hidden, 'yes'
            indicates deleted records are visible, 'only' indicates that
            *only* deleted records are visible.

        :param overwrite: Set to False to ensure that the greenthread local
            copy of the index is not overwritten.

        :param kwargs: Extra arguments that might be present, but we ignore
            because they possibly came in from older rpc messages.
        """
        if kwargs:
            LOG.warn(_LW('Arguments dropped when creating context: %s'),
                     str(kwargs))

        self.user_id = user_id
        self.project_id = project_id
        self.roles = roles or []
        self.is_admin = is_admin
        if self.is_admin is None:
            self.is_admin = policy.check_is_admin(self.roles)
        elif self.is_admin and 'admin' not in self.roles:
            self.roles.append('admin')
        self.read_deleted = read_deleted
        self.remote_address = remote_address
        if not timestamp:
            timestamp = timeutils.utcnow()
        if isinstance(timestamp, six.string_types):
            timestamp = timeutils.parse_strtime(timestamp)
        self.timestamp = timestamp
        if service_catalog:
            self.service_catalog = [
                s for s in service_catalog
                if s.get('type') in ('compute', 'volume')
            ]
        else:
            self.service_catalog = []

        if not request_id:
            request_id = common_context.generate_request_id()
        self.request_id = request_id
        self.auth_token = auth_token
        self.quota_class = quota_class
        if overwrite or not common_context.get_current():
            self.update_store()
Ejemplo n.º 3
0
 def __call__(self, req):
     req_id = context.generate_request_id()
     req.environ[ENV_REQUEST_ID] = req_id
     response = req.get_response(self.application)
     if HTTP_RESP_HEADER_REQUEST_ID not in response.headers:
         response.headers.add(HTTP_RESP_HEADER_REQUEST_ID, req_id)
     return response
Ejemplo n.º 4
0
 def __call__(self, req):
     req_id = context.generate_request_id()
     req.environ[ENV_REQUEST_ID] = req_id
     response = req.get_response(self.application)
     if HTTP_RESP_HEADER_REQUEST_ID not in response.headers:
         response.headers.add(HTTP_RESP_HEADER_REQUEST_ID, req_id)
     return response
Ejemplo n.º 5
0
    def notify(action,
               alarm_id,
               alarm_name,
               previous,
               current,
               reason,
               reason_data,
               headers=None):
        headers = headers or {}
        if not headers.get('x-openstack-request-id'):
            headers['x-openstack-request-id'] = context.generate_request_id()

        LOG.info(
            _("Notifying alarm %(alarm_name)s %(alarm_id)s from "
              "%(previous)s to %(current)s with action %(action)s because "
              "%(reason)s. request-id: %(request_id)s ") %
            ({
                'alarm_name': alarm_name,
                'alarm_id': alarm_id,
                'previous': previous,
                'current': current,
                'action': action,
                'reason': reason,
                'request_id': headers['x-openstack-request-id']
            }))
        body = {
            'alarm_name': alarm_name,
            'alarm_id': alarm_id,
            'previous': previous,
            'current': current,
            'reason': reason,
            'reason_data': reason_data
        }
        headers['content-type'] = 'application/json'
        kwargs = {'data': jsonutils.dumps(body), 'headers': headers}

        if action.scheme == 'https':
            default_verify = int(cfg.CONF.alarm.rest_notifier_ssl_verify)
            options = urlparse.parse_qs(action.query)
            verify = bool(
                int(
                    options.get('ceilometer-alarm-ssl-verify',
                                [default_verify])[-1]))
            kwargs['verify'] = verify

            cert = cfg.CONF.alarm.rest_notifier_certificate_file
            key = cfg.CONF.alarm.rest_notifier_certificate_key
            if cert:
                kwargs['cert'] = (cert, key) if key else cert

        # FIXME(rhonjo): Retries are automatically done by urllib3 in requests
        # library. However, there's no interval between retries in urllib3
        # implementation. It will be better to put some interval between
        # retries (future work).
        max_retries = cfg.CONF.alarm.rest_notifier_max_retries
        session = requests.Session()
        session.mount(action.geturl(),
                      requests.adapters.HTTPAdapter(max_retries=max_retries))
        eventlet.spawn_n(session.post, action.geturl(), **kwargs)
Ejemplo n.º 6
0
 def _get_nova_client(self):
     global_id = common_context.generate_request_id()
     return nova_client.Client(
         api_versions.APIVersion(NOVA_API_VERSION),
         session=self.session,
         region_name=cfg.CONF.nova.region_name,
         endpoint_type=cfg.CONF.nova.endpoint_type,
         extensions=self.extensions,
         global_request_id=global_id)
Ejemplo n.º 7
0
 def _get_nova_client(self):
     global_id = common_context.generate_request_id()
     return nova_client.Client(api_versions.APIVersion(NOVA_API_VERSION),
                               session=self.session,
                               region_name=cfg.CONF.nova.region_name,
                               endpoint_type=cfg.CONF.nova.endpoint_type,
                               extensions=self.extensions,
                               connect_retries=cfg.CONF.http_retries,
                               global_request_id=global_id)
Ejemplo n.º 8
0
    def __init__(self, user_id, project_id, is_admin=None, read_deleted="no",
                 roles=None, remote_address=None, timestamp=None,
                 request_id=None, auth_token=None, overwrite=True,
                 quota_class=None, service_catalog=None, **kwargs):
        """Initialize RequestContext.

        :param read_deleted: 'no' indicates deleted records are hidden, 'yes'
            indicates deleted records are visible, 'only' indicates that
            *only* deleted records are visible.

        :param overwrite: Set to False to ensure that the greenthread local
            copy of the index is not overwritten.

        :param kwargs: Extra arguments that might be present, but we ignore
            because they possibly came in from older rpc messages.
        """
        user = kwargs.pop('user', None)
        tenant = kwargs.pop('tenant', None)
        if kwargs:
            LOG.warn(_LW('Arguments dropped when creating context: %s'),
                     str(kwargs))

        self.user_id = user_id or user
        self.project_id = project_id or tenant
        self.roles = roles or []
        self.is_admin = is_admin
        if self.is_admin is None:
            self.is_admin = policy.check_is_admin(self.roles)
        elif self.is_admin and 'admin' not in self.roles:
            self.roles.append('admin')
        self.read_deleted = read_deleted
        self.remote_address = remote_address
        if not timestamp:
            timestamp = timeutils.utcnow()
        if isinstance(timestamp, six.string_types):
            timestamp = timeutils.parse_strtime(timestamp)
        self.timestamp = timestamp
        if service_catalog:
            self.service_catalog = [s for s in service_catalog
                                    if s.get('type') in ('compute', 'volume')]
        else:
            self.service_catalog = []

        if not request_id:
            request_id = common_context.generate_request_id()
        self.request_id = request_id
        self.auth_token = auth_token
        self.quota_class = quota_class
        if overwrite or not common_context.get_current():
            self.update_store()
Ejemplo n.º 9
0
    def __call__(self, req):
        self.set_global_req_id(req)

        req_id = context.generate_request_id()
        req.environ[ENV_REQUEST_ID] = req_id
        response = req.get_response(self.application)

        return_headers = [HTTP_RESP_HEADER_REQUEST_ID]
        return_headers.extend(self.compat_headers)

        for header in return_headers:
            if header not in response.headers:
                response.headers.add(header, req_id)
        return response
Ejemplo n.º 10
0
    def _execute(self, invoke):
        class Fake(object):
            pass
        fake_ec2_request = Fake()
        fake_ec2_request.invoke = invoke

        fake_wsgi_request = Fake()

        fake_wsgi_request.environ = {
            'ec2api.context': mock.Mock(
                request_id=context.generate_request_id()),
            'ec2.request': fake_ec2_request,
        }
        return self.executor(fake_wsgi_request)
    def test_generate_request_id(self):
        @webob.dec.wsgify
        def application(req):
            return req.environ[ENV_REQUEST_ID]

        app = compute_req_id.ComputeReqIdMiddleware(application)
        req = webob.Request.blank('/test')
        req_id = context.generate_request_id()
        req.environ[ENV_REQUEST_ID] = req_id
        res = req.get_response(app)

        res_id = res.headers.get(compute_req_id.HTTP_RESP_HEADER_REQUEST_ID)
        self.assertThat(res_id, matchers.StartsWith('req-'))
        self.assertEqual(res_id.encode('utf-8'), res.body)
Ejemplo n.º 12
0
    def test_generate_request_id(self):
        @webob.dec.wsgify
        def application(req):
            return req.environ[compute_req_id.ENV_REQUEST_ID]

        app = compute_req_id.ComputeReqIdMiddleware(application)
        req = webob.Request.blank('/test')
        req_id = context.generate_request_id()
        req.environ[compute_req_id.ENV_REQUEST_ID] = req_id
        res = req.get_response(app)

        res_id = res.headers.get(compute_req_id.HTTP_RESP_HEADER_REQUEST_ID)
        self.assertThat(res_id, matchers.StartsWith('req-'))
        self.assertEqual(res_id, res.body)
Ejemplo n.º 13
0
    def setUp(self):
        super(ApiInitTestCase, self).setUp()
        self.controller = self.mock(
            'ec2api.api.cloud.VpcCloudController').return_value
        self.fake_context = mock.NonCallableMock(
            request_id=context.generate_request_id())

        ec2_request = apirequest.APIRequest('FakeAction', 'fake_v1',
                                            {'Param': 'fake_param'})
        self.environ = {'REQUEST_METHOD': 'FAKE',
                        'ec2.request': ec2_request,
                        'ec2api.context': self.fake_context}
        self.request = wsgi.Request(self.environ)
        self.application = api.Executor()
Ejemplo n.º 14
0
    def setUp(self):
        super(ApiInitTestCase, self).setUp()
        self.controller = self.mock(
            'ec2api.api.cloud.VpcCloudController').return_value
        self.fake_context = mock.NonCallableMock(
            request_id=context.generate_request_id())

        ec2_request = apirequest.APIRequest('FakeAction', 'fake_v1',
                                            {'Param': 'fake_param'})
        self.environ = {
            'REQUEST_METHOD': 'FAKE',
            'ec2.request': ec2_request,
            'ec2api.context': self.fake_context
        }
        self.request = wsgi.Request(self.environ)
        self.application = api.Executor()
Ejemplo n.º 15
0
    def __call__(self, req):
        client_request_id = None
        if self.env_client_request_id in req.headers:
            client_request_id = req.headers[self.resp_header_client_request_id]
            req.environ[self.env_client_request_id] = client_request_id
        if self.resp_header_request_id in req.headers:
            req_id = req.headers[self.resp_header_request_id]
        else:
            req_id = context.generate_request_id()

        req.environ[self.env_request_id] = req_id
        response = req.get_response(self.application)
        if client_request_id:
            response.headers.add(self.resp_header_client_request_id,
                                 client_request_id)
        if self.resp_header_request_id not in response.headers:
            response.headers.add(self.resp_header_request_id, req_id)

        return response
Ejemplo n.º 16
0
    def notify(self, action, alarm_id, alarm_name, severity, previous,
               current, reason, reason_data, headers=None):
        headers = headers or {}
        if not headers.get('x-openstack-request-id'):
            headers['x-openstack-request-id'] = context.generate_request_id()

        LOG.info(_(
            "Notifying alarm %(alarm_name)s %(alarm_id)s with severity"
            " %(severity)s from %(previous)s to %(current)s with action "
            "%(action)s because %(reason)s. request-id: %(request_id)s ") %
            ({'alarm_name': alarm_name, 'alarm_id': alarm_id,
              'severity': severity, 'previous': previous,
              'current': current, 'action': action, 'reason': reason,
              'request_id': headers['x-openstack-request-id']}))
        body = {'alarm_name': alarm_name, 'alarm_id': alarm_id,
                'severity': severity, 'previous': previous,
                'current': current, 'reason': reason,
                'reason_data': reason_data}
        headers['content-type'] = 'application/json'
        kwargs = {'data': jsonutils.dumps(body),
                  'headers': headers}

        if action.scheme == 'https':
            default_verify = int(self.conf.rest_notifier_ssl_verify)
            options = urlparse.parse_qs(action.query)
            verify = bool(int(options.get('aodh-alarm-ssl-verify',
                                          [default_verify])[-1]))
            kwargs['verify'] = verify

            cert = self.conf.rest_notifier_certificate_file
            key = self.conf.rest_notifier_certificate_key
            if cert:
                kwargs['cert'] = (cert, key) if key else cert

        # FIXME(rhonjo): Retries are automatically done by urllib3 in requests
        # library. However, there's no interval between retries in urllib3
        # implementation. It will be better to put some interval between
        # retries (future work).
        max_retries = self.conf.rest_notifier_max_retries
        session = requests.Session()
        session.mount(action.geturl(),
                      requests.adapters.HTTPAdapter(max_retries=max_retries))
        session.post(action.geturl(), **kwargs)
Ejemplo n.º 17
0
    def __call__(self, req):
        """Generate a WSGI response based on the exception passed to ctor."""
        code = ec2api.api.exception_to_ec2code(self.wrapped_exc)
        status = self.wrapped_exc.status_int
        message = self.wrapped_exc.explanation

        if status == 501:
            message = "The requested function is not supported"

        if 'AWSAccessKeyId' not in req.params:
            raise webob.exc.HTTPBadRequest()
        user_id, _sep, project_id = req.params['AWSAccessKeyId'].partition(':')
        project_id = project_id or user_id
        remote_address = getattr(req, 'remote_address', '127.0.0.1')
        if CONF.use_forwarded_for:
            remote_address = req.headers.get('X-Forwarded-For', remote_address)

        resp = ec2_error_response(common_context.generate_request_id(), code,
                                  message=message, status=status)
        return resp
Ejemplo n.º 18
0
 def __attach_req_id_to_resp(self, req, resp):
     req_id = context.generate_request_id()
     req.env['request-id'] = req_id
     if 'x-request-id' not in resp._headers:
         resp._headers['x-request-id'] = req_id
Ejemplo n.º 19
0
 def context(self):
     self._context.request_id = o_context.generate_request_id()
     return self._context
Ejemplo n.º 20
0
 def context(self):
     self._context.request_id = o_context.generate_request_id()
     return self._context
Ejemplo n.º 21
0
 def test_generate_request_id_unique(self):
     id1 = context.generate_request_id()
     id2 = context.generate_request_id()
     self.assertNotEqual(id1, id2)
Ejemplo n.º 22
0
 def test_generate_request_id(self):
     id = context.generate_request_id()
     self.assertEqual("req-", id[:4])
Ejemplo n.º 23
0
 def test_generate_request_id(self):
     id = context.generate_request_id()
     self.assertEqual("req-", id[:4])
Ejemplo n.º 24
0
    def __call__(self, req):
        # 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()

        request_id = common_context.generate_request_id()
        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:
            auth_params = {}
        else:
            # Make a copy of args for authentication and signature verification
            auth_params = dict(req.params)
            # Not part of authentication args
            auth_params.pop('Signature', None)

        cred_dict = {
            'access': access,
            'signature': signature,
            'host': req.host,
            'verb': req.method,
            'path': req.path,
            'params': auth_params,
            'headers': req.headers,
            'body_hash': body_hash
        }
        if "ec2" in CONF.keystone_ec2_url:
            creds = {'ec2Credentials': cred_dict}
        else:
            creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}}
        creds_json = jsonutils.dumps(creds)
        headers = {'Content-Type': 'application/json'}

        verify = not CONF.keystone_ec2_insecure
        if verify and CONF.ssl.ca_file:
            verify = CONF.ssl.ca_file

        cert = None
        if CONF.ssl.cert_file and CONF.ssl.key_file:
            cert = (CONF.ssl.cert_file, CONF.ssl.key_file)
        elif CONF.ssl.cert_file:
            cert = CONF.ssl.cert_file

        response = requests.request('POST',
                                    CONF.keystone_ec2_url,
                                    data=creds_json,
                                    headers=headers,
                                    verify=verify,
                                    cert=cert)
        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:
            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')
            roles = [
                role['name'] for role in result['access']['user']['roles']
            ]
        except (AttributeError, KeyError) as e:
            LOG.error(_LE("Keystone failure: %s"), e)
            msg = _("Failure parsing response from keystone: %s") % e
            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)

        catalog = result['access']['serviceCatalog']
        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)

        req.environ['nova.context'] = ctxt

        return self.application
Ejemplo n.º 25
0
 def context(self):
     # generate a new request-id on each call to make server side tracking
     # of RPC calls easier.
     self._context.request_id = common_context.generate_request_id()
     return self._context
Ejemplo n.º 26
0
 def test_generate_request_id_unique(self):
     id1 = context.generate_request_id()
     id2 = context.generate_request_id()
     self.assertNotEqual(id1, id2)
Ejemplo n.º 27
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
Ejemplo n.º 28
0
 def setUp(self):
     super(EC2RequesterTestCase, self).setUp()
     self.controller = self.mock(
         'ec2api.api.cloud.VpcCloudController').return_value
     self.fake_context = mock.NonCallableMock(
         request_id=context.generate_request_id())
Ejemplo n.º 29
0
    def __call__(self, req):
        # 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()

        request_id = common_context.generate_request_id()
        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:
            auth_params = {}
        else:
            # Make a copy of args for authentication and signature verification
            auth_params = dict(req.params)
            # Not part of authentication args
            auth_params.pop('Signature', None)

        cred_dict = {
            'access': access,
            'signature': signature,
            'host': req.host,
            'verb': req.method,
            'path': req.path,
            'params': auth_params,
            'headers': req.headers,
            'body_hash': body_hash
        }
        if "ec2" in CONF.keystone_ec2_url:
            creds = {'ec2Credentials': cred_dict}
        else:
            creds = {'auth': {'OS-KSEC2:ec2Credentials': cred_dict}}
        creds_json = jsonutils.dumps(creds)
        headers = {'Content-Type': 'application/json'}

        verify = not CONF.keystone_ec2_insecure
        if verify and CONF.ssl.ca_file:
            verify = CONF.ssl.ca_file

        cert = None
        if CONF.ssl.cert_file and CONF.ssl.key_file:
            cert = (CONF.ssl.cert_file, CONF.ssl.key_file)
        elif CONF.ssl.cert_file:
            cert = CONF.ssl.cert_file

        response = requests.request('POST', CONF.keystone_ec2_url,
                                    data=creds_json, headers=headers,
                                    verify=verify, cert=cert)
        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:
            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')
            roles = [role['name'] for role
                     in result['access']['user']['roles']]
        except (AttributeError, KeyError) as e:
            LOG.error(_LE("Keystone failure: %s"), e)
            msg = _("Failure parsing response from keystone: %s") % e
            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)

        catalog = result['access']['serviceCatalog']
        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)

        req.environ['nova.context'] = ctxt

        return self.application
Ejemplo n.º 30
0
 def setUp(self):
     super(EC2RequesterTestCase, self).setUp()
     self.controller = self.mock(
         'ec2api.api.cloud.VpcCloudController').return_value
     self.fake_context = mock.NonCallableMock(
         request_id=context.generate_request_id())
Ejemplo n.º 31
0
    def __call__(self, req):
        # 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()

        request_id = common_context.generate_request_id()
        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:
            auth_params = {}
        else:
            # Make a copy of args for authentication and signature verification
            auth_params = dict(req.params)
            # Not part of authentication args
            auth_params.pop("Signature", None)

        cred_dict = {
            "access": access,
            "signature": signature,
            "host": req.host,
            "verb": req.method,
            "path": req.path,
            "params": auth_params,
            "headers": req.headers,
            "body_hash": body_hash,
        }
        if "ec2" in CONF.keystone_ec2_url:
            creds = {"ec2Credentials": cred_dict}
        else:
            creds = {"auth": {"OS-KSEC2:ec2Credentials": cred_dict}}
        creds_json = jsonutils.dumps(creds)
        headers = {"Content-Type": "application/json"}

        verify = not CONF.keystone_ec2_insecure
        if verify and CONF.ssl.ca_file:
            verify = CONF.ssl.ca_file

        cert = None
        if CONF.ssl.cert_file and CONF.ssl.key_file:
            cert = (CONF.ssl.cert_file, CONF.ssl.key_file)
        elif CONF.ssl.cert_file:
            cert = CONF.ssl.cert_file

        response = requests.request(
            "POST", CONF.keystone_ec2_url, data=creds_json, headers=headers, verify=verify, cert=cert
        )
        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:
            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")
            roles = [role["name"] for role in result["access"]["user"]["roles"]]
        except (AttributeError, KeyError) as e:
            LOG.error(_LE("Keystone failure: %s"), e)
            msg = _("Failure parsing response from keystone: %s") % e
            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)

        catalog = result["access"]["serviceCatalog"]
        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,
        )

        req.environ["nova.context"] = ctxt

        return self.application
Ejemplo n.º 32
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
Ejemplo n.º 33
0
 def context(self):
     # generate a new request-id on each call to make server side tracking
     # of RPC calls easier.
     self._context.request_id = common_context.generate_request_id()
     return self._context
Ejemplo n.º 34
0
    def __call__(self, req):
        """
            参数req:
            {
                'environ': {
                    'SCRIPT_NAME': '/v2',
                    'webob.adhoc_attrs': {
                        'response': <Response at 0x74efa10 200 OK>
                        },
                    'REQUEST_METHOD': 'GET',
                    'PATH_INFO': '/0d6ef9bd028641a8ae239c9c1b1f088f/cloudos-servers/detail',
                    'SERVER_PROTOCOL': 'HTTP/1.0',
                    'QUERY_STRING': 'all_tenants=True',
                    'HTTP_X_AUTH_TOKEN': '42ab4a87008648b5b10e40690aff8fe3',
                    'HTTP_USER_AGENT': 'python-novaclient',
                    'HTTP_CONNECTION': 'keep-alive',
                    'REMOTE_PORT': '48695',
                    'SERVER_NAME': '192.168.65.18',
                    'REMOTE_ADDR': '192.168.65.18',
                    'eventlet.input': <eventlet.wsgi.Input object at 0x7114350>,
                    'wsgi.url_scheme': 'http',
                    'SERVER_PORT': '8774',
                    'wsgi.input': <eventlet.wsgi.Input object at 0x7114350>,
                    'HTTP_HOST': '192.168.65.18:8774',
                    'HTTP_X_AUTH_PROJECT_ID': 'service',
                    'wsgi.multithread': True,
                    'eventlet.posthooks': [],
                    'HTTP_ACCEPT': 'application/json',
                    'wsgi.version': (1, 0),
                    'RAW_PATH_INFO': '/v2/0d6ef9bd028641a8ae239c9c1b1f088f/cloudos-servers/detail',
                    'GATEWAY_INTERFACE': 'CGI/1.1',
                    'wsgi.run_once': False,
                    'wsgi.errors': <open file '<stderr>', mode 'w' at 0x7fd45b2bc1e0>,
                    'wsgi.multiprocess': False,
                    'CONTENT_TYPE': 'text/plain',
                    'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
                    'nova.best_content_type': 'application/json'
                    }
                }
        """

        ### def generate_request_id():
        ###    return b'req-' + str(uuid.uuid4()).encode('ascii')
        req_id = context.generate_request_id()
        req.environ[ENV_REQUEST_ID] = req_id

        ### get_response = Request.send
        ### self.application = <nova.api.openstack.FaultWrapper object at 0x7096250>
        response = req.get_response(self.application)

        if HTTP_RESP_HEADER_REQUEST_ID not in response.headers:
            response.headers.add(HTTP_RESP_HEADER_REQUEST_ID, req_id)

        """
            response示例:
                200 OK
                Content-Type: application/json
                Content-Length: 15282
                x-compute-request-id: req-b6e5f0cb-e354-4f33-8ced-f85f83ab8372
        """
        return response