Beispiel #1
0
 def before(self, state):
     if state.request.method not in self.ACTION_MAP:
         pecan.abort(405)
     neutron_context = state.request.context.get('neutron_context')
     resource = state.request.context.get('resource')
     is_update = (state.request.method == 'PUT')
     items = state.request.resources
     policy.init()
     action = '%s_%s' % (self.ACTION_MAP[state.request.method], resource)
     for item in items:
         if is_update:
             obj = copy.copy(state.request.original_object)
             obj.update(item)
             obj[const.ATTRIBUTES_TO_UPDATE] = item.keys()
             item = obj
         try:
             policy.enforce(
                 neutron_context, action, item,
                 pluralized=attribute_population._plural(resource))
         except oslo_policy.PolicyNotAuthorized:
             with excutils.save_and_reraise_exception() as ctxt:
                 # If a tenant is modifying it's own object, it's safe to
                 # return a 403. Otherwise, pretend that it doesn't exist
                 # to avoid giving away information.
                 if (is_update and
                         neutron_context.tenant_id != obj['tenant_id']):
                     ctxt.reraise = False
             msg = _('The resource could not be found.')
             raise webob.exc.HTTPNotFound(msg)
Beispiel #2
0
 def _handle_action(request, id, **kwargs):
     arg_list = [request.context, id]
     # Ensure policy engine is initialized
     policy.init()
     # Fetch the resource and verify if the user can access it
     try:
         parent_id = kwargs.get(self._parent_id_name)
         resource = self._item(request,
                               id,
                               do_authz=True,
                               field_list=None,
                               parent_id=parent_id)
     except oslo_policy.PolicyNotAuthorized:
         msg = _('The resource could not be found.')
         raise webob.exc.HTTPNotFound(msg)
     body = copy.deepcopy(kwargs.pop('body', None))
     # Explicit comparison with None to distinguish from {}
     if body is not None:
         arg_list.append(body)
     # It is ok to raise a 403 because accessibility to the
     # object was checked earlier in this method
     policy.enforce(request.context,
                    name,
                    resource,
                    pluralized=self._collection)
     ret_value = getattr(self._plugin, name)(*arg_list, **kwargs)
     # It is simply impossible to predict whether one of this
     # actions alters resource usage. For instance a tenant port
     # is created when a router interface is added. Therefore it is
     # important to mark as dirty resources whose counters have
     # been altered by this operation
     resource_registry.set_resources_dirty(request.context)
     return ret_value
Beispiel #3
0
    def setUp(self):
        super(BaseTestCase, self).setUp()

        self.useFixture(lockutils.ExternalLockFixture())
        self.useFixture(fixture.APIDefinitionFixture())

        cfg.CONF.set_override('state_path', self.get_default_temp_dir().path)

        self.addCleanup(CONF.reset)
        self.useFixture(ProcessMonitorFixture())

        self.useFixture(fixtures.MonkeyPatch(
            'neutron_lib.exceptions.NeutronException.use_fatal_exceptions',
            fake_use_fatal_exceptions))

        self.useFixture(fixtures.MonkeyPatch(
            'oslo_config.cfg.find_config_files',
            lambda project=None, prog=None, extension=None: []))

        self.setup_rpc_mocks()
        self.setup_config()

        self._callback_manager = registry_manager.CallbacksManager()
        self.useFixture(fixture.CallbackRegistryFixture(
            callback_manager=self._callback_manager))
        # Give a private copy of the directory to each test.
        self.useFixture(fixture.PluginDirectoryFixture())

        policy.init()
        self.addCleanup(policy.reset)
        self.addCleanup(resource_registry.unregister_all_resources)
        self.addCleanup(db_api.sqla_remove_all)
        self.addCleanup(rpc_consumer_reg.clear)
        self.addCleanup(rpc_producer_reg.clear)
Beispiel #4
0
    def _update(self, request, id, body, **kwargs):
        body = Controller.prepare_request_body(
            request.context, copy.deepcopy(body), False, self._resource, self._attr_info, allow_bulk=self._allow_bulk
        )
        action = self._plugin_handlers[self.UPDATE]
        # Load object to check authz
        # but pass only attributes in the original body and required
        # by the policy engine to the policy 'brain'
        field_list = [
            name
            for (name, value) in six.iteritems(self._attr_info)
            if (value.get("required_by_policy") or value.get("primary_key") or "default" not in value)
        ]
        # Ensure policy engine is initialized
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        orig_obj = self._item(request, id, field_list=field_list, parent_id=parent_id)
        orig_object_copy = copy.copy(orig_obj)
        orig_obj.update(body[self._resource])
        # Make a list of attributes to be updated to inform the policy engine
        # which attributes are set explicitly so that it can distinguish them
        # from the ones that are set to their default values.
        orig_obj[n_const.ATTRIBUTES_TO_UPDATE] = body[self._resource].keys()
        try:
            policy.enforce(request.context, action, orig_obj, pluralized=self._collection)
        except oslo_policy.PolicyNotAuthorized:
            with excutils.save_and_reraise_exception() as ctxt:
                # If a tenant is modifying it's own object, it's safe to return
                # a 403. Otherwise, pretend that it doesn't exist to avoid
                # giving away information.
                if request.context.tenant_id != orig_obj["tenant_id"]:
                    ctxt.reraise = False
            msg = _("The resource could not be found.")
            raise webob.exc.HTTPNotFound(msg)

        obj_updater = getattr(self._plugin, action)
        kwargs = {self._resource: body}
        if parent_id:
            kwargs[self._parent_id_name] = parent_id
        obj = obj_updater(request.context, id, **kwargs)
        # Usually an update operation does not alter resource usage, but as
        # there might be side effects it might be worth checking for changes
        # in resource usage here as well (e.g: a tenant port is created when a
        # router interface is added)
        resource_registry.set_resources_dirty(request.context)

        result = {self._resource: self._view(request.context, obj)}
        notifier_method = self._resource + ".update.end"
        self._notifier.info(request.context, notifier_method, result)
        registry.notify(
            self._resource,
            events.BEFORE_RESPONSE,
            self,
            context=request.context,
            data=result,
            method_name=notifier_method,
            action=action,
            original=orig_object_copy,
        )
        return result
Beispiel #5
0
    def delete(self, request, id, **kwargs):
        """Deletes the specified entity."""
        self._notifier.info(request.context,
                            self._resource + '.delete.start',
                            {self._resource + '_id': id})
        action = self._plugin_handlers[self.DELETE]

        # Check authz
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        obj = self._item(request, id, parent_id=parent_id)
        try:
            policy.enforce(request.context,
                           action,
                           obj)
        except common_policy.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_deleter = getattr(self._plugin, action)
        obj_deleter(request.context, id, **kwargs)
        notifier_method = self._resource + '.delete.end'
        self._notifier.info(request.context,
                            notifier_method,
                            {self._resource + '_id': id})
        result = {self._resource: self._view(request.context, obj)}
        self._send_nova_notification(action, {}, result)
        self._send_dhcp_notification(request.context,
                                     result,
                                     notifier_method)
    def delete(self, request, id, **kwargs):
        """Deletes the specified entity."""
        self._notifier.info(request.context,
                            self._resource + '.delete.start',
                            {self._resource + '_id': id}) #通知
        action = self._plugin_handlers[self.DELETE]  #获取具体资源操作行为 eg delete_port

        # Check authz
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        obj = self._item(request, id, parent_id=parent_id)
        try:
            policy.enforce(request.context,
                           action,
                           obj)                                    #检查操作权限
        except exceptions.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_deleter = getattr(self._plugin, action) #获取具体操作方法 eg:M2lplugin类中delete_port
        obj_deleter(request.context, id, **kwargs)  #根据参数,执行具体操作方法
        notifier_method = self._resource + '.delete.end'
        self._notifier.info(request.context,
                            notifier_method,
                            {self._resource + '_id': id}) #消息格式??
        result = {self._resource: self._view(request.context, obj)}
        self._send_nova_notification(action, {}, result)  #通知nova消息,消息内容什么样的?
        self._send_dhcp_notification(request.context,          #通知dhcp消息,消息内容什么样的?
                                     result,
                                     notifier_method)
