def __call__(self, target, creds, enforcer): if self.target_field not in target: # policy needs a plugin check # target field is in the form resource:field # however if they're not separated by a colon, use an underscore # as a separator for backward compatibility def do_split(separator): parent_res, parent_field = self.target_field.split( separator, 1) return parent_res, parent_field for separator in (':', '_'): try: parent_res, parent_field = do_split(separator) break except ValueError: LOG.debug("Unable to find ':' as separator in %s.", self.target_field) else: # If we are here split failed with both separators err_reason = (_("Unable to find resource name in %s") % self.target_field) LOG.error(err_reason) raise exceptions.PolicyCheckError(policy="%s:%s" % (self.kind, self.match), reason=err_reason) parent_foreign_key = _RESOURCE_FOREIGN_KEYS.get( "%ss" % parent_res, None) if parent_res == constants.EXT_PARENT_PREFIX: for resource in service_const.EXT_PARENT_RESOURCE_MAPPING: key = "%s_%s_id" % (constants.EXT_PARENT_PREFIX, resource) if key in target: parent_foreign_key = key parent_res = resource break if not parent_foreign_key: err_reason = (_("Unable to verify match:%(match)s as the " "parent resource: %(res)s was not found") % { 'match': self.match, 'res': parent_res }) LOG.error(err_reason) raise exceptions.PolicyCheckError(policy="%s:%s" % (self.kind, self.match), reason=err_reason) target[self.target_field] = self._extract( parent_res, target[parent_foreign_key], parent_field) match = self.match % target if self.kind in creds: return match == str(creds[self.kind]) return False
def __call__(self, target, creds, enforcer): if self.target_field not in target: # policy needs a plugin check # target field is in the form resource:field # however if they're not separated by a colon, use an underscore # as a separator for backward compatibility def do_split(separator): parent_res, parent_field = self.target_field.split( separator, 1) return parent_res, parent_field for separator in (':', '_'): try: parent_res, parent_field = do_split(separator) break except ValueError: LOG.debug("Unable to find ':' as separator in %s.", self.target_field) else: # If we are here split failed with both separators err_reason = (_("Unable to find resource name in %s") % self.target_field) LOG.error(err_reason) raise exceptions.PolicyCheckError(policy="%s:%s" % (self.kind, self.match), reason=err_reason) parent_foreign_key = attributes.RESOURCE_FOREIGN_KEYS.get( "%ss" % parent_res, None) if not parent_foreign_key: err_reason = (_("Unable to verify match:%(match)s as the " "parent resource: %(res)s was not found") % { 'match': self.match, 'res': parent_res }) LOG.error(err_reason) raise exceptions.PolicyCheckError(policy="%s:%s" % (self.kind, self.match), reason=err_reason) if target[parent_foreign_key] is None: # The API user is trying to clear an attribute back to None # therefore there is no point in doing a policy check on "None" # as no resource will be found and an exception will be thrown. return True target[self.target_field] = self._extract( parent_res, target[parent_foreign_key], parent_field) match = self.match % target if self.kind in creds: return match == six.text_type(creds[self.kind]) return False
def __call__(self, target, creds, enforcer): if self.target_field not in target: # policy needs a plugin check # target field is in the form resource:field # however if they're not separated by a colon, use an underscore # as a separator for backward compatibility def do_split(separator): parent_res, parent_field = self.target_field.split( separator, 1) return parent_res, parent_field for separator in (':', '_'): try: parent_res, parent_field = do_split(separator) break except ValueError: LOG.debug("Unable to find ':' as separator in %s.", self.target_field) else: # If we are here split failed with both separators err_reason = (_("Unable to find resource name in %s") % self.target_field) LOG.error(err_reason) raise exceptions.PolicyCheckError( policy="%s:%s" % (self.kind, self.match), reason=err_reason) parent_foreign_key = attributes.RESOURCE_FOREIGN_KEYS.get( "%ss" % parent_res, None) if not parent_foreign_key: err_reason = (_("Unable to verify match:%(match)s as the " "parent resource: %(res)s was not found") % {'match': self.match, 'res': parent_res}) LOG.error(err_reason) raise exceptions.PolicyCheckError( policy="%s:%s" % (self.kind, self.match), reason=err_reason) # NOTE(salv-orlando): This check currently assumes the parent # resource is handled by the core plugin. It might be worth # having a way to map resources to plugins so to make this # check more general # NOTE(ihrachys): if import is put in global, circular # import failure occurs manager = importutils.import_module('neutron.manager') f = getattr(manager.NeutronManager.get_instance().plugin, 'get_%s' % parent_res) # f *must* exist, if not found it is better to let neutron # explode. Check will be performed with admin context context = importutils.import_module('neutron.context') try: data = f(context.get_admin_context(), target[parent_foreign_key], fields=[parent_field]) target[self.target_field] = data[parent_field] except exceptions.NotFound as e: # NOTE(kevinbenton): a NotFound exception can occur if a # list operation is happening at the same time as one of # the parents and its children being deleted. So we issue # a RetryRequest so the API will redo the lookup and the # problem items will be gone. raise db_exc.RetryRequest(e) except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_LE('Policy check error while calling %s!'), f) match = self.match % target if self.kind in creds: return match == six.text_type(creds[self.kind]) return False