def _validate_ext_not_in_use_by_tenant(self, resource, event, trigger, payload=None): object_type = payload.metadata.get('object_type') policy = payload.latest_state context = payload.context if (object_type != 'network' or policy['action'] != 'access_as_external'): return new_project = None if event == events.BEFORE_UPDATE: new_project = payload.request_body['target_project'] if new_project == policy['target_project']: # nothing to validate if the tenant didn't change return gw_ports = port_obj.Port.get_gateway_port_ids_by_network( context, policy['object_id']) if policy['target_project'] != '*': filters = { 'gw_port_id': gw_ports, 'project_id': policy['target_project'] } # if there is a wildcard entry we can safely proceed without the # router lookup because they will have access either way if net_obj.NetworkRBAC.count(context, object_id=policy['object_id'], action='access_as_external', target_project='*'): return router_exist = l3_obj.Router.objects_exist(context, **filters) else: # deleting the wildcard is okay as long as the tenants with # attached routers have their own entries and the network is # not the default external network. if net_obj.ExternalNetwork.objects_exist( context, network_id=policy['object_id'], is_default=True): msg = _("Default external networks must be shared to " "everyone.") raise rbac_ext.RbacPolicyInUse(object_id=policy['object_id'], details=msg) projects = net_obj.NetworkRBAC.get_projects( context, object_id=policy['object_id'], action='access_as_external') projects_with_entries = [ project for project in projects if project != '*' ] if new_project: projects_with_entries.append(new_project) router_exist = l3_obj.Router.check_routers_not_owned_by_projects( context, gw_ports, projects_with_entries) if router_exist: msg = _("There are routers attached to this network that " "depend on this policy for access.") raise rbac_ext.RbacPolicyInUse(object_id=policy['object_id'], details=msg)
def _validate_ext_not_in_use_by_tenant(self, resource, event, trigger, context, object_type, policy, **kwargs): if (object_type != 'network' or policy['action'] != 'access_as_external'): return new_project = None if event == events.BEFORE_UPDATE: new_project = kwargs['policy_update']['target_tenant'] if new_project == policy['target_tenant']: # nothing to validate if the tenant didn't change return gw_ports = context.session.query(models_v2.Port.id).filter_by( device_owner=constants.DEVICE_OWNER_ROUTER_GW, network_id=policy['object_id']) gw_ports = [gw_port[0] for gw_port in gw_ports] rbac = rbac_db.NetworkRBAC if policy['target_tenant'] != '*': filters = { 'gw_port_id': gw_ports, 'project_id': policy['target_tenant'] } # if there is a wildcard entry we can safely proceed without the # router lookup because they will have access either way if context.session.query(rbac_db.NetworkRBAC.object_id).filter( rbac.object_id == policy['object_id'], rbac.action == 'access_as_external', rbac.target_tenant == '*').count(): return router_exist = l3_obj.Router.objects_exist(context, **filters) else: # deleting the wildcard is okay as long as the tenants with # attached routers have their own entries and the network is # not the default external network. if net_obj.ExternalNetwork.objects_exist( context, network_id=policy['object_id'], is_default=True): msg = _("Default external networks must be shared to " "everyone.") raise rbac_ext.RbacPolicyInUse(object_id=policy['object_id'], details=msg) projects_with_entries = (context.session.query( rbac.target_tenant).filter( rbac.object_id == policy['object_id'], rbac.action == 'access_as_external', rbac.target_tenant != '*')) projects_with_entries = [ projects_with_entry[0] for projects_with_entry in projects_with_entries ] if new_project: projects_with_entries.append(new_project) router_exist = l3_obj.Router.check_routers_not_owned_by_projects( context, gw_ports, projects_with_entries) if router_exist: msg = _("There are routers attached to this network that " "depend on this policy for access.") raise rbac_ext.RbacPolicyInUse(object_id=policy['object_id'], details=msg)
def _validate_ext_not_in_use_by_tenant(self, resource, event, trigger, context, object_type, policy, **kwargs): if (object_type != 'network' or policy['action'] != 'access_as_external'): return new_tenant = None if event == events.BEFORE_UPDATE: new_tenant = kwargs['policy_update']['target_tenant'] if new_tenant == policy['target_tenant']: # nothing to validate if the tenant didn't change return ports = context.session.query(models_v2.Port.id).filter_by( device_owner=DEVICE_OWNER_ROUTER_GW, network_id=policy['object_id']) router = context.session.query(l3_models.Router).filter( l3_models.Router.gw_port_id.in_(ports)) rbac = rbac_db.NetworkRBAC if policy['target_tenant'] != '*': router = router.filter( l3_models.Router.tenant_id == policy['target_tenant']) # if there is a wildcard entry we can safely proceed without the # router lookup because they will have access either way if context.session.query(rbac_db.NetworkRBAC).filter( rbac.object_id == policy['object_id'], rbac.action == 'access_as_external', rbac.target_tenant == '*').count(): return else: # deleting the wildcard is okay as long as the tenants with # attached routers have their own entries and the network is # not the default external network. is_default = context.session.query( ext_net_models.ExternalNetwork).filter_by( network_id=policy['object_id'], is_default=True).count() if is_default: msg = _("Default external networks must be shared to " "everyone.") raise rbac_ext.RbacPolicyInUse(object_id=policy['object_id'], details=msg) tenants_with_entries = ( context.session.query(rbac.target_tenant). filter(rbac.object_id == policy['object_id'], rbac.action == 'access_as_external', rbac.target_tenant != '*')) router = router.filter( ~l3_models.Router.tenant_id.in_(tenants_with_entries)) if new_tenant: # if this is an update we also need to ignore any router # interfaces that belong to the new target. router = router.filter( l3_models.Router.tenant_id != new_tenant) if router.count(): msg = _("There are routers attached to this network that " "depend on this policy for access.") raise rbac_ext.RbacPolicyInUse(object_id=policy['object_id'], details=msg)
def delete_rbac_policy(self, context, id): entry = self._get_rbac_policy(context, id) object_type = entry['object_type'] try: registry.notify(resources.RBAC_POLICY, events.BEFORE_DELETE, self, context=context, object_type=object_type, policy=entry) except c_exc.CallbackFailure as ex: raise ext_rbac.RbacPolicyInUse(object_id=entry['object_id'], details=ex) # make a dict copy because deleting the entry will nullify its # object_id link to network entry_dict = dict(entry) with context.session.begin(subtransactions=True): context.session.delete(entry) registry.notify(resources.RBAC_POLICY, events.AFTER_DELETE, self, context=context, object_type=object_type, policy=entry_dict) self.object_type_cache.pop(id, None)
def delete_rbac_policy(self, context, id): entry = self._get_rbac_policy(context, id) object_type = entry.db_model.object_type try: registry.publish(resources.RBAC_POLICY, events.BEFORE_DELETE, self, payload=events.DBEventPayload( context, states=(entry, ), resource_id=id, metadata={'object_type': object_type})) except c_exc.CallbackFailure as ex: raise ext_rbac.RbacPolicyInUse(object_id=entry.object_id, details=ex) # make a dict copy because deleting the entry will nullify its # object_id link to network entry_dict = entry.to_dict() entry.delete() registry.publish(resources.RBAC_POLICY, events.AFTER_DELETE, self, payload=events.DBEventPayload( context, states=(entry_dict, ), resource_id=id, metadata={'object_type': object_type})) self.object_type_cache.pop(id, None)
def delete_rbac_policy(self, context, id): entry = self._get_rbac_policy(context, id) object_type = entry['object_type'] try: registry.notify(RBAC_POLICY, events.BEFORE_DELETE, self, context=context, object_type=object_type, policy=entry) except c_exc.CallbackFailure as ex: raise ext_rbac.RbacPolicyInUse(object_id=entry['object_id'], details=ex) with context.session.begin(subtransactions=True): context.session.delete(entry) self.object_type_cache.pop(id, None)
def update_rbac_policy(self, context, id, rbac_policy): pol = rbac_policy['rbac_policy'] entry = self._get_rbac_policy(context, id) object_type = entry['object_type'] try: registry.notify(RBAC_POLICY, events.BEFORE_UPDATE, self, context=context, policy=entry, object_type=object_type, policy_update=pol) except c_exc.CallbackFailure as ex: raise ext_rbac.RbacPolicyInUse(object_id=entry['object_id'], details=ex) with context.session.begin(subtransactions=True): entry.update(pol) return self._make_rbac_policy_dict(entry)
def update_rbac_policy(self, context, id, rbac_policy): pol = rbac_policy['rbac_policy'] entry = self._get_rbac_policy(context, id) object_type = entry.db_model.object_type try: registry.notify(resources.RBAC_POLICY, events.BEFORE_UPDATE, self, context=context, policy=entry, object_type=object_type, policy_update=pol) except c_exc.CallbackFailure as ex: raise ext_rbac.RbacPolicyInUse(object_id=entry.object_id, details=ex) entry.update_fields(pol) entry.update() return self._make_rbac_policy_dict(entry)
def update_rbac_policy(self, context, id, rbac_policy): pol = rbac_policy['rbac_policy'] entry = self._get_rbac_policy(context, id) object_type = entry.db_model.object_type try: registry.publish(resources.RBAC_POLICY, events.BEFORE_UPDATE, self, payload=events.DBEventPayload( context, request_body=pol, states=(entry, ), resource_id=id, metadata={'object_type': object_type})) except c_exc.CallbackFailure as ex: raise ext_rbac.RbacPolicyInUse(object_id=entry.object_id, details=ex) entry.update_fields(pol) entry.update() return self._make_rbac_policy_dict(entry)
def update_rbac_policy(self, context, id, rbac_policy): pol = rbac_policy['rbac_policy'] # NOTE(ralonsoh): remove this conversion when "bp/keystone-v3" is # widely implemented in all OpenStack projects. try: pol['target_project'] = pol.pop('target_tenant') except KeyError: pass entry = self._get_rbac_policy(context, id) object_type = entry.db_model.object_type try: registry.publish(resources.RBAC_POLICY, events.BEFORE_UPDATE, self, payload=events.DBEventPayload( context, request_body=pol, states=(entry,), resource_id=id, metadata={'object_type': object_type})) except c_exc.CallbackFailure as ex: raise ext_rbac.RbacPolicyInUse(object_id=entry.object_id, details=ex) entry.update_fields(pol) entry.update() return self._make_rbac_policy_dict(entry)
def delete_rbac_policy(self, context, id): entry = self._get_rbac_policy(context, id) object_type = entry.db_model.object_type try: registry.notify(resources.RBAC_POLICY, events.BEFORE_DELETE, self, context=context, object_type=object_type, policy=entry) except c_exc.CallbackFailure as ex: raise ext_rbac.RbacPolicyInUse(object_id=entry.object_id, details=ex) # make a dict copy because deleting the entry will nullify its # object_id link to network entry_dict = entry.to_dict() entry.delete() registry.notify(resources.RBAC_POLICY, events.AFTER_DELETE, self, context=context, object_type=object_type, policy=entry_dict) self.object_type_cache.pop(id, None)
def raise_policy_in_use(): raise ext_rbac.RbacPolicyInUse( object_id=obj_id, details='tenant_id={}'.format(target_tenant))