Beispiel #7
0
    def update(self, request, id, body=None, **kwargs):
        """Updates the specified entity's attributes."""
        parent_id = kwargs.get(self._parent_id_name)
        try:
            payload = body.copy()
        except AttributeError:
            msg = _("Invalid format: %s") % request.body
            raise exceptions.BadRequest(resource='body', msg=msg)
        payload['id'] = id
        self._notifier.info(request.context,
                            self._resource + '.update.start',
                            payload)
        body = Controller.prepare_request_body(request.context, body, False,
                                               self._resource, self._attr_info,
                                               allow_bulk=self._allow_bulk)
        action = self._plugin_handlers[self.UPDATE]
        # Load object to check authz
        # but pass only attributes in the original body and required
        # by the policy engine to the policy 'brain'
        field_list = [name for (name, value) in self._attr_info.iteritems()
                      if (value.get('required_by_policy') or
                          value.get('primary_key') or
                          'default' not in value)]
        # Ensure policy engine is initialized
        policy.init()
        orig_obj = self._item(request, id, field_list=field_list,
                              parent_id=parent_id)
        orig_object_copy = copy.copy(orig_obj)
        orig_obj.update(body[self._resource])
        # Make a list of attributes to be updated to inform the policy engine
        # which attributes are set explicitly so that it can distinguish them
        # from the ones that are set to their default values.
        orig_obj[const.ATTRIBUTES_TO_UPDATE] = body[self._resource].keys()
        try:
            policy.enforce(request.context,
                           action,
                           orig_obj)
        except common_policy.PolicyNotAuthorized:
            with excutils.save_and_reraise_exception() as ctxt:
                # If a tenant is modifying it's own object, it's safe to return
                # a 403. Otherwise, pretend that it doesn't exist to avoid
                # giving away information.
                if request.context.tenant_id != orig_obj['tenant_id']:
                    ctxt.reraise = False
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_updater = getattr(self._plugin, action)
        kwargs = {self._resource: body}
        if parent_id:
            kwargs[self._parent_id_name] = parent_id
        obj = obj_updater(request.context, id, **kwargs)
        result = {self._resource: self._view(request.context, obj)}
        notifier_method = self._resource + '.update.end'
        self._notifier.info(request.context, notifier_method, result)
        self._send_dhcp_notification(request.context,
                                     result,
                                     notifier_method)
        self._send_nova_notification(action, orig_object_copy, result)
        return result
Beispiel #8
0
    def setUp(self):
        super(BaseTestCase, self).setUp()

        self.useFixture(lockutils.ExternalLockFixture())

        cfg.CONF.set_override("state_path", self.get_default_temp_dir().path)

        self.addCleanup(CONF.reset)
        self.useFixture(ProcessMonitorFixture())

        self.useFixture(
            fixtures.MonkeyPatch(
                "neutron_lib.exceptions.NeutronException.use_fatal_exceptions", fake_use_fatal_exceptions
            )
        )

        self.useFixture(
            fixtures.MonkeyPatch(
                "oslo_config.cfg.find_config_files", lambda project=None, prog=None, extension=None: []
            )
        )

        self.setup_rpc_mocks()
        self.setup_config()
        self.setup_test_registry_instance()
        self.setup_test_directory_instance()

        policy.init()
        self.addCleanup(policy.reset)
        self.addCleanup(resource_registry.unregister_all_resources)
        self.addCleanup(rpc_consumer_reg.clear)
Beispiel #9
0
    def _delete(self, request, id, **kwargs):
        action = self._plugin_handlers[self.DELETE]

        # Check authz
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        obj = self._item(request, id, parent_id=parent_id)
        try:
            policy.enforce(request.context, action, obj, pluralized=self._collection)
        except oslo_policy.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist
            msg = _("The resource could not be found.")
            raise webob.exc.HTTPNotFound(msg)

        obj_deleter = getattr(self._plugin, action)
        obj_deleter(request.context, id, **kwargs)
        # A delete operation usually alters resource usage, so mark affected
        # usage trackers as dirty
        resource_registry.set_resources_dirty(request.context)
        notifier_method = self._resource + ".delete.end"
        result = {self._resource: self._view(request.context, obj)}
        notifier_payload = {self._resource + "_id": id}
        notifier_payload.update(result)
        self._notifier.info(request.context, notifier_method, notifier_payload)
        registry.notify(
            self._resource,
            events.BEFORE_RESPONSE,
            self,
            context=request.context,
            data=result,
            method_name=notifier_method,
            action=action,
            original={},
        )
Beispiel #10
0
 def _test_enforce_tenant_id_raises(self, bad_rule):
     self.rules["admin_or_owner"] = common_policy.parse_rule(bad_rule)
     # Trigger a policy with rule admin_or_owner
     action = "create_network"
     target = {"tenant_id": "fake"}
     policy.init()
     self.assertRaises(exceptions.PolicyCheckError, policy.enforce, self.context, action, target)
Beispiel #11
0
    def _delete(self, request, id, **kwargs):
        action = self._plugin_handlers[self.DELETE]

        # Check authz
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        obj = self._item(request, id, parent_id=parent_id)
        try:
            policy.enforce(request.context,
                           action,
                           obj,
                           pluralized=self._collection)
        except oslo_policy.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_deleter = getattr(self._plugin, action)
        obj_deleter(request.context, id, **kwargs)
        # A delete operation usually alters resource usage, so mark affected
        # usage trackers as dirty
        resource_registry.set_resources_dirty(request.context)
        notifier_method = self._resource + '.delete.end'
        self._notifier.info(request.context,
                            notifier_method,
                            {self._resource + '_id': id})
        result = {self._resource: self._view(request.context, obj)}
        self._send_nova_notification(action, {}, result)
        self._send_dhcp_notification(request.context,
                                     result,
                                     notifier_method)
Beispiel #12
0
    def setUp(self):
        super(BaseTestCase, self).setUp()

        # suppress all but errors here
        capture_logs = bool_from_env('OS_LOG_CAPTURE')
        self.useFixture(
            fixtures.FakeLogger(
                name='neutron.api.extensions',
                format=LOG_FORMAT,
                level=std_logging.ERROR,
                nuke_handlers=capture_logs,
            ))

        self.useFixture(lockutils.ExternalLockFixture())

        cfg.CONF.set_override('state_path', self.get_default_temp_dir().path)

        self.addCleanup(CONF.reset)
        self.useFixture(ProcessMonitorFixture())

        self.useFixture(fixtures.MonkeyPatch(
            'neutron.common.exceptions.NeutronException.use_fatal_exceptions',
            fake_use_fatal_exceptions))

        self.setup_rpc_mocks()
        self.setup_config()

        policy.init()
        self.addCleanup(policy.reset)
Beispiel #13
0
    def setUp(self):
        super(NeutronPolicyTestCase, self).setUp()
        policy.reset()
        policy.init()
        self.addCleanup(policy.reset)
        self.admin_only_legacy = "role:admin"
        self.admin_or_owner_legacy = "role:admin or tenant_id:%(tenant_id)s"
        # Add a Fake 'something' resource to RESOURCE_ATTRIBUTE_MAP
        attributes.RESOURCE_ATTRIBUTE_MAP.update(FAKE_RESOURCE)
        self.rules = dict((k, common_policy.parse_rule(v)) for k, v in {
            "context_is_admin": "role:admin",
            "admin_or_network_owner": "rule:context_is_admin or "
                                      "tenant_id:%(network:tenant_id)s",
            "admin_or_owner": ("rule:context_is_admin or "
                               "tenant_id:%(tenant_id)s"),
            "admin_only": "rule:context_is_admin",
            "regular_user": "******",
            "shared": "field:networks:shared=True",
            "external": "field:networks:router:external=True",
            "default": '@',

            "create_network": "rule:admin_or_owner",
            "create_network:shared": "rule:admin_only",
            "update_network": '@',
            "update_network:shared": "rule:admin_only",

            "get_network": "rule:admin_or_owner or "
                           "rule:shared or "
                           "rule:external",
            "create_port:mac": "rule:admin_or_network_owner",
            "create_something": "rule:admin_or_owner",
            "create_something:attr": "rule:admin_or_owner",
            "create_something:attr:sub_attr_1": "rule:admin_or_owner",
            "create_something:attr:sub_attr_2": "rule:admin_only",

            "get_firewall_policy": "rule:admin_or_owner or "
                            "rule:shared",
            "get_firewall_rule": "rule:admin_or_owner or "
                            "rule:shared"
        }.items())

        def fakepolicyinit():
            common_policy.set_rules(common_policy.Rules(self.rules))

        def remove_fake_resource():
            del attributes.RESOURCE_ATTRIBUTE_MAP["%ss" % FAKE_RESOURCE_NAME]

        self.patcher = mock.patch.object(neutron.policy,
                                         'init',
                                         new=fakepolicyinit)
        self.patcher.start()
        self.addCleanup(remove_fake_resource)
        self.context = context.Context('fake', 'fake', roles=['user'])
        plugin_klass = importutils.import_class(
            "neutron.db.db_base_plugin_v2.NeutronDbPluginV2")
        self.manager_patcher = mock.patch('neutron.manager.NeutronManager')
        fake_manager = self.manager_patcher.start()
        fake_manager_instance = fake_manager.return_value
        fake_manager_instance.plugin = plugin_klass()
Beispiel #14
0
    def update(self, request, id, body=None, **kwargs):
        """Updates the specified entity's attributes."""
        parent_id = kwargs.get(self._parent_id_name)
        try:
            payload = body.copy()
        except AttributeError:
            msg = _("Invalid format: %s") % request.body
            raise exceptions.BadRequest(resource='body', msg=msg)
        payload['id'] = id
        notifier_api.notify(request.context,
                            self._publisher_id,
                            self._resource + '.update.start',
                            notifier_api.CONF.default_notification_level,
                            payload)
        body = Controller.prepare_request_body(request.context, body, False,
                                               self._resource, self._attr_info,
                                               allow_bulk=self._allow_bulk)
        action = self._plugin_handlers[self.UPDATE]
        # Load object to check authz
        # but pass only attributes in the original body and required
        # by the policy engine to the policy 'brain'
        field_list = [name for (name, value) in self._attr_info.iteritems()
                      if (value.get('required_by_policy') or
                          value.get('primary_key') or
                          'default' not in value)]
        # Ensure policy engine is initialized
        policy.init()
        orig_obj = self._item(request, id, field_list=field_list,
                              parent_id=parent_id)
        orig_object_copy = copy.copy(orig_obj)
        orig_obj.update(body[self._resource])
        try:
            policy.enforce(request.context,
                           action,
                           orig_obj)
        except exceptions.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_updater = getattr(self._plugin, action)
        kwargs = {self._resource: body}
        if parent_id:
            kwargs[self._parent_id_name] = parent_id
        obj = obj_updater(request.context, id, **kwargs)
        result = {self._resource: self._view(request.context, obj)}
        notifier_method = self._resource + '.update.end'
        notifier_api.notify(request.context,
                            self._publisher_id,
                            notifier_method,
                            notifier_api.CONF.default_notification_level,
                            result)
        self._send_dhcp_notification(request.context,
                                     result,
                                     notifier_method)
        self._nova_notifier.send_network_change(
            action, orig_object_copy, result)
        return result
