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
def index(self, request, **kwargs): lbaas_plugin = manager.NeutronManager.get_service_plugins().get(plugin_const.LOADBALANCER) if not lbaas_plugin: return {"pools": []} policy.enforce(request.context, "get_%s" % LOADBALANCER_POOLS, {}, plugin=lbaas_plugin) return lbaas_plugin.list_pools_on_lbaas_agent(request.context, kwargs["agent_id"])
def index(self, request, **kwargs): lbaas_plugin = manager.NeutronManager.get_service_plugins().get(plugin_const.LOADBALANCER) if not lbaas_plugin: return policy.enforce(request.context, "get_%s" % LOADBALANCER_AGENT, {}, plugin=lbaas_plugin) return lbaas_plugin.get_lbaas_agent_hosting_pool(request.context, kwargs["pool_id"])
def delete(self, request, id, **kwargs): """Deletes the specified entity.""" notifier_api.notify(request.context, self._publisher_id, self._resource + '.delete.start', notifier_api.CONF.default_notification_level, {self._resource + '_id': id}) action = self._plugin_handlers[self.DELETE] # Check authz 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) obj_deleter(request.context, id, **kwargs) notifier_method = self._resource + '.delete.end' notifier_api.notify(request.context, self._publisher_id, notifier_method, notifier_api.CONF.default_notification_level, {self._resource + '_id': id}) result = {self._resource: self._view(request.context, obj)} self._send_dhcp_notification(request.context, result, notifier_method)
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)
def index(self, request, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "get_%s" % L3_ROUTERS, {}) return plugin.list_routers_on_l3_agent( request.context, kwargs['agent_id'])
def index(self, request, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "get_%s" % L3_AGENTS, {}) return plugin.list_l3_agents_hosting_router( request.context, kwargs['router_id'])
def index(self, request, **kwargs): plugin = directory.get_plugin() policy.enforce(request.context, "get_%s" % DHCP_AGENTS, {}) return plugin.list_dhcp_agents_hosting_network( request.context, kwargs['network_id'])
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)
def index(self, request, **kwargs): plugin = directory.get_plugin() policy.enforce(request.context, "get_%s" % DHCP_NETS, {}) return plugin.list_networks_on_dhcp_agent( request.context, kwargs['agent_id'])
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
def delete(self, request, id, **kwargs): plugin = manager.NeutronManager.get_plugin() policy.enforce(request.context, "delete_%s" % DHCP_NET, {}) return plugin.remove_network_from_dhcp_agent( request.context, kwargs['agent_id'], id)
def index(self, request, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "get_%s" % FIREWALLS, {}) return plugin.list_firewalls_on_l3_agent( request.context, kwargs['agent_id'])
def create(self, request, body, **kwargs): plugin = manager.NeutronManager.get_plugin() policy.enforce(request.context, "create_%s" % DHCP_NET, {}) return plugin.add_network_to_dhcp_agent( request.context, kwargs['agent_id'], body['network_id'])
def delete(self, request, id, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "delete_%s" % FIREWALL, {}) return plugin.remove_firewall_from_l3_agent( request.context, kwargs['agent_id'], id)
def delete(self, request, id, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "delete_%s" % L3_ROUTER, {}) return plugin.remove_router_from_l3_agent( request.context, kwargs['agent_id'], id)
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) 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): 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={}, )
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
def delete(self, request, id, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "delete_%s" % L3_ROUTER, {}) agent_id = kwargs["agent_id"] result = plugin.remove_router_from_l3_agent(request.context, agent_id, id) notify(request.context, "l3_agent.router.remove", id, agent_id) return result
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)
def test_templatized_enforcement(self): target_mine = {'tenant_id': 'fake'} target_not_mine = {'tenant_id': 'another'} action = "example:my_file" policy.enforce(self.context, action, target_mine) self.assertRaises(exceptions.PolicyNotAuthorized, policy.enforce, self.context, action, target_not_mine)
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
def create(self, request, body, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "create_%s" % L3_ROUTER, {}) agent_id = kwargs["agent_id"] router_id = body["router_id"] result = plugin.add_router_to_l3_agent(request.context, agent_id, router_id) notify(request.context, "l3_agent.router.add", router_id, agent_id) return result
def index(self, request, **kwargs): plugin = manager.NeutronManager.get_service_plugins().get( service_constants.L3_ROUTER_NAT) policy.enforce(request.context, "get_%s" % L3_AGENTS, {}) return plugin.list_l3_agents_hosting_router( request.context, kwargs['router_id'])
def index(self, request, **kwargs): plugin = manager.NeutronManager.get_service_plugins().get( service_constants.FIREWALL) policy.enforce(request.context, "get_%s" % FIREWALLS, {}) return plugin.list_l3_agents_hosting_firewall( request.context, kwargs['firewall_id'])
def test_ignore_case_role_check(self): lowercase_action = "example:lowercase_admin" uppercase_action = "example:uppercase_admin" # NOTE(dprince) we mix case in the Admin role here to ensure # case is ignored admin_context = context.Context('admin', 'fake', roles=['AdMiN']) policy.enforce(admin_context, lowercase_action, self.target) policy.enforce(admin_context, uppercase_action, self.target)
def create(self, request, body, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "create_%s" % FIREWALLS, {}) return plugin.add_firewall_to_l3_agent( request.context, kwargs['agent_id'], body['firewall_id'])
def create(self, request, body, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "create_%s" % L3_ROUTER, {}) return plugin.add_router_to_l3_agent( request.context, kwargs['agent_id'], body['router_id'])
def delete(self, request, id, **kwargs): plugin = directory.get_plugin() policy.enforce(request.context, "delete_%s" % DHCP_NET, {}) agent_id = kwargs['agent_id'] result = plugin.remove_network_from_dhcp_agent(request.context, agent_id, id) notify(request.context, 'dhcp_agent.network.remove', id, agent_id) return result
def test_enforce_regularuser_on_read(self): action = "get_network" target = {'shared': True, 'tenant_id': 'somebody_else'} result = policy.enforce(self.context, action, target) self.assertTrue(result)
def test_enforce_tenant_id_check(self): # Trigger a policy with rule admin_or_owner action = "create_network" target = {'tenant_id': 'fake'} result = policy.enforce(self.context, action, target) self.assertTrue(result)
def test_enforce_firewall_rule_shared(self): action = "get_firewall_rule" target = {'shared': True, 'tenant_id': 'somebody_else'} result = policy.enforce(self.context, action, target) self.assertTrue(result)
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 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
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') resource_obj = fetch_resource(neutron_context, controller, 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 conventietly 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. 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)
def test_early_OR_enforcement(self): action = "example:early_or_success" policy.enforce(self.context, action, self.target)
def test_enforce_http_true(self): self.useFixture(op_fixture.HttpCheckFixture()) action = "example:get_http" target = {} result = policy.enforce(self.context, action, target) self.assertTrue(result)
def test_delete_segment(self): self.assertTrue( policy.enforce(self.context, 'delete_segment', self.target))
def test_get_service_provider(self): self.assertTrue( policy.enforce(self.context, 'get_service_provider', self.target))
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 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) return notify( {self._resource: self._view(request.context, obj)})
def validate_policy(context, policy_name): policy.init() policy.enforce(context, policy_name, target={'project_id': context.project_id}, plugin=None)
def test_create_floatingip_with_ip_address(self): self.assertTrue( policy.enforce(self.context, "create_floatingip:floating_ip_address", self.target))
def test_get_floatingip(self): self.assertTrue( policy.enforce(self.context, "get_floatingip", self.target))
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, 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 n_exc.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 db_api.context_manager.writer.using(request.context): # 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) registry.notify(self._resource, events.BEFORE_RESPONSE, self, context=request.context, data=create_result, method_name=notifier_method, collection=self._collection, action=action, original={}) 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( 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) return notify({self._resource: self._view(request.context, obj)})
def test_enforce_subattribute(self): action = "create_" + FAKE_RESOURCE_NAME target = {'tenant_id': 'fake', 'attr': {'sub_attr_1': 'x'}} result = policy.enforce(self.context, action, target, None) self.assertTrue(result)
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 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() 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) 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
def test_not_found_policy_calls_default(self): policy.enforce(self.context, "example:noexist", {})
def create(self, request, body=None, **kwargs): """Creates a new instance of the requested entity.""" parent_id = kwargs.get(self._parent_id_name) self._notifier.info(request.context, self._resource + '.create.start', body) 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] 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], pluralized=self._collection) if 'tenant_id' not in item[self._resource]: # no tenant_id - no quota check continue 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' self._notifier.info(request.context, notifier_method, 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) # 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: 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._send_nova_notification(action, {}, {self._resource: obj}) return notify( {self._resource: self._view(request.context, obj)})
def index(self, request, **kwargs): plugin = directory.get_plugin() policy.enforce(request.context, "get_%s" % DHCP_AGENTS, {}) return plugin.list_dhcp_agents_hosting_network(request.context, kwargs['network_id'])
def index(self, request, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "get_%s" % HOSTING_DEVICE_CFG_AGENTS, {}) return plugin.list_cfg_agents_handling_hosting_device( request.context, kwargs['hosting_device_id'])
def test_get_log(self): self.assertTrue( policy.enforce(self.context, 'get_log', self.target))
def test_enforce_good_action(self): action = "example:allowed" result = policy.enforce(self.context, action, self.target) self.assertTrue(result)
def test_enforce_subattribute(self): action = "create_something" target = {'tenant_id': 'fake', 'attr': {'sub_attr_1': 'x'}} result = policy.enforce(self.context, action, target, None) self.assertEqual(result, True)
def index(self, request, **kwargs): plugin = directory.get_plugin() policy.enforce(request.context, "get_%s" % DHCP_NETS, {}) return plugin.list_networks_on_dhcp_agent(request.context, kwargs['agent_id'])
def test_enforce_http_true(self, mock_urlrequest): action = "example:get_http" target = {} result = policy.enforce(self.context, action, target) self.assertEqual(result, True)
def test_get_loggable_resource(self): self.assertTrue( policy.enforce(self.context, 'get_loggable_resource', self.target))
def test_create_network(self): self.assertTrue( policy.enforce(self.context, 'create_network', self.target)) self.assertRaises(base_policy.PolicyNotAuthorized, policy.enforce, self.context, 'create_network', self.alt_target)
def _test_enforce_adminonly_attribute(self, action): admin_context = context.get_admin_context() target = {'shared': True} result = policy.enforce(admin_context, action, target) self.assertEqual(result, True)
def index(self, request, **kwargs): plugin = self.get_plugin() policy.enforce(request.context, "get_%s" % CFG_AGENT_HOSTING_DEVICES, {}) return plugin.list_hosting_devices_handled_by_cfg_agent( request.context, kwargs['agent_id'])
def test_enforce_subattribute_as_list(self): action = "create_" + FAKE_RESOURCE_NAME target = {'tenant_id': 'fake', 'list_attr': [{'user_element': 'x'}]} result = policy.enforce(self.context, action, target, None) self.assertTrue(result)