def _get_backend_router_and_fw_section(self, context, router_id): # find the backend router id in the DB nsx_router_id = nsx_db.get_nsx_router_id(context.session, router_id) if nsx_router_id is None: LOG.error("Didn't find nsx router for router %s", router_id) raise exceptions.FirewallInternalDriverError( driver=self.driver_name) # get the FW section id of the backend router try: section_id = self.nsx_router.get_firewall_section_id(nsx_router_id) except Exception as e: LOG.error( "Failed to find router firewall section for router " "%(id)s: %(e)s", { 'id': router_id, 'e': e }) raise exceptions.FirewallInternalDriverError( driver=self.driver_name) if section_id is None: LOG.error( "Failed to find router firewall section for router " "%(id)s.", {'id': router_id}) raise exceptions.FirewallInternalDriverError( driver=self.driver_name) return nsx_router_id, section_id
def _get_router_ids_for_fw(self, context, fw, to_delete=False): """Return the router_ids either from fw dict or tenant routers.""" routers_in_proj = self._get_routers_in_project(context, fw['tenant_id']) if self._has_router_insertion_fields(fw): # it is a new version of plugin (supports specific routers) ids = (fw['del-router-ids'] if to_delete else fw['add-router-ids']) project_ids = [ router['id'] for router in routers_in_proj if router['id'] in ids ] if len(project_ids) < len(ids): # This means that there is a router from another project. LOG.error( "Failed to attach routers from a different project " "to firewall %(fw)s: %(routers)s", { 'fw': fw['id'], 'routers': list(set(ids) - set(project_ids)) }) self.fwplugin_rpc.set_firewall_status(context, fw['id'], nl_constants.ERROR) raise exceptions.FirewallInternalDriverError( driver=self.fwaas_driver.driver_name) return ids else: return [router['id'] for router in routers_in_proj]
def apply_default_policy(self, agent_mode, apply_list, firewall): LOG.debug('Applying firewall %(fw_id)s for tenant %(tid)s', {'fw_id': firewall['id'], 'tid': firewall['tenant_id']}) fwid = firewall['id'] try: for router_info in apply_list: ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( agent_mode, router_info) for ipt_if_prefix in ipt_if_prefix_list: # the following only updates local memory; no hole in FW ipt_mgr = ipt_if_prefix['ipt'] self._remove_chains(fwid, ipt_mgr) self._remove_default_chains(ipt_mgr) # create default 'DROP ALL' policy chain self._add_default_policy_chain_v4v6(ipt_mgr) self._enable_policy_chain(fwid, ipt_if_prefix) # apply the changes immediately (no defer in firewall path) ipt_mgr.defer_apply_off() except (LookupError, RuntimeError): # catch known library exceptions and raise Fwaas generic exception LOG.exception( "Failed to apply default policy on firewall: %s", fwid) raise f_exc.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def _set_rules_on_router_edge(self, context, router_id, neutron_id, edge_id, fw_id, translated_rules, delete_fw=False): """Recreate router edge firewall rules Using the plugin code to recreate all the rules with the additional FWaaS rules. router_id is the is of the router about to be updated (in case of distributed router - the plr) neutron_id is the neutron router id """ # update the backend router_db = self.core_plugin._get_router(context, neutron_id) try: with locking.LockManager.get_lock(str(edge_id)): self.core_plugin.update_router_firewall( context, router_id, router_db, fwaas_rules=translated_rules) except Exception as e: # catch known library exceptions and raise Fwaas generic exception LOG.error("Failed to update firewall %(fw)s on edge %(edge_id)s: " "%(e)s", {'e': e, 'fw': fw_id, 'edge_id': edge_id}) raise exceptions.FirewallInternalDriverError( driver=self.driver_name)
def _get_driver_for_project(self, project): plugin_type = tvd_utils.get_tvd_plugin_type_for_project(project) if not self.drivers.get(plugin_type): LOG.error( "Project %(project)s with plugin %(plugin)s has no " "support for FWaaS V1", { 'project': project, 'plugin': plugin_type }) raise exceptions.FirewallInternalDriverError( driver=self.driver_name) return self.drivers[plugin_type]
def should_apply_firewall_to_router(self, router_data, raise_exception=True): """Return True if the firewall rules should be added the router Return False in those cases: - router without an external gateway (rule may be added later when there is a gateway) Raise an exception if the router is unsupported (and raise_exception is True): - shared router (not supported) - md proxy router (not supported) """ if (not router_data.get('distributed') and router_data.get('router_type') == 'shared'): LOG.error("Cannot apply firewall to shared router %s", router_data['id']) if raise_exception: raise exceptions.FirewallInternalDriverError( driver=self.driver_name) return False if router_data.get('name', '').startswith('metadata_proxy_router'): LOG.error("Cannot apply firewall to the metadata proxy router %s", router_data['id']) if raise_exception: raise exceptions.FirewallInternalDriverError( driver=self.driver_name) return False if not router_data.get('external_gateway_info'): LOG.info("Cannot apply firewall to router %s with no gateway", router_data['id']) return False return True
def create_firewall(self, agent_mode, apply_list, firewall): LOG.debug('Creating firewall %(fw_id)s for tenant %(tid)s', {'fw_id': firewall['id'], 'tid': firewall['tenant_id']}) try: if firewall['admin_state_up']: self._setup_firewall(agent_mode, apply_list, firewall) self._remove_conntrack_new_firewall(agent_mode, apply_list, firewall) self.pre_firewall = dict(firewall) else: self.apply_default_policy(agent_mode, apply_list, firewall) except (LookupError, RuntimeError): # catch known library exceptions and raise Fwaas generic exception LOG.exception("Failed to create firewall: %s", firewall['id']) raise f_exc.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def delete_firewall(self, agent_mode, apply_list, firewall): LOG.debug('Deleting firewall %(fw_id)s for tenant %(tid)s', {'fw_id': firewall['id'], 'tid': firewall['tenant_id']}) fwid = firewall['id'] try: for router_info in apply_list: ipt_if_prefix_list = self._get_ipt_mgrs_with_if_prefix( agent_mode, router_info) for ipt_if_prefix in ipt_if_prefix_list: ipt_mgr = ipt_if_prefix['ipt'] self._remove_chains(fwid, ipt_mgr) self._remove_default_chains(ipt_mgr) # apply the changes immediately (no defer in firewall path) ipt_mgr.defer_apply_off() self.pre_firewall = None except (LookupError, RuntimeError): # catch known library exceptions and raise Fwaas generic exception LOG.exception("Failed to delete firewall: %s", fwid) raise f_exc.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def _translate_action(fwaas_action, fwaas_rule_id): """Translate FWaaS action to NSX action""" if fwaas_action == fwaas_consts.FWAAS_ALLOW: return consts.FW_ACTION_ALLOW if fwaas_action == fwaas_consts.FWAAS_DENY: return consts.FW_ACTION_DROP if fwaas_action == fwaas_consts.FWAAS_REJECT: # reject is not supported by the nsx router firewall LOG.warning( "Reject action is not supported by the NSX backend " "for router firewall. Using %(action)s instead for " "rule %(id)s", { 'action': consts.FW_ACTION_DROP, 'id': fwaas_rule_id }) return consts.FW_ACTION_DROP # Unexpected action LOG.error("Unsupported FWAAS action %(action)s for rule %(id)s", { 'action': fwaas_action, 'id': fwaas_rule_id }) raise exceptions.FirewallInternalDriverError(driver=FWAAS_DRIVER_NAME)
def _apply_firewall(self, context, **fw_with_rules): tenant_id = fw_with_rules['tenant_id'] default_fwr = self._make_default_firewall_rule_dict(tenant_id) try: if fw_with_rules.get('del-router-ids', None): for fwr in list(fw_with_rules.get('firewall_rule_list', None)): self._delete_firewall_rule(context, tenant_id, **fwr) if default_fwr: self._delete_firewall_rule( context, tenant_id, **default_fwr) self.update_firewall_status( context, fw_with_rules['id'], n_consts.INACTIVE) if fw_with_rules.get('add-router-ids', None): vdom = getattr( fortinet_db.Fortinet_ML2_Namespace.query_one( context, tenant_id=tenant_id), 'vdom', None) if not vdom: raise fw_exc.FirewallInternalDriverError( driver='Fortinet_fwaas_plugin') if default_fwr: self._add_firewall_rule(context, tenant_id, **default_fwr) for fwr in reversed( list(fw_with_rules.get('firewall_rule_list', None))): self._add_firewall_rule(context, tenant_id, **fwr) self.update_firewall_status( context, fw_with_rules['id'], n_consts.ACTIVE) else: self.update_firewall_status( context, fw_with_rules['id'], n_consts.INACTIVE) except Exception as e: with excutils.save_and_reraise_exception(): LOG.error(_LE("apply_firewall %(fws)s failed"), {'fws': fw_with_rules}) utils._rollback_on_err(self, context, e) utils.update_status(self, context, t_consts.TaskStatus.COMPLETED)
def validate_backend_version(self): # prevent firewall actions if the backend does not support it if not self.backend_support: LOG.error("The NSX backend does not support router firewall") raise exceptions.FirewallInternalDriverError( driver=self.driver_name)