Beispiel #15
0
 def setUp(self):
     super(TestPaginationAndSorting, self).setUp()
     policy.init()
     self.addCleanup(policy.reset)
     self.plugin = directory.get_plugin()
     self.ctx = context.get_admin_context()
     self._create_networks(self.RESOURCE_COUNT)
     self.networks = self._get_collection()['networks']
Beispiel #16
0
 def setUp(self):
     super(TestExcludeAttributePolicy, self).setUp()
     policy.init()
     self.addCleanup(policy.reset)
     plugin = directory.get_plugin()
     ctx = context.get_admin_context()
     self.network_id = pecan_utils.create_network(ctx, plugin)['id']
     mock.patch('neutron.pecan_wsgi.controllers.resource.'
                'CollectionsController.get').start()
Beispiel #17
0
    def delete(self, request, id, **kwargs):
        """Deletes the specified entity."""
        self._notifier.info(request.context,
                            self._resource + '.delete.start',
                            {self._resource + '_id': id})
        action = self._plugin_handlers[self.DELETE]

        # Check authz
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        obj = self._item(request, id, parent_id=parent_id)
        try:
            policy.enforce(request.context,
                           action,
                           obj)
        except exceptions.PolicyNotAuthorized:
            with excutils.save_and_reraise_exception() as ctxt:
                # if the tenant id is same, reraise
                # otherwise pretend
                if request.context.tenant_id != obj['tenant_id']:
                    ctxt.reraise = False
            # To avoid giving away information, pretend that it
            # doesn't exist
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)
        filters = api_common.get_filters(
            request, self._attr_info, keeps_pre='_x_')
        if not kwargs:
            kwargs = {}
        if filters:
            kwargs['filters'] = filters
        obj_deleter = getattr(self._plugin, action)
        if kwargs:
            obj_deleter(request.context, id, **kwargs)
        else:
            obj_deleter(request.context, id)
        result = {self._resource: self._view(request.context, obj)}
        notifier_method = self._resource + '.delete.end'
        delete_notification_dict = result.copy()
        delete_notification_dict[self._resource + '_id'] = id
        data = {}
        for attr, attr_vals in self._attr_info.iteritems():
            delete_notification = attr_vals.get('delete_notification')
            if delete_notification:
                data[attr] = obj[attr]
        if data:
            delete_notification_dict['_x_data'] = data
        self._notifier.info(request.context,
                            notifier_method,
                            delete_notification_dict)

        self._send_nova_notification(action, {}, result)
        self._send_dhcp_notification(request.context,
                                     result,
                                     notifier_method)
    def before(self, state):
        # This hook should be run only for PUT,POST and DELETE methods and for
        # requests targeting a neutron resource
        resources = state.request.context.get('resources', [])
        if state.request.method not in ('POST', 'PUT', 'DELETE'):
            return
        # As this routine will likely alter the resources, do a shallow copy
        resources_copy = resources[:]
        neutron_context = state.request.context.get('neutron_context')
        resource = state.request.context.get('resource')
        # If there is no resource for this request, don't bother running authZ
        # policies
        if not resource:
            return
        collection = state.request.context.get('collection')
        needs_prefetch = (state.request.method == 'PUT' or
                          state.request.method == 'DELETE')
        policy.init()
        action = '%s_%s' % (self.ACTION_MAP[state.request.method], resource)

        # NOTE(salv-orlando): As bulk updates are not supported, in case of PUT
        # requests there will be only a single item to process, and its
        # identifier would have been already retrieved by the lookup process;
        # in the case of DELETE requests there won't be any item to process in
        # the request body
        if needs_prefetch:
            try:
                item = resources_copy.pop()
            except IndexError:
                # Ops... this was a delete after all!
                item = {}
            resource_id = state.request.context.get('resource_id')
            obj = copy.copy(self._fetch_resource(neutron_context,
                                                 resource,
                                                 resource_id))
            obj.update(item)
            obj[const.ATTRIBUTES_TO_UPDATE] = item.keys()
            # Put back the item in the list so that policies could be enforced
            resources_copy.append(obj)

        for item in resources_copy:
            try:
                policy.enforce(
                    neutron_context, action, item,
                    pluralized=collection)
            except oslo_policy.PolicyNotAuthorized:
                with excutils.save_and_reraise_exception() as ctxt:
                    # If a tenant is modifying it's own object, it's safe to
                    # return a 403. Otherwise, pretend that it doesn't exist
                    # to avoid giving away information.
                    if (needs_prefetch and
                        neutron_context.tenant_id != item['tenant_id']):
                        ctxt.reraise = False
                msg = _('The resource could not be found.')
                raise webob.exc.HTTPNotFound(msg)
Beispiel #19
0
    def setUp(self):
        super(DefaultPolicyTestCase, self).setUp()
        policy.reset()
        policy.init()
        self.addCleanup(policy.reset)

        self.rules = {"default": "", "example:exist": "!"}

        self._set_rules("default")

        self.context = context.Context("fake", "fake")
Beispiel #20
0
    def before(self, state):
        # This hook should be run only for PUT,POST and DELETE methods and for
        # requests targeting a neutron resource
        resources = state.request.context.get("resources", [])
        if state.request.method not in ("POST", "PUT", "DELETE"):
            return
        # As this routine will likely alter the resources, do a shallow copy
        resources_copy = resources[:]
        neutron_context = state.request.context.get("neutron_context")
        resource = state.request.context.get("resource")
        # If there is no resource for this request, don't bother running authZ
        # policies
        if not resource:
            return
        collection = state.request.context.get("collection")
        needs_prefetch = state.request.method == "PUT" or state.request.method == "DELETE"
        policy.init()
        action = "%s_%s" % (pecan_constants.ACTION_MAP[state.request.method], resource)

        # NOTE(salv-orlando): As bulk updates are not supported, in case of PUT
        # requests there will be only a single item to process, and its
        # identifier would have been already retrieved by the lookup process;
        # in the case of DELETE requests there won't be any item to process in
        # the request body
        merged_resources = []
        if needs_prefetch:
            try:
                item = resources_copy.pop()
            except IndexError:
                # Ops... this was a delete after all!
                item = {}
            resource_id = state.request.context.get("resource_id")
            obj = copy.copy(self._fetch_resource(neutron_context, resource, resource_id))
            obj.update(item)
            merged_resources.append(obj.copy())
            obj[const.ATTRIBUTES_TO_UPDATE] = item.keys()
            # Put back the item in the list so that policies could be enforced
            resources_copy.append(obj)
        # TODO(salv-orlando): as other hooks might need to prefetch resources,
        # store them in the request context. However, this should be done in a
        # separate hook which is conventietly called before all other hooks
        state.request.context["request_resources"] = merged_resources
        for item in resources_copy:
            try:
                policy.enforce(neutron_context, action, item, pluralized=collection)
            except oslo_policy.PolicyNotAuthorized:
                with excutils.save_and_reraise_exception() as ctxt:
                    # If a tenant is modifying it's own object, it's safe to
                    # return a 403. Otherwise, pretend that it doesn't exist
                    # to avoid giving away information.
                    if needs_prefetch and neutron_context.tenant_id != item["tenant_id"]:
                        ctxt.reraise = False
                msg = _("The resource could not be found.")
                raise webob.exc.HTTPNotFound(msg)
Beispiel #21
0
 def setUp(self):
     fake_ext = pecan_utils.FakeExtension()
     fake_plugin = pecan_utils.FakePlugin()
     plugins = {pecan_utils.FakePlugin.PLUGIN_TYPE: fake_plugin}
     new_extensions = {fake_ext.get_alias(): fake_ext}
     super(TestShimControllers, self).setUp(service_plugins=plugins, extensions=new_extensions)
     policy.init()
     policy._ENFORCER.set_rules(
         oslo_policy.Rules.from_dict({"get_meh_meh": "", "get_meh_mehs": "", "get_fake_subresources": ""}),
         overwrite=False,
     )
     self.addCleanup(policy.reset)
    def after(self, state):
        neutron_context = state.request.context.get('neutron_context')
        resource = state.request.context.get('resource')
        collection = state.request.context.get('collection')
        controller = utils.get_controller(state)
        if not resource:
            # can't filter a resource we don't recognize
            return
        # NOTE(kevinbenton): extension listing isn't controlled by policy
        if resource == 'extension':
            return
        try:
            data = state.response.json
        except ValueError:
            return
        if state.request.method not in pecan_constants.ACTION_MAP:
            return
        if not data or (resource not in data and collection not in data):
            return
        policy.init()
        is_single = resource in data
        action_type = pecan_constants.ACTION_MAP[state.request.method]
        if action_type == 'get':
            action = controller.plugin_handlers[controller.SHOW]
        else:
            action = controller.plugin_handlers[action_type]
        key = resource if is_single else collection
        to_process = [data[resource]] if is_single else data[collection]
        # in the single case, we enforce which raises on violation
        # in the plural case, we just check so violating items are hidden
        policy_method = policy.enforce if is_single else policy.check
        plugin = manager.NeutronManager.get_plugin_for_resource(collection)
        try:
            resp = [self._get_filtered_item(state.request, controller,
                                            resource, collection, item)
                    for item in to_process
                    if (state.request.method != 'GET' or
                        policy_method(neutron_context, action, item,
                                      plugin=plugin,
                                      pluralized=collection))]
        except oslo_policy.PolicyNotAuthorized:
            # This exception must be explicitly caught as the exception
            # translation hook won't be called if an error occurs in the
            # 'after' handler.  Instead of raising an HTTPForbidden exception,
            # we have to set the status_code here to prevent the catch_errors
            # middleware from turning this into a 500.
            state.response.status_code = 403
            return

        if is_single:
            resp = resp[0]
        state.response.json = {key: resp}
Beispiel #23
0
    def setUp(self):
        super(DefaultPolicyTestCase, self).setUp()
        policy.reset()
        policy.init()
        self.addCleanup(policy.reset)

        self.rules = {
            "default": '',
            "example:exist": '!',
        }

        self._set_rules('default')

        self.context = context.Context('fake', 'fake')
Beispiel #24
0
 def test_get_child_resource_policy_check(self):
     policy.reset()
     policy.init()
     policy._ENFORCER.set_rules(
         oslo_policy.Rules.from_dict(
             {'get_meh_meh_fake_duplicate': ''}
         )
     )
     url = '/v2.0/{0}/something/{1}'.format(self.collection,
                                            self.fake_collection)
     resp = self.app.get(url)
     self.assertEqual(200, resp.status_int)
     self.assertEqual({'fake_duplicates': [{'fake': 'something'}]},
                      resp.json)
Beispiel #25
0
 def setUp(self):
     cfg.CONF.set_override(
         'service_plugins',
         ['neutron.services.l3_router.l3_router_plugin.L3RouterPlugin',
          'neutron.services.flavors.flavors_plugin.FlavorsPlugin'])
     super(TestRouterController, self).setUp()
     policy.init()
     self.addCleanup(policy.reset)
     plugin = directory.get_plugin()
     ctx = context.get_admin_context()
     l3_plugin = directory.get_plugin(plugin_constants.L3)
     network_id = pecan_utils.create_network(ctx, plugin)['id']
     self.subnet = pecan_utils.create_subnet(ctx, plugin, network_id)
     self.router = pecan_utils.create_router(ctx, l3_plugin)
Beispiel #26
0
 def test_proper_load_order(self):
     """
     Verifies that loading policies by way of admin context after
     populating extensions and extending the resource map results in
     networks with router:external are visible to regular tenants.
     """
     policy.reset()
     extension_manager = extensions.ExtensionManager(self.extension_path)
     extension_manager.extend_resources(self.api_version,
                                        attributes.RESOURCE_ATTRIBUTE_MAP)
     policy.init()
     admin_context = context.get_admin_context()
     tenant_context = context.Context('test_user', 'test_tenant_id', False)
     self.assertTrue(self._check_external_router_policy(admin_context))
     self.assertTrue(self._check_external_router_policy(tenant_context))
Beispiel #27
0
    def _delete(self, request, id, **kwargs):
        action = self._plugin_handlers[self.DELETE]

        # Check authz
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        obj = self._item(request, id, parent_id=parent_id)
        try:
            policy.enforce(request.context,
                           action,
                           obj,
                           pluralized=self._collection)
        except oslo_policy.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist if policy does not authorize SHOW
            with excutils.save_and_reraise_exception() as ctxt:
                if not policy.check(request.context,
                                    self._plugin_handlers[self.SHOW],
                                    obj,
                                    pluralized=self._collection):
                    ctxt.reraise = False
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_deleter = getattr(self._plugin, action)
        obj_deleter(request.context, id, **kwargs)
        # A delete operation usually alters resource usage, so mark affected
        # usage trackers as dirty
        resource_registry.set_resources_dirty(request.context)
        notifier_method = self._resource + '.delete.end'
        result = {self._resource: self._view(request.context, obj)}
        notifier_payload = {self._resource + '_id': id}
        notifier_payload.update(result)
        self._notifier.info(request.context, notifier_method, notifier_payload)

        registry.publish(self._resource,
                         events.BEFORE_RESPONSE,
                         self,
                         payload=events.APIEventPayload(
                             request.context,
                             notifier_method,
                             action,
                             states=(
                                 {},
                                 obj,
                                 result,
                             ),
                             collection_name=self._collection))
Beispiel #28
0
 def setUp(self):
     super(UOSExtensionPolicyTestCase, self).setUp()
     policy.reset()
     policy.init()
     rules = {
         "associate_floatingip_router": "not role:project_observer",
         "get_router_details": "role:admin",
         "remove_router_portforwarding": "role:member"
     }
     common_policy.set_rules(common_policy.Rules(
         dict((k, common_policy.parse_rule(v))
              for k, v in rules.items())))
     self.context = context.Context('fake', 'fake', roles=['member'])
     self.request = FakeRequest(self.context)
     self.target = {}
     self.controller = uos.UosController()
Beispiel #29
0
    def test_proper_load_order(self):
        """Test proper policy load order

        Verifies that loading policies by way of admin context after
        populating extensions and extending the resource map results in
        networks with router:external are visible to regular tenants.
        """
        policy.reset()
        extension_manager = extensions.ExtensionManager(self.extension_path)
        extension_manager.extend_resources(self.api_version,
                                           attributes.RESOURCES)
        policy.init()
        admin_context = context.get_admin_context()
        tenant_context = context.Context('test_user', 'test_tenant_id', False)
        self.assertTrue(self._check_external_router_policy(admin_context))
        self.assertTrue(self._check_external_router_policy(tenant_context))
 def setUp(self):
     fake_ext = pecan_utils.FakeExtension()
     fake_plugin = pecan_utils.FakePlugin()
     plugins = {pecan_utils.FakePlugin.PLUGIN_TYPE: fake_plugin}
     new_extensions = {fake_ext.get_alias(): fake_ext}
     super(TestShimControllers, self).setUp(service_plugins=plugins,
                                            extensions=new_extensions)
     policy.init()
     policy._ENFORCER.set_rules(oslo_policy.Rules.from_dict({
         'get_meh_meh':
         '',
         'get_meh_mehs':
         ''
     }),
                                overwrite=False)
     self.addCleanup(policy.reset)
Beispiel #31
0
 def setUp(self):
     super(TestDHCPAgentShimControllers, self).setUp()
     policy.init()
     policy._ENFORCER.set_rules(
         oslo_policy.Rules.from_dict(
             {'get_dhcp-agents': 'role:admin',
              'get_dhcp-networks': 'role:admin',
              'create_dhcp-networks': 'role:admin',
              'delete_dhcp-networks': 'role:admin'}),
         overwrite=False)
     plugin = directory.get_plugin()
     ctx = context.get_admin_context()
     self.network = pecan_utils.create_network(ctx, plugin)
     self.agent = helpers.register_dhcp_agent()
     # NOTE(blogan): Not sending notifications because this test is for
     # testing the shim controllers
     plugin.agent_notifiers[n_const.AGENT_TYPE_DHCP] = None
Beispiel #32
0
 def setUp(self):
     super(UOSExtensionPolicyTestCase, self).setUp()
     policy.reset()
     policy.init()
     rules = {
         "associate_floatingip_router": "not role:project_observer",
         "get_router_details": "role:admin",
         "remove_router_portforwarding": "role:member"
     }
     common_policy.set_rules(
         common_policy.Rules(
             dict((k, common_policy.parse_rule(v))
                  for k, v in rules.items())))
     self.context = context.Context('fake', 'fake', roles=['member'])
     self.request = FakeRequest(self.context)
     self.target = {}
     self.controller = uos.UosController()
Beispiel #33
0
 def setUp(self):
     super(TestDHCPAgentShimControllers, self).setUp()
     policy.init()
     policy._ENFORCER.set_rules(
         oslo_policy.Rules.from_dict(
             {'get_dhcp-agents': 'role:admin',
              'get_dhcp-networks': 'role:admin',
              'create_dhcp-networks': 'role:admin',
              'delete_dhcp-networks': 'role:admin'}),
         overwrite=False)
     plugin = manager.NeutronManager.get_plugin()
     ctx = context.get_admin_context()
     self.network = pecan_utils.create_network(ctx, plugin)
     self.agent = helpers.register_dhcp_agent()
     # NOTE(blogan): Not sending notifications because this test is for
     # testing the shim controllers
     plugin.agent_notifiers[n_const.AGENT_TYPE_DHCP] = None
Beispiel #34
0
 def _handle_action(request, id, **kwargs):
     arg_list = [request.context, id]
     # Ensure policy engine is initialized
     policy.init()
     # Fetch the resource and verify if the user can access it
     try:
         resource = self._item(request, id, True)
     except exceptions.PolicyNotAuthorized:
         msg = _('The resource could not be found.')
         raise webob.exc.HTTPNotFound(msg)
     body = kwargs.pop('body', None)
     # Explicit comparison with None to distinguish from {}
     if body is not None:
         arg_list.append(body)
     # It is ok to raise a 403 because accessibility to the
     # object was checked earlier in this method
     policy.enforce(request.context, name, resource)
     return getattr(self._plugin, name)(*arg_list, **kwargs)
Beispiel #35
0
 def _handle_action(request, id, **kwargs):
     arg_list = [request.context, id]
     # Ensure policy engine is initialized
     policy.init()
     # Fetch the resource and verify if the user can access it
     try:
         resource = self._item(request, id, True)
     except exceptions.PolicyNotAuthorized:
         msg = _("The resource could not be found.")
         raise webob.exc.HTTPNotFound(msg)
     body = kwargs.pop("body", None)
     # Explicit comparison with None to distinguish from {}
     if body is not None:
         arg_list.append(body)
     # It is ok to raise a 403 because accessibility to the
     # object was checked earlier in this method
     policy.enforce(request.context, name, resource)
     return getattr(self._plugin, name)(*arg_list, **kwargs)
Beispiel #36
0
 def setUp(self):
     fake_ext = pecan_utils.FakeExtension()
     fake_plugin = pecan_utils.FakePlugin()
     plugins = {pecan_utils.FakePlugin.PLUGIN_TYPE: fake_plugin}
     new_extensions = {fake_ext.get_alias(): fake_ext}
     super(TestParentSubresourceController, self).setUp(
         service_plugins=plugins, extensions=new_extensions)
     policy.init()
     policy._ENFORCER.set_rules(
         oslo_policy.Rules.from_dict(
             {'get_fake_duplicate': '',
              'get_meh_meh_fake_duplicate': ''}),
         overwrite=False)
     self.addCleanup(policy.reset)
     hyphen_collection = pecan_utils.FakeExtension.HYPHENATED_COLLECTION
     self.collection = hyphen_collection.replace('_', '-')
     self.fake_collection = (pecan_utils.FakeExtension.
                             FAKE_PARENT_SUBRESOURCE_COLLECTION)
Beispiel #37
0
 def setUp(self):
     fake_ext = pecan_utils.FakeExtension()
     fake_plugin = pecan_utils.FakePlugin()
     plugins = {pecan_utils.FakePlugin.PLUGIN_TYPE: fake_plugin}
     new_extensions = {fake_ext.get_alias(): fake_ext}
     super(TestParentSubresourceController, self).setUp(
         service_plugins=plugins, extensions=new_extensions)
     policy.init()
     policy._ENFORCER.set_rules(
         oslo_policy.Rules.from_dict(
             {'get_fake_duplicate': '',
              'get_meh_meh_fake_duplicates': ''}),
         overwrite=False)
     self.addCleanup(policy.reset)
     hyphen_collection = pecan_utils.FakeExtension.HYPHENATED_COLLECTION
     self.collection = hyphen_collection.replace('_', '-')
     self.fake_collection = (pecan_utils.FakeExtension.
                             FAKE_PARENT_SUBRESOURCE_COLLECTION)
Beispiel #38
0
 def setUp(self):
     cfg.CONF.set_override(
         'service_plugins',
         ['neutron.services.l3_router.l3_router_plugin.L3RouterPlugin',
          'neutron.services.flavors.flavors_plugin.FlavorsPlugin'])
     super(TestL3AgentShimControllers, self).setUp()
     policy.init()
     policy._ENFORCER.set_rules(
         oslo_policy.Rules.from_dict(
             {'get_l3-agents': 'role:admin',
              'get_l3-routers': 'role:admin'}),
         overwrite=False)
     ctx = context.get_admin_context()
     l3_plugin = directory.get_plugin(n_const.L3)
     self.router = pecan_utils.create_router(ctx, l3_plugin)
     self.agent = helpers.register_l3_agent()
     # NOTE(blogan): Not sending notifications because this test is for
     # testing the shim controllers
     l3_plugin.agent_notifiers[n_const.AGENT_TYPE_L3] = None
Beispiel #39
0
    def test_proper_load_order(self):
        """Test proper policy load order

        Verifies that loading policies by way of admin context after
        populating extensions and extending the resource map results in
        networks with router:external are visible to regular tenants.
        """
        policy.reset()
        extension_manager = extensions.ExtensionManager(self.extension_path)
        extension_manager.extend_resources(self.api_version,
                                           attributes.RESOURCES)
        # TODO(amotoki): Consider this should be part of
        # neutron.policy.reset (or refresh), but as of now
        # this is only required for unit testing.
        policies.reload_default_policies()
        policy.init()
        admin_context = context.get_admin_context()
        tenant_context = context.Context('test_user', 'test_tenant_id', False)
        self.assertTrue(self._check_external_router_policy(admin_context))
        self.assertTrue(self._check_external_router_policy(tenant_context))
Beispiel #40
0
    def before(self, state):
        # This hook should be run only for PUT,POST and DELETE methods and for
        # requests targeting a neutron resource
        # FIXME(salv-orlando): DELETE support. It does not work with the
        # current logic. See LP Bug #1520180
        items = state.request.context.get('resources')
        if state.request.method not in ('POST', 'PUT') or not items:
            return
        neutron_context = state.request.context.get('neutron_context')
        resource = state.request.context.get('resource')
        collection = state.request.context.get('collection')
        is_update = (state.request.method == 'PUT')
        policy.init()
        action = '%s_%s' % (self.ACTION_MAP[state.request.method], resource)

        # NOTE(salv-orlando): As bulk updates are not supported, in case of PUT
        # requests there will be only a single item to process, and its
        # identifier would have been already retrieved by the lookup process
        for item in items:
            if is_update:
                resource_id = state.request.context.get('resource_id')
                obj = copy.copy(self._fetch_resource(neutron_context,
                                                     resource,
                                                     resource_id))
                obj.update(item)
                obj[const.ATTRIBUTES_TO_UPDATE] = item.keys()
                item = obj
            try:
                policy.enforce(
                    neutron_context, action, item,
                    pluralized=collection)
            except oslo_policy.PolicyNotAuthorized:
                with excutils.save_and_reraise_exception() as ctxt:
                    # If a tenant is modifying it's own object, it's safe to
                    # return a 403. Otherwise, pretend that it doesn't exist
                    # to avoid giving away information.
                    if (is_update and
                            neutron_context.tenant_id != obj['tenant_id']):
                        ctxt.reraise = False
                msg = _('The resource could not be found.')
                raise webob.exc.HTTPNotFound(msg)
Beispiel #41
0
 def test_policy_404(self):
     with self.subnet(cidr='12.0.0.0/24') as public_sub:
         self._set_net_external(public_sub['subnet']['network_id'])
         fip = self._make_floatingip(self.fmt,
                                     public_sub['subnet']['network_id'])
         policy.reset()
         policy.init()
         rules = {"delete_floatingip": "role:admin_only"}
         common_policy.set_rules(
             common_policy.Rules(
                 dict((k, common_policy.parse_rule(v))
                      for k, v in rules.items())))
         fip_id = fip['floatingip']['id']
         self.context = context.Context('fake', 'fake', roles=['member'])
         req = self.new_delete_request('floatingips', fip_id)
         req.environ['neutron.context'] = self.context
         res = req.get_response(self._api_for_resource('floatingips'))
         self.assertEqual(404, res.status_int)
         policy.reset()
         policy.init()
         self._delete('floatingips', fip_id)
Beispiel #42
0
    def test_modified_policy_reloads(self):
        def fake_find_config_file(_1, _2):
            return self.tempdir.join('policy')

        with mock.patch.object(neutron.common.utils,
                               'find_config_file',
                               new=fake_find_config_file):
            tmpfilename = fake_find_config_file(None, None)
            action = "example:test"
            with open(tmpfilename, "w") as policyfile:
                policyfile.write("""{"example:test": ""}""")
            policy.init()
            policy.enforce(self.context, action, self.target)
            with open(tmpfilename, "w") as policyfile:
                policyfile.write("""{"example:test": "!"}""")
            # NOTE(vish): reset stored policy cache so we don't have to
            # sleep(1)
            policy._POLICY_CACHE = {}
            policy.init()
            self.assertRaises(exceptions.PolicyNotAuthorized, policy.enforce,
                              self.context, action, self.target)
Beispiel #43
0
    def setUp(self):
        super(BaseTestCase, self).setUp()

        self.useFixture(lockutils.ExternalLockFixture())
        self.useFixture(fixture.APIDefinitionFixture())

        config.register_common_config_options()
        cfg.CONF.set_override('state_path', self.get_default_temp_dir().path)

        self.addCleanup(CONF.reset)
        self.useFixture(ProcessMonitorFixture())

        self.useFixture(
            fixtures.MonkeyPatch(
                'neutron_lib.exceptions.NeutronException.use_fatal_exceptions',
                fake_use_fatal_exceptions))

        self.useFixture(
            fixtures.MonkeyPatch(
                'oslo_config.cfg.find_config_files',
                lambda project=None, prog=None, extension=None: []))

        self.useFixture(fixture.RPCFixture())

        self.setup_config()

        self._callback_manager = registry_manager.CallbacksManager()
        self.useFixture(
            fixture.CallbackRegistryFixture(
                callback_manager=self._callback_manager))
        # Give a private copy of the directory to each test.
        self.useFixture(fixture.PluginDirectoryFixture())

        policy.init(suppress_deprecation_warnings=True)
        self.addCleanup(policy.reset)
        self.addCleanup(resource_registry.unregister_all_resources)
        self.addCleanup(db_api.sqla_remove_all)
        self.addCleanup(rpc_consumer_reg.clear)
        self.addCleanup(rpc_producer_reg.clear)
        self.addCleanup(profiler.clean)
Beispiel #44
0
 def setUp(self):
     # Create a controller for a fake resource. This will make the tests
     # independent from the evolution of the API (so if one changes the API
     # or the default policies there won't be any risk of breaking these
     # tests, or at least I hope so)
     super(TestPolicyEnforcementHook, self).setUp()
     self.mock_plugin = mock.Mock()
     attributes.RESOURCES.update(self.FAKE_RESOURCE)
     manager.NeutronManager.set_plugin_for_resource('mehs',
                                                    self.mock_plugin)
     manager.NeutronManager.set_plugin_for_resource('admin_mehs',
                                                    self.mock_plugin)
     fake_controller = resource.CollectionsController('mehs', 'meh')
     admin_fake_controller = resource.CollectionsController(
         'admin_mehs', 'admin_meh')
     manager.NeutronManager.set_controller_for_resource(
         'mehs', fake_controller)
     manager.NeutronManager.set_controller_for_resource(
         'admin_mehs', admin_fake_controller)
     # Inject policies for the fake resource
     policy.init()
     policy._ENFORCER.set_rules(oslo_policy.Rules.from_dict({
         'create_meh':
         '',
         'update_meh':
         'rule:admin_only',
         'delete_meh':
         'rule:admin_only',
         'get_meh':
         'rule:admin_only or field:mehs:id=xxx',
         'get_meh:restricted_attr':
         'rule:admin_only',
         'create_admin_meh':
         'rule:admin_only',
         'get_admin_meh':
         'rule:admin_only'
     }),
                                overwrite=False)
Beispiel #45
0
 def setUp(self):
     super(PolicyTestCase, self).setUp()
     policy.reset()
     self.addCleanup(policy.reset)
     # NOTE(vish): preload rules to circumvent reloading from file
     policy.init()
     rules = {
         "true": '@',
         "example:allowed": '@',
         "example:denied": '!',
         "example:get_http": "http:http://www.example.com",
         "example:my_file": "role:compute_admin or tenant_id:%(tenant_id)s",
         "example:early_and_fail": "! and @",
         "example:early_or_success": "@ or !",
         "example:lowercase_admin": "role:admin or role:sysadmin",
         "example:uppercase_admin": "role:ADMIN or role:sysadmin",
     }
     # NOTE(vish): then overload underlying rules
     common_policy.set_rules(common_policy.Rules(
         dict((k, common_policy.parse_rule(v))
              for k, v in rules.items())))
     self.context = context.Context('fake', 'fake', roles=['member'])
     self.target = {}
Beispiel #46
0
    def setUp(self):
        super(BaseTestCase, self).setUp()

        # suppress all but errors here
        capture_logs = bool_from_env('OS_LOG_CAPTURE')
        self.useFixture(
            fixtures.FakeLogger(
                name='neutron.api.extensions',
                format=LOG_FORMAT,
                level=std_logging.ERROR,
                nuke_handlers=capture_logs,
            ))

        self.useFixture(lockutils.ExternalLockFixture())

        cfg.CONF.set_override('state_path', self.get_default_temp_dir().path)

        self.addCleanup(CONF.reset)
        self.useFixture(ProcessMonitorFixture())

        self.useFixture(
            fixtures.MonkeyPatch(
                'neutron.common.exceptions.NeutronException.use_fatal_exceptions',
                fake_use_fatal_exceptions))

        self.useFixture(
            fixtures.MonkeyPatch(
                'oslo_config.cfg.find_config_files',
                lambda project=None, prog=None, extension=None: []))

        self.setup_rpc_mocks()
        self.setup_config()
        self.setup_test_registry_instance()

        policy.init()
        self.addCleanup(policy.reset)
        self.addCleanup(rpc_consumer_reg.clear)
Beispiel #47
0
    def _delete(self, request, id, **kwargs):
        action = self._plugin_handlers[self.DELETE]

        # Check authz
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        obj = self._item(request, id, parent_id=parent_id)
        try:
            policy.enforce(request.context,
                           action,
                           obj,
                           pluralized=self._collection)
        except oslo_policy.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_deleter = getattr(self._plugin, action)
        obj_deleter(request.context, id, **kwargs)
        # A delete operation usually alters resource usage, so mark affected
        # usage trackers as dirty
        resource_registry.set_resources_dirty(request.context)
        notifier_method = self._resource + '.delete.end'
        result = {self._resource: self._view(request.context, obj)}
        notifier_payload = {self._resource + '_id': id}
        notifier_payload.update(result)
        self._notifier.info(request.context, notifier_method, notifier_payload)
        registry.notify(self._resource,
                        events.BEFORE_RESPONSE,
                        self,
                        context=request.context,
                        data=result,
                        method_name=notifier_method,
                        action=action,
                        original={})
Beispiel #48
0
 def show(self, request, id, **kwargs):
     """Returns detailed information about the requested entity."""
     try:
         # NOTE(salvatore-orlando): The following ensures that fields
         # which are needed for authZ policy validation are not stripped
         # away by the plugin before returning.
         field_list, added_fields = self._do_field_list(
             api_common.list_args(request, "fields"))
         parent_id = kwargs.get(self._parent_id_name)
         # Ensure policy engine is initialized
         policy.init()
         return {self._resource:
                 self._view(request.context,
                            self._item(request,
                                       id,
                                       do_authz=True,
                                       field_list=field_list,
                                       parent_id=parent_id),
                            fields_to_strip=added_fields)}
     except oslo_policy.PolicyNotAuthorized:
         # To avoid giving away information, pretend that it
         # doesn't exist
         msg = _('The resource could not be found.')
         raise webob.exc.HTTPNotFound(msg)
Beispiel #49
0
    def delete(self, request, id, **kwargs):
        """Deletes the specified entity."""
        self._notifier.info(request.context,
                            self._resource + '.delete.start',
                            {self._resource + '_id': id})
        action = self._plugin_handlers[self.DELETE]

        # Check authz
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        obj = self._item(request, id, parent_id=parent_id)
        try:
            policy.enforce(request.context,
                           action,
                           obj,
                           pluralized=self._collection)
        except oslo_policy.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_deleter = getattr(self._plugin, action)
        obj_deleter(request.context, id, **kwargs)
        # A delete operation usually alters resource usage, so mark affected
        # usage trackers as dirty
        resource_registry.set_resources_dirty(request.context)
        notifier_method = self._resource + '.delete.end'
        self._notifier.info(request.context,
                            notifier_method,
                            {self._resource + '_id': id})
        result = {self._resource: self._view(request.context, obj)}
        self._send_nova_notification(action, {}, result)
        self._send_dhcp_notification(request.context,
                                     result,
                                     notifier_method)
Beispiel #50
0
 def index(self, request, **kwargs):
     """Returns a list of the requested entity."""
     parent_id = kwargs.get(self._parent_id_name)
     # Ensure policy engine is initialized
     policy.init()
     return self._items(request, True, parent_id)
Beispiel #51
0
    def _create(self, request, body, **kwargs):
        """Creates a new instance of the requested entity."""
        parent_id = kwargs.get(self._parent_id_name)
        body = Controller.prepare_request_body(request.context,
                                               copy.deepcopy(body),
                                               True,
                                               self._resource,
                                               self._attr_info,
                                               allow_bulk=self._allow_bulk)
        action = self._plugin_handlers[self.CREATE]
        # Check authz
        if self._collection in body:
            # Have to account for bulk create
            items = body[self._collection]
        else:
            items = [body]
        # Ensure policy engine is initialized
        policy.init()
        # Store requested resource amounts grouping them by tenant
        # This won't work with multiple resources. However because of the
        # current structure of this controller there will hardly be more than
        # one resource for which reservations are being made
        request_deltas = collections.defaultdict(int)
        for item in items:
            self._validate_network_tenant_ownership(request,
                                                    item[self._resource])
            policy.enforce(request.context,
                           action,
                           item[self._resource],
                           pluralized=self._collection)
            if 'tenant_id' not in item[self._resource]:
                # no tenant_id - no quota check
                continue
            tenant_id = item[self._resource]['tenant_id']
            request_deltas[tenant_id] += 1
        # Quota enforcement
        reservations = []
        try:
            for (tenant, delta) in request_deltas.items():
                reservation = quota.QUOTAS.make_reservation(
                    request.context, tenant, {self._resource: delta},
                    self._plugin)
                reservations.append(reservation)
        except exceptions.QuotaResourceUnknown as e:
            # We don't want to quota this resource
            LOG.debug(e)

        def notify(create_result):
            # Ensure usage trackers for all resources affected by this API
            # operation are marked as dirty
            with request.context.session.begin():
                # Commit the reservation(s)
                for reservation in reservations:
                    quota.QUOTAS.commit_reservation(request.context,
                                                    reservation.reservation_id)
                resource_registry.set_resources_dirty(request.context)

            notifier_method = self._resource + '.create.end'
            self._notifier.info(request.context, notifier_method,
                                create_result)
            self._send_dhcp_notification(request.context, create_result,
                                         notifier_method)
            return create_result

        def do_create(body, bulk=False, emulated=False):
            kwargs = {self._parent_id_name: parent_id} if parent_id else {}
            if bulk and not emulated:
                obj_creator = getattr(self._plugin, "%s_bulk" % action)
            else:
                obj_creator = getattr(self._plugin, action)
            try:
                if emulated:
                    return self._emulate_bulk_create(obj_creator, request,
                                                     body, parent_id)
                else:
                    if self._collection in body:
                        # This is weird but fixing it requires changes to the
                        # plugin interface
                        kwargs.update({self._collection: body})
                    else:
                        kwargs.update({self._resource: body})
                    return obj_creator(request.context, **kwargs)
            except Exception:
                # In case of failure the plugin will always raise an
                # exception. Cancel the reservation
                with excutils.save_and_reraise_exception():
                    for reservation in reservations:
                        quota.QUOTAS.cancel_reservation(
                            request.context, reservation.reservation_id)

        if self._collection in body and self._native_bulk:
            # plugin does atomic bulk create operations
            objs = do_create(body, bulk=True)
            # Use first element of list to discriminate attributes which
            # should be removed because of authZ policies
            fields_to_strip = self._exclude_attributes_by_policy(
                request.context, objs[0])
            return notify({
                self._collection: [
                    self._filter_attributes(request.context,
                                            obj,
                                            fields_to_strip=fields_to_strip)
                    for obj in objs
                ]
            })
        else:
            if self._collection in body:
                # Emulate atomic bulk behavior
                objs = do_create(body, bulk=True, emulated=True)
                return notify({self._collection: objs})
            else:
                obj = do_create(body)
                self._send_nova_notification(action, {}, {self._resource: obj})
                return notify(
                    {self._resource: self._view(request.context, obj)})
Beispiel #52
0
    def update(self, request, id, body=None, **kwargs):
        """Updates the specified entity's attributes."""
        parent_id = kwargs.get(self._parent_id_name)
        try:
            payload = body.copy()
        except AttributeError:
            msg = _("Invalid format: %s") % request.body
            raise exceptions.BadRequest(resource='body', msg=msg)
        payload['id'] = id
        notifier_api.notify(request.context, self._publisher_id,
                            self._resource + '.update.start',
                            notifier_api.CONF.default_notification_level,
                            payload)
        body = Controller.prepare_request_body(request.context,
                                               body,
                                               False,
                                               self._resource,
                                               self._attr_info,
                                               allow_bulk=self._allow_bulk)
        action = self._plugin_handlers[self.UPDATE]
        # Load object to check authz
        # but pass only attributes in the original body and required
        # by the policy engine to the policy 'brain'
        field_list = [
            name for (name, value) in self._attr_info.iteritems()
            if (value.get('required_by_policy') or value.get('primary_key')
                or 'default' not in value)
        ]
        # Ensure policy engine is initialized
        policy.init()
        orig_obj = self._item(request,
                              id,
                              field_list=field_list,
                              parent_id=parent_id)
        orig_object_copy = copy.copy(orig_obj)
        orig_obj.update(body[self._resource])
        # Make a list of attributes to be updated to inform the policy engine
        # which attributes are set explicitly so that it can distinguish them
        # from the ones that are set to their default values.
        orig_obj[const.ATTRIBUTES_TO_UPDATE] = body[self._resource].keys()
        try:
            policy.enforce(request.context, action, orig_obj)
        except exceptions.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_updater = getattr(self._plugin, action)
        kwargs = {self._resource: body}
        if parent_id:
            kwargs[self._parent_id_name] = parent_id
        obj = obj_updater(request.context, id, **kwargs)
        result = {self._resource: self._view(request.context, obj)}
        notifier_method = self._resource + '.update.end'
        notifier_api.notify(request.context, self._publisher_id,
                            notifier_method,
                            notifier_api.CONF.default_notification_level,
                            result)
        self._send_dhcp_notification(request.context, result, notifier_method)
        self._nova_notifier.send_network_change(action, orig_object_copy,
                                                result)
        return result
Beispiel #53
0
 def setUp(self):
     super(RuleScopesTestCase, self).setUp()
     policy.init()
Beispiel #54
0
    def _update(self, request, id, body, **kwargs):
        body = Controller.prepare_request_body(request.context,
                                               body,
                                               False,
                                               self._resource,
                                               self._attr_info,
                                               allow_bulk=self._allow_bulk)
        action = self._plugin_handlers[self.UPDATE]
        # Load object to check authz
        # but pass only attributes in the original body and required
        # by the policy engine to the policy 'brain'
        field_list = [
            name for (name, value) in six.iteritems(self._attr_info)
            if (value.get('required_by_policy') or value.get('primary_key')
                or 'default' not in value)
        ]
        # Ensure policy engine is initialized
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        orig_obj = self._item(request,
                              id,
                              field_list=field_list,
                              parent_id=parent_id)
        orig_object_copy = copy.copy(orig_obj)
        orig_obj.update(body[self._resource])
        # Make a list of attributes to be updated to inform the policy engine
        # which attributes are set explicitly so that it can distinguish them
        # from the ones that are set to their default values.
        orig_obj[const.ATTRIBUTES_TO_UPDATE] = body[self._resource].keys()
        try:
            policy.enforce(request.context,
                           action,
                           orig_obj,
                           pluralized=self._collection)
        except oslo_policy.PolicyNotAuthorized:
            with excutils.save_and_reraise_exception() as ctxt:
                # If a tenant is modifying it's own object, it's safe to return
                # a 403. Otherwise, pretend that it doesn't exist to avoid
                # giving away information.
                if request.context.tenant_id != orig_obj['tenant_id']:
                    ctxt.reraise = False
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        obj_updater = getattr(self._plugin, action)
        kwargs = {self._resource: body}
        if parent_id:
            kwargs[self._parent_id_name] = parent_id
        obj = obj_updater(request.context, id, **kwargs)
        # Usually an update operation does not alter resource usage, but as
        # there might be side effects it might be worth checking for changes
        # in resource usage here as well (e.g: a tenant port is created when a
        # router interface is added)
        resource_registry.set_resources_dirty(request.context)

        result = {self._resource: self._view(request.context, obj)}
        notifier_method = self._resource + '.update.end'
        self._notifier.info(request.context, notifier_method, result)
        self._send_dhcp_notification(request.context, result, notifier_method)
        self._send_nova_notification(action, orig_object_copy, result)
        return result
Beispiel #55
0
    def create(self, request, body=None, **kwargs):
        """Creates a new instance of the requested entity."""
        parent_id = kwargs.get(self._parent_id_name)
        notifier_api.notify(request.context, self._publisher_id,
                            self._resource + '.create.start',
                            notifier_api.CONF.default_notification_level, body)
        body = Controller.prepare_request_body(request.context,
                                               body,
                                               True,
                                               self._resource,
                                               self._attr_info,
                                               allow_bulk=self._allow_bulk)
        action = self._plugin_handlers[self.CREATE]
        # Check authz
        if self._collection in body:
            # Have to account for bulk create
            items = body[self._collection]
            deltas = {}
            bulk = True
        else:
            items = [body]
            bulk = False
        # Ensure policy engine is initialized
        policy.init()
        for item in items:
            self._validate_network_tenant_ownership(request,
                                                    item[self._resource])
            policy.enforce(request.context, action, item[self._resource])
            try:
                tenant_id = item[self._resource]['tenant_id']
                count = quota.QUOTAS.count(request.context, self._resource,
                                           self._plugin, self._collection,
                                           tenant_id)
                if bulk:
                    delta = deltas.get(tenant_id, 0) + 1
                    deltas[tenant_id] = delta
                else:
                    delta = 1
                kwargs = {self._resource: count + delta}
            except exceptions.QuotaResourceUnknown as e:
                # We don't want to quota this resource
                LOG.debug(e)
            else:
                quota.QUOTAS.limit_check(request.context,
                                         item[self._resource]['tenant_id'],
                                         **kwargs)

        def notify(create_result):
            notifier_method = self._resource + '.create.end'
            notifier_api.notify(request.context, self._publisher_id,
                                notifier_method,
                                notifier_api.CONF.default_notification_level,
                                create_result)
            self._send_dhcp_notification(request.context, create_result,
                                         notifier_method)
            return create_result

        kwargs = {self._parent_id_name: parent_id} if parent_id else {}
        if self._collection in body and self._native_bulk:
            # plugin does atomic bulk create operations
            obj_creator = getattr(self._plugin, "%s_bulk" % action)
            objs = obj_creator(request.context, body, **kwargs)
            return notify({
                self._collection:
                [self._view(request.context, obj) for obj in objs]
            })
        else:
            obj_creator = getattr(self._plugin, action)
            if self._collection in body:
                # Emulate atomic bulk behavior
                objs = self._emulate_bulk_create(obj_creator, request, body,
                                                 parent_id)
                return notify({self._collection: objs})
            else:
                kwargs.update({self._resource: body})
                obj = obj_creator(request.context, **kwargs)

                self._nova_notifier.send_network_change(
                    action, {}, {self._resource: obj})
                return notify(
                    {self._resource: self._view(request.context, obj)})
Beispiel #56
0
    def setUp(self):
        super(NeutronPolicyTestCase, self).setUp()
        policy.reset()
        policy.init()
        self.addCleanup(policy.reset)
        self.admin_only_legacy = "role:admin"
        self.admin_or_owner_legacy = "role:admin or tenant_id:%(tenant_id)s"
        # Add a Fake 'something' resource to RESOURCE_ATTRIBUTE_MAP
        attributes.RESOURCE_ATTRIBUTE_MAP.update(FAKE_RESOURCE)
        self.rules = dict(
            (k, common_policy.parse_rule(v)) for k, v in {
                "context_is_admin":
                "role:admin",
                "admin_or_network_owner":
                "rule:context_is_admin or "
                "tenant_id:%(network:tenant_id)s",
                "admin_or_owner": ("rule:context_is_admin or "
                                   "tenant_id:%(tenant_id)s"),
                "admin_only":
                "rule:context_is_admin",
                "regular_user":
                "******",
                "shared":
                "field:networks:shared=True",
                "external":
                "field:networks:router:external=True",
                "default":
                '@',
                "create_network":
                "rule:admin_or_owner",
                "create_network:shared":
                "rule:admin_only",
                "update_network":
                '@',
                "update_network:shared":
                "rule:admin_only",
                "get_network":
                "rule:admin_or_owner or "
                "rule:shared or "
                "rule:external",
                "create_port:mac":
                "rule:admin_or_network_owner",
                "create_something":
                "rule:admin_or_owner",
                "create_something:attr":
                "rule:admin_or_owner",
                "create_something:attr:sub_attr_1":
                "rule:admin_or_owner",
                "create_something:attr:sub_attr_2":
                "rule:admin_only",
                "get_firewall_policy":
                "rule:admin_or_owner or "
                "rule:shared",
                "get_firewall_rule":
                "rule:admin_or_owner or "
                "rule:shared"
            }.items())

        def fakepolicyinit():
            common_policy.set_rules(common_policy.Rules(self.rules))

        def remove_fake_resource():
            del attributes.RESOURCE_ATTRIBUTE_MAP["%ss" % FAKE_RESOURCE_NAME]

        self.patcher = mock.patch.object(neutron.policy,
                                         'init',
                                         new=fakepolicyinit)
        self.patcher.start()
        self.addCleanup(self.patcher.stop)
        self.addCleanup(remove_fake_resource)
        self.context = context.Context('fake', 'fake', roles=['user'])
        plugin_klass = importutils.import_class(
            "neutron.db.db_base_plugin_v2.NeutronDbPluginV2")
        self.manager_patcher = mock.patch('neutron.manager.NeutronManager')
        fake_manager = self.manager_patcher.start()
        fake_manager_instance = fake_manager.return_value
        fake_manager_instance.plugin = plugin_klass()
        self.addCleanup(self.manager_patcher.stop)
Beispiel #57
0
def validate_policy(context, policy_name):
    policy.init()
    policy.enforce(context,
                   policy_name,
                   target={'project_id': context.project_id},
                   plugin=None)
Beispiel #58
0
    def _update(self, request, id, body, **kwargs):
        try:
            body = Controller.prepare_request_body(request.context,
                                                   body,
                                                   False,
                                                   self._resource,
                                                   self._attr_info,
                                                   allow_bulk=self._allow_bulk)
        except Exception as e:
            LOG.warning(
                "An exception happened while processing the request "
                "body. The exception message is [%s].", e)
            raise e

        action = self._plugin_handlers[self.UPDATE]
        # Load object to check authz
        # but pass only attributes in the original body and required
        # by the policy engine to the policy 'brain'
        field_list = [
            name for (name, value) in self._attr_info.items()
            if (value.get('required_by_policy') or value.get('primary_key')
                or 'default' not in value)
        ]
        # Ensure policy engine is initialized
        policy.init()
        parent_id = kwargs.get(self._parent_id_name)
        # If the parent_id exist, we should get orig_obj with
        # self._parent_id_name field.
        if parent_id and self._parent_id_name not in field_list:
            field_list.append(self._parent_id_name)
        orig_obj = self._item(request,
                              id,
                              field_list=field_list,
                              parent_id=parent_id)
        orig_object_copy = copy.copy(orig_obj)
        orig_obj.update(body[self._resource])
        # Make a list of attributes to be updated to inform the policy engine
        # which attributes are set explicitly so that it can distinguish them
        # from the ones that are set to their default values.
        orig_obj[constants.ATTRIBUTES_TO_UPDATE] = body[self._resource].keys()
        # Then get the ext_parent_id, format to ext_parent_parent_resource_id
        if self._parent_id_name in orig_obj:
            self._set_parent_id_into_ext_resources_request(
                request, orig_obj, parent_id)
        try:
            policy.enforce(request.context,
                           action,
                           orig_obj,
                           pluralized=self._collection)
        except oslo_policy.PolicyNotAuthorized:
            # To avoid giving away information, pretend that it
            # doesn't exist if policy does not authorize SHOW
            with excutils.save_and_reraise_exception() as ctxt:
                if not policy.check(request.context,
                                    self._plugin_handlers[self.SHOW],
                                    orig_obj,
                                    pluralized=self._collection):
                    ctxt.reraise = False
            msg = _('The resource could not be found.')
            raise webob.exc.HTTPNotFound(msg)

        if self._native_bulk and hasattr(self._plugin, "%s_bulk" % action):
            obj_updater = getattr(self._plugin, "%s_bulk" % action)
        else:
            obj_updater = getattr(self._plugin, action)

        kwargs = {self._resource: body}
        if parent_id:
            kwargs[self._parent_id_name] = parent_id
        obj = obj_updater(request.context, id, **kwargs)
        # Usually an update operation does not alter resource usage, but as
        # there might be side effects it might be worth checking for changes
        # in resource usage here as well (e.g: a tenant port is created when a
        # router interface is added)
        resource_registry.set_resources_dirty(request.context)

        result = {self._resource: self._view(request.context, obj)}
        notifier_method = self._resource + '.update.end'
        self._notifier.info(request.context, notifier_method, result)
        registry.publish(self._resource,
                         events.BEFORE_RESPONSE,
                         self,
                         payload=events.APIEventPayload(
                             request.context,
                             notifier_method,
                             action,
                             request_body=body,
                             states=(
                                 orig_object_copy,
                                 result,
                             ),
                             collection_name=self._collection))
        return result
Beispiel #59
0
 def setUp(self):
     super(TestResourceController, self).setUp()
     policy.init()
     self.addCleanup(policy.reset)
     self._gen_port()
Beispiel #60
0
    def before(self, state):
        # This hook should be run only for PUT,POST and DELETE methods and for
        # requests targeting a neutron resource
        resources = state.request.context.get('resources', [])
        if state.request.method not in ('POST', 'PUT', 'DELETE'):
            return
        # As this routine will likely alter the resources, do a shallow copy
        resources_copy = resources[:]
        neutron_context = state.request.context.get('neutron_context')
        resource = state.request.context.get('resource')
        # If there is no resource for this request, don't bother running authZ
        # policies
        if not resource:
            return
        controller = utils.get_controller(state)
        if not controller or utils.is_member_action(controller):
            return
        collection = state.request.context.get('collection')
        needs_prefetch = (state.request.method == 'PUT' or
                          state.request.method == 'DELETE')
        policy.init()

        action = controller.plugin_handlers[
            pecan_constants.ACTION_MAP[state.request.method]]

        # NOTE(salv-orlando): As bulk updates are not supported, in case of PUT
        # requests there will be only a single item to process, and its
        # identifier would have been already retrieved by the lookup process;
        # in the case of DELETE requests there won't be any item to process in
        # the request body
        original_resources = []
        if needs_prefetch:
            try:
                item = resources_copy.pop()
            except IndexError:
                # Ops... this was a delete after all!
                item = {}
            resource_id = state.request.context.get('resource_id')
            parent_id = state.request.context.get('parent_id')
            method = state.request.method
            resource_obj = fetch_resource(method, neutron_context, controller,
                                          collection, resource, resource_id,
                                          parent_id=parent_id)
            if resource_obj:
                original_resources.append(resource_obj)
                obj = copy.copy(resource_obj)
                obj.update(item)
                obj[const.ATTRIBUTES_TO_UPDATE] = item.keys()
                # Put back the item in the list so that policies could be
                # enforced
                resources_copy.append(obj)
        # TODO(salv-orlando): as other hooks might need to prefetch resources,
        # store them in the request context. However, this should be done in a
        # separate hook which is conveniently called before all other hooks
        state.request.context['original_resources'] = original_resources
        for item in resources_copy:
            try:
                policy.enforce(
                    neutron_context, action, item,
                    pluralized=collection)
            except oslo_policy.PolicyNotAuthorized:
                with excutils.save_and_reraise_exception() as ctxt:
                    # If a tenant is modifying it's own object, it's safe to
                    # return a 403. Otherwise, pretend that it doesn't exist
                    # to avoid giving away information.
                    orig_item_tenant_id = item.get('tenant_id')
                    if (needs_prefetch and
                        (neutron_context.tenant_id != orig_item_tenant_id or
                         orig_item_tenant_id is None)):
                        ctxt.reraise = False
                msg = _('The resource could not be found.')
                raise webob.exc.HTTPNotFound(msg)