NSX|V: FWaaS-V2 driver
This patch adds a driver for FWaaS V2 support in the NSX-V plugin. It supports setting firewall rules per router interface port on the router edge firewall. In addition, the FWaaS TVD driver will now support NSX-V as well. The driver code is a combination of the NSX-V3 FWaas-V2 code, and the old NSX-V FWaaS-V1 code that is being deleted. Change-Id: Iacc7eaff0c70b68156516008cf0277c154edd76b
This commit is contained in:
parent
85c9ae8071
commit
a36a1dba74
@ -41,6 +41,25 @@ Optional: Update the nsx qos_peak_bw_multiplier in nsx.ini (default value is 2.0
|
|||||||
[NSX]
|
[NSX]
|
||||||
qos_peak_bw_multiplier = <i.e 10.0>
|
qos_peak_bw_multiplier = <i.e 10.0>
|
||||||
|
|
||||||
|
FWaaS (V2) Driver
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``::
|
||||||
|
|
||||||
|
[[local|localrc]]
|
||||||
|
enable_service q-fwaas-v2
|
||||||
|
Q_SERVICE_PLUGIN_CLASSES+=,firewall_v2
|
||||||
|
|
||||||
|
[[post-config|$NEUTRON_CONF]]
|
||||||
|
[fwaas]
|
||||||
|
enabled = True
|
||||||
|
driver = vmware_nsxv_edge_v2
|
||||||
|
|
||||||
|
[service_providers]
|
||||||
|
service_provider = FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default
|
||||||
|
|
||||||
|
Note - if devstack fails due to ml2_conf.ini being missing, please copy neutron/plugins/ml2/ml2_conf.ini.sample to /etc/neutron/plugins/ml2/ml2_conf.ini and stack again.
|
||||||
|
|
||||||
L2GW Driver
|
L2GW Driver
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
@ -188,8 +207,8 @@ FWaaS (V2) Driver
|
|||||||
Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``::
|
Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``::
|
||||||
|
|
||||||
[[local|localrc]]
|
[[local|localrc]]
|
||||||
ENABLED_SERVICES+=,q-fwaas-v2
|
enable_service q-fwaas-v2
|
||||||
Q_SERVICE_PLUGIN_CLASSES+=,neutron_fwaas.services.firewall.fwaas_plugin_v2.FirewallPluginV2
|
Q_SERVICE_PLUGIN_CLASSES+=,firewall_v2
|
||||||
|
|
||||||
[[post-config|$NEUTRON_CONF]]
|
[[post-config|$NEUTRON_CONF]]
|
||||||
[fwaas]
|
[fwaas]
|
||||||
@ -199,6 +218,8 @@ Add neutron-fwaas repo as an external repository and configure following flags i
|
|||||||
[service_providers]
|
[service_providers]
|
||||||
service_provider = FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default
|
service_provider = FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default
|
||||||
|
|
||||||
|
Note - if devstack fails due to ml2_conf.ini being missing, please copy neutron/plugins/ml2/ml2_conf.ini.sample to /etc/neutron/plugins/ml2/ml2_conf.ini and stack again.
|
||||||
|
|
||||||
LBaaS v2 Driver
|
LBaaS v2 Driver
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -297,14 +318,13 @@ Configure the service provider::
|
|||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
api_extensions_path = $DEST/neutron-lbaas/neutron_lbaas/extensions
|
api_extensions_path = $DEST/neutron-lbaas/neutron_lbaas/extensions
|
||||||
|
|
||||||
|
|
||||||
FWaaS (V2) Driver
|
FWaaS (V2) Driver
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``::
|
Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``::
|
||||||
|
|
||||||
[[local|localrc]]
|
[[local|localrc]]
|
||||||
ENABLED_SERVICES+=,q-fwaas-v2
|
enable_service q-fwaas-v2
|
||||||
Q_SERVICE_PLUGIN_CLASSES+=,vmware_nsxtvd_fwaasv2
|
Q_SERVICE_PLUGIN_CLASSES+=,vmware_nsxtvd_fwaasv2
|
||||||
|
|
||||||
[[post-config|$NEUTRON_CONF]]
|
[[post-config|$NEUTRON_CONF]]
|
||||||
@ -317,6 +337,8 @@ Add neutron-fwaas repo as an external repository and configure following flags i
|
|||||||
[service_providers]
|
[service_providers]
|
||||||
service_provider = FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default
|
service_provider = FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default
|
||||||
|
|
||||||
|
Note - if devstack fails due to ml2_conf.ini being missing, please copy neutron/plugins/ml2/ml2_conf.ini.sample to /etc/neutron/plugins/ml2/ml2_conf.ini and stack again.
|
||||||
|
|
||||||
L2GW Driver
|
L2GW Driver
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
prelude: >
|
||||||
|
The NSX-V plugin can suppport FWaaS-V2 for setting router edges firewall rules.
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The NSX-V plugin can suppport FWaaS-V2 for setting router edges firewall rules.
|
@ -36,7 +36,7 @@ neutron.core_plugins =
|
|||||||
vmware_dvs = vmware_nsx.plugin:NsxDvsPlugin
|
vmware_dvs = vmware_nsx.plugin:NsxDvsPlugin
|
||||||
vmware_nsxtvd = vmware_nsx.plugin:NsxTVDPlugin
|
vmware_nsxtvd = vmware_nsx.plugin:NsxTVDPlugin
|
||||||
firewall_drivers =
|
firewall_drivers =
|
||||||
vmware_nsxv3_edge = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v1:EdgeFwaasV3DriverV1
|
vmware_nsxv_edge_v2 = vmware_nsx.services.fwaas.nsx_v.edge_fwaas_driver_v2:EdgeFwaasVDriverV2
|
||||||
vmware_nsxv3_edge_v2 = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v2:EdgeFwaasV3DriverV2
|
vmware_nsxv3_edge_v2 = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v2:EdgeFwaasV3DriverV2
|
||||||
vmware_nsxtvd_edge_v2 = vmware_nsx.services.fwaas.nsx_tv.edge_fwaas_driver_v2:EdgeFwaasTVDriverV2
|
vmware_nsxtvd_edge_v2 = vmware_nsx.services.fwaas.nsx_tv.edge_fwaas_driver_v2:EdgeFwaasTVDriverV2
|
||||||
neutron.service_plugins =
|
neutron.service_plugins =
|
||||||
|
@ -144,6 +144,8 @@ from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
|||||||
from vmware_nsx.plugins.nsx_v.vshield import securitygroup_utils
|
from vmware_nsx.plugins.nsx_v.vshield import securitygroup_utils
|
||||||
from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
|
from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
|
||||||
from vmware_nsx.services.flowclassifier.nsx_v import utils as fc_utils
|
from vmware_nsx.services.flowclassifier.nsx_v import utils as fc_utils
|
||||||
|
from vmware_nsx.services.fwaas.common import utils as fwaas_utils
|
||||||
|
from vmware_nsx.services.fwaas.nsx_v import fwaas_callbacks_v2
|
||||||
from vmware_nsx.services.lbaas.nsx_v.implementation import healthmon_mgr
|
from vmware_nsx.services.lbaas.nsx_v.implementation import healthmon_mgr
|
||||||
from vmware_nsx.services.lbaas.nsx_v.implementation import l7policy_mgr
|
from vmware_nsx.services.lbaas.nsx_v.implementation import l7policy_mgr
|
||||||
from vmware_nsx.services.lbaas.nsx_v.implementation import l7rule_mgr
|
from vmware_nsx.services.lbaas.nsx_v.implementation import l7rule_mgr
|
||||||
@ -329,9 +331,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
# Make sure starting rpc listeners (for QoS and other agents)
|
# Make sure starting rpc listeners (for QoS and other agents)
|
||||||
# will happen only once
|
# will happen only once
|
||||||
self.start_rpc_listeners_called = False
|
self.start_rpc_listeners_called = False
|
||||||
|
self.fwaas_callbacks = None
|
||||||
# Init the FWaaS support
|
|
||||||
self._init_fwaas()
|
|
||||||
|
|
||||||
# Service insertion driver register
|
# Service insertion driver register
|
||||||
self._si_handler = fc_utils.NsxvServiceInsertionHandler(self)
|
self._si_handler = fc_utils.NsxvServiceInsertionHandler(self)
|
||||||
@ -412,6 +412,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
self.octavia_listener = octavia_listener.NSXOctaviaListener(
|
self.octavia_listener = octavia_listener.NSXOctaviaListener(
|
||||||
**octavia_objects)
|
**octavia_objects)
|
||||||
|
|
||||||
|
# Init the FWaaS support
|
||||||
|
self._init_fwaas()
|
||||||
|
|
||||||
self.init_is_complete = True
|
self.init_is_complete = True
|
||||||
|
|
||||||
def _get_octavia_objects(self):
|
def _get_octavia_objects(self):
|
||||||
@ -497,8 +500,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
|
|
||||||
def _init_fwaas(self):
|
def _init_fwaas(self):
|
||||||
# Bind FWaaS callbacks to the driver
|
# Bind FWaaS callbacks to the driver
|
||||||
#TODO(asarfaty): waiting for FWaaS v2 support
|
if fwaas_utils.is_fwaas_v2_plugin_enabled():
|
||||||
self.fwaas_callbacks = None
|
LOG.info("NSXv FWaaS v2 plugin enabled")
|
||||||
|
self.fwaas_callbacks = fwaas_callbacks_v2.NsxvFwaasCallbacksV2()
|
||||||
|
|
||||||
def _create_security_group_container(self):
|
def _create_security_group_container(self):
|
||||||
name = "OpenStack Security Group container"
|
name = "OpenStack Security Group container"
|
||||||
@ -3913,9 +3917,29 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
context, router_id, interface_info)
|
context, router_id, interface_info)
|
||||||
|
|
||||||
def remove_router_interface(self, context, router_id, interface_info):
|
def remove_router_interface(self, context, router_id, interface_info):
|
||||||
|
# Get the router interface port id
|
||||||
|
if self.fwaas_callbacks:
|
||||||
|
port_id = interface_info.get('port_id')
|
||||||
|
if not port_id:
|
||||||
|
subnet_id = interface_info['subnet_id']
|
||||||
|
subnet = self._get_subnet(context, subnet_id)
|
||||||
|
rport_qry = context.session.query(models_v2.Port)
|
||||||
|
ports = rport_qry.filter_by(
|
||||||
|
device_id=router_id,
|
||||||
|
device_owner=l3_db.DEVICE_OWNER_ROUTER_INTF,
|
||||||
|
network_id=subnet['network_id'])
|
||||||
|
for p in ports:
|
||||||
|
if p['fixed_ips'][0]['subnet_id'] == subnet_id:
|
||||||
|
port_id = p['id']
|
||||||
|
break
|
||||||
|
|
||||||
router_driver = self._find_router_driver(context, router_id)
|
router_driver = self._find_router_driver(context, router_id)
|
||||||
return router_driver.remove_router_interface(
|
result = router_driver.remove_router_interface(
|
||||||
context, router_id, interface_info)
|
context, router_id, interface_info)
|
||||||
|
# inform the FWaaS that interface port was removed
|
||||||
|
if self.fwaas_callbacks and port_id:
|
||||||
|
self.fwaas_callbacks.delete_port(context, port_id)
|
||||||
|
return result
|
||||||
|
|
||||||
def _get_floatingips_by_router(self, context, router_id):
|
def _get_floatingips_by_router(self, context, router_id):
|
||||||
fip_qry = context.session.query(l3_db_models.FloatingIP)
|
fip_qry = context.session.query(l3_db_models.FloatingIP)
|
||||||
@ -4015,35 +4039,22 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
router_db is the neutron router structure
|
router_db is the neutron router structure
|
||||||
router_id is the id of the actual router that will be updated on
|
router_id is the id of the actual router that will be updated on
|
||||||
the NSX (in case of distributed router it can be plr or tlr)
|
the NSX (in case of distributed router it can be plr or tlr)
|
||||||
|
|
||||||
|
This is just a wrapper of update_router_firewall
|
||||||
"""
|
"""
|
||||||
if not router_id:
|
if not router_id:
|
||||||
router_id = router_db['id']
|
router_id = router_db['id']
|
||||||
|
|
||||||
# Add fw rules if FWaaS is enabled
|
self.update_router_firewall(context, router_id, router_db)
|
||||||
# in case of a distributed-router:
|
|
||||||
# router['id'] is the id of the neutron router (=tlr)
|
|
||||||
# and router_id is the plr/tlr (the one that is being updated)
|
|
||||||
fwaas_rules = None
|
|
||||||
if (self.fwaas_callbacks and
|
|
||||||
self.fwaas_callbacks.should_apply_firewall_to_router(
|
|
||||||
context, router_db, router_id)):
|
|
||||||
fwaas_rules = self.fwaas_callbacks.get_fwaas_rules_for_router(
|
|
||||||
context, router_db['id'])
|
|
||||||
|
|
||||||
self.update_router_firewall(context, router_id, router_db,
|
def update_router_firewall(self, context, router_id, router_db):
|
||||||
fwaas_rules=fwaas_rules)
|
|
||||||
|
|
||||||
def update_router_firewall(self, context, router_id, router_db,
|
|
||||||
fwaas_rules=None):
|
|
||||||
"""Recreate all rules in the router edge firewall
|
"""Recreate all rules in the router edge firewall
|
||||||
|
|
||||||
router_db is the neutron router structure
|
router_db is the neutron router structure
|
||||||
router_id is the id of the actual router that will be updated on
|
router_id is the id of the actual router that will be updated on
|
||||||
the NSX (in case of distributed router it can be plr or tlr)
|
the NSX (in case of distributed router it can be plr or tlr)
|
||||||
if fwaas_rules is not none - this router is attached to a firewall
|
|
||||||
"""
|
"""
|
||||||
fw_rules = []
|
fw_rules = []
|
||||||
router_with_firewall = True if fwaas_rules is not None else False
|
|
||||||
edge_id = self._get_edge_id_by_rtr_id(context, router_id)
|
edge_id = self._get_edge_id_by_rtr_id(context, router_id)
|
||||||
|
|
||||||
# Add FW rule/s to open subnets firewall flows and static routes
|
# Add FW rule/s to open subnets firewall flows and static routes
|
||||||
@ -4056,33 +4067,41 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
if self.metadata_proxy_handler:
|
if self.metadata_proxy_handler:
|
||||||
fw_rules += nsx_v_md_proxy.get_router_fw_rules()
|
fw_rules += nsx_v_md_proxy.get_router_fw_rules()
|
||||||
|
|
||||||
# Add FWaaS rules
|
# Add FWaaS rules if FWaaS is enabled
|
||||||
if router_with_firewall and fwaas_rules:
|
if (self.fwaas_callbacks and
|
||||||
fw_rules += fwaas_rules
|
self.fwaas_callbacks.should_apply_firewall_to_router(
|
||||||
|
context, router_db, router_id)):
|
||||||
|
fwaas_rules = self.fwaas_callbacks.get_fwaas_rules_for_router(
|
||||||
|
context, router_db['id'], edge_id)
|
||||||
|
if fwaas_rules:
|
||||||
|
fw_rules += fwaas_rules
|
||||||
|
|
||||||
if not router_with_firewall:
|
# The rules added from here forward are relevant only for interface
|
||||||
dnat_rule = self._get_dnat_fw_rule(context, router_db)
|
# ports without fwaas firewall group
|
||||||
if dnat_rule:
|
# To allow this traffic on interfaces with firewall group, the user
|
||||||
fw_rules.append(dnat_rule)
|
# should add specific rules.
|
||||||
|
dnat_rule = self._get_dnat_fw_rule(context, router_db)
|
||||||
|
if dnat_rule:
|
||||||
|
fw_rules.append(dnat_rule)
|
||||||
|
|
||||||
# Add rule for not NAT-ed allocation pools
|
# Add rule for not NAT-ed allocation pools
|
||||||
alloc_pool_rule = self._get_allocation_pools_fw_rule(
|
alloc_pool_rule = self._get_allocation_pools_fw_rule(
|
||||||
context, router_db)
|
context, router_db)
|
||||||
if alloc_pool_rule:
|
if alloc_pool_rule:
|
||||||
fw_rules.append(alloc_pool_rule)
|
fw_rules.append(alloc_pool_rule)
|
||||||
|
|
||||||
# Add no-snat rules
|
# Add no-snat rules
|
||||||
nosnat_fw_rules = self._get_nosnat_subnets_fw_rules(
|
nosnat_fw_rules = self._get_nosnat_subnets_fw_rules(
|
||||||
context, router_db)
|
context, router_db)
|
||||||
fw_rules.extend(nosnat_fw_rules)
|
fw_rules.extend(nosnat_fw_rules)
|
||||||
|
|
||||||
vpn_plugin = directory.get_plugin(plugin_const.VPN)
|
vpn_plugin = directory.get_plugin(plugin_const.VPN)
|
||||||
if vpn_plugin:
|
if vpn_plugin:
|
||||||
vpn_driver = vpn_plugin.drivers[vpn_plugin.default_provider]
|
vpn_driver = vpn_plugin.drivers[vpn_plugin.default_provider]
|
||||||
vpn_rules = (
|
vpn_rules = (
|
||||||
vpn_driver._generate_ipsecvpn_firewall_rules(
|
vpn_driver._generate_ipsecvpn_firewall_rules(
|
||||||
self.plugin_type(), context, edge_id=edge_id))
|
self.plugin_type(), context, edge_id=edge_id))
|
||||||
fw_rules.extend(vpn_rules)
|
fw_rules.extend(vpn_rules)
|
||||||
|
|
||||||
# Get the load balancer rules in case they are refreshed
|
# Get the load balancer rules in case they are refreshed
|
||||||
# (relevant only for older LB that are still on the router edge)
|
# (relevant only for older LB that are still on the router edge)
|
||||||
@ -4102,11 +4121,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
|
|
||||||
fw = {'firewall_rule_list': fw_rules}
|
fw = {'firewall_rule_list': fw_rules}
|
||||||
try:
|
try:
|
||||||
# If we have a firewall we shouldn't add the default
|
edge_utils.update_firewall(self.nsx_v, context, router_id, fw)
|
||||||
# allow-external rule
|
|
||||||
allow_external = False if router_with_firewall else True
|
|
||||||
edge_utils.update_firewall(self.nsx_v, context, router_id, fw,
|
|
||||||
allow_external=allow_external)
|
|
||||||
except vsh_exc.ResourceNotFound:
|
except vsh_exc.ResourceNotFound:
|
||||||
LOG.error("Failed to update firewall for router %s",
|
LOG.error("Failed to update firewall for router %s",
|
||||||
router_id)
|
router_id)
|
||||||
|
@ -2577,7 +2577,8 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
|||||||
relay_target = []
|
relay_target = []
|
||||||
if self.fwaas_callbacks:
|
if self.fwaas_callbacks:
|
||||||
relay_target = (self.fwaas_callbacks.fwaas_driver.
|
relay_target = (self.fwaas_callbacks.fwaas_driver.
|
||||||
translate_addresses_to_target(set(relay_servers)))
|
translate_addresses_to_target(set(relay_servers),
|
||||||
|
self.plugin_type()))
|
||||||
|
|
||||||
dhcp_services = self._get_port_relay_services()
|
dhcp_services = self._get_port_relay_services()
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2017 VMware, Inc.
|
# Copyright 2018 VMware, Inc.
|
||||||
# All Rights Reserved
|
# All Rights Reserved
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
@ -48,22 +48,20 @@ class NsxFwaasCallbacksV2(firewall_l3_agent_v2.L3WithFWaaS):
|
|||||||
neutron_conf.agent_mode = 'nsx'
|
neutron_conf.agent_mode = 'nsx'
|
||||||
super(NsxFwaasCallbacksV2, self).__init__(conf=neutron_conf)
|
super(NsxFwaasCallbacksV2, self).__init__(conf=neutron_conf)
|
||||||
self.agent_api = DummyAgentApi()
|
self.agent_api = DummyAgentApi()
|
||||||
self._core_plugin = None
|
self.core_plugin = self._get_core_plugin()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def plugin_type(self):
|
def plugin_type(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@property
|
def _get_core_plugin(self):
|
||||||
def core_plugin(self):
|
"""Get the NSX core plugin"""
|
||||||
"""Get the NSX-V3 core plugin"""
|
core_plugin = directory.get_plugin()
|
||||||
if not self._core_plugin:
|
if core_plugin.is_tvd_plugin():
|
||||||
self._core_plugin = directory.get_plugin()
|
# get the plugin that match this driver
|
||||||
if self._core_plugin.is_tvd_plugin():
|
core_plugin = core_plugin.get_plugin_by_type(
|
||||||
# get the plugin that match this driver
|
self.plugin_type)
|
||||||
self._core_plugin = self._core_plugin.get_plugin_by_type(
|
return core_plugin
|
||||||
self.plugin_type)
|
|
||||||
return self._core_plugin
|
|
||||||
|
|
||||||
# Override functions using the agent_api that is not used by our plugin
|
# Override functions using the agent_api that is not used by our plugin
|
||||||
def _get_firewall_group_ports(self, context, firewall_group,
|
def _get_firewall_group_ports(self, context, firewall_group,
|
||||||
@ -203,3 +201,33 @@ class NsxFwaasCallbacksV2(firewall_l3_agent_v2.L3WithFWaaS):
|
|||||||
port_id=port_id).first()
|
port_id=port_id).first()
|
||||||
if entry:
|
if entry:
|
||||||
return entry.firewall_group_id
|
return entry.firewall_group_id
|
||||||
|
|
||||||
|
def should_apply_firewall_to_router(self, context, router_id):
|
||||||
|
"""Return True if there are FWaaS rules that are attached to an
|
||||||
|
interface of the given router.
|
||||||
|
"""
|
||||||
|
if not self.fwaas_enabled:
|
||||||
|
return False
|
||||||
|
|
||||||
|
ctx = context.elevated()
|
||||||
|
router_interfaces = self.core_plugin._get_router_interfaces(
|
||||||
|
ctx, router_id)
|
||||||
|
for port in router_interfaces:
|
||||||
|
fwg_id = self._get_port_firewall_group_id(ctx, port['id'])
|
||||||
|
if fwg_id:
|
||||||
|
# check the state of this firewall group
|
||||||
|
fwg = self._get_fw_group_from_plugin(ctx, fwg_id)
|
||||||
|
if fwg is not None:
|
||||||
|
if fwg.get('status') not in (nl_constants.ERROR,
|
||||||
|
nl_constants.PENDING_DELETE):
|
||||||
|
# Found a router interface port with rules
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def delete_port(self, context, port_id):
|
||||||
|
# Mark the FW group as inactive if this is the last port
|
||||||
|
fwg = self.get_port_fwg(context, port_id)
|
||||||
|
if (fwg and fwg.get('status') == nl_constants.ACTIVE and
|
||||||
|
len(fwg.get('ports', [])) <= 1):
|
||||||
|
self.fwplugin_rpc.set_firewall_group_status(
|
||||||
|
context, fwg['id'], nl_constants.INACTIVE)
|
||||||
|
93
vmware_nsx/services/fwaas/common/fwaas_driver_base.py
Normal file
93
vmware_nsx/services/fwaas/common/fwaas_driver_base.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# Copyright 2017 VMware, Inc.
|
||||||
|
# All Rights Reserved
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import abc
|
||||||
|
|
||||||
|
from oslo_log import helpers as log_helpers
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from neutron_lib.exceptions import firewall_v2 as exceptions
|
||||||
|
|
||||||
|
try:
|
||||||
|
from neutron_fwaas.services.firewall.service_drivers.agents.drivers \
|
||||||
|
import fwaas_base
|
||||||
|
except ImportError:
|
||||||
|
# FWaaS project no found
|
||||||
|
from vmware_nsx.services.fwaas.common import fwaas_mocks \
|
||||||
|
as fwaas_base
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class EdgeFwaasDriverBaseV2(fwaas_base.FwaasDriverBase):
|
||||||
|
"""NSX Base driver for Firewall As A Service - V2."""
|
||||||
|
|
||||||
|
def __init__(self, driver_name):
|
||||||
|
super(EdgeFwaasDriverBaseV2, self).__init__()
|
||||||
|
self.driver_name = driver_name
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def create_firewall_group(self, agent_mode, apply_list, firewall_group):
|
||||||
|
"""Create the Firewall with a given policy. """
|
||||||
|
self._validate_firewall_group(firewall_group)
|
||||||
|
self._update_backend_routers(apply_list, firewall_group['id'])
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def update_firewall_group(self, agent_mode, apply_list, firewall_group):
|
||||||
|
"""Remove previous policy and apply the new policy."""
|
||||||
|
self._validate_firewall_group(firewall_group)
|
||||||
|
self._update_backend_routers(apply_list, firewall_group['id'])
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def delete_firewall_group(self, agent_mode, apply_list, firewall_group):
|
||||||
|
"""Delete firewall.
|
||||||
|
|
||||||
|
Removes rules created by this instance from the backend firewall
|
||||||
|
And add the default allow rule.
|
||||||
|
"""
|
||||||
|
self._update_backend_routers(apply_list, firewall_group['id'])
|
||||||
|
|
||||||
|
@log_helpers.log_method_call
|
||||||
|
def apply_default_policy(self, agent_mode, apply_list, firewall_group):
|
||||||
|
"""Apply the default policy (deny all).
|
||||||
|
|
||||||
|
The backend firewall always has this policy (=deny all) as default,
|
||||||
|
so we only need to delete the current rules.
|
||||||
|
"""
|
||||||
|
self._update_backend_routers(apply_list, firewall_group['id'])
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def _update_backend_routers(self, apply_list, fwg_id):
|
||||||
|
"""Update all the affected router on the backend"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _validate_firewall_group(self, firewall_group):
|
||||||
|
"""Validate the rules in the firewall group"""
|
||||||
|
for rule in firewall_group['egress_rule_list']:
|
||||||
|
if rule.get('source_ip_address'):
|
||||||
|
# this rule cannot be used as egress rule
|
||||||
|
LOG.error("Rule %(id)s cannot be used in an egress "
|
||||||
|
"policy because it has a source",
|
||||||
|
{'id': rule['id']})
|
||||||
|
raise exceptions.FirewallInternalDriverError(
|
||||||
|
driver=self.driver_name)
|
||||||
|
for rule in firewall_group['ingress_rule_list']:
|
||||||
|
if rule.get('destination_ip_address'):
|
||||||
|
# this rule cannot be used as ingress rule
|
||||||
|
LOG.error("Rule %(id)s cannot be used in an ingress "
|
||||||
|
"policy because it has a destination",
|
||||||
|
{'id': rule['id']})
|
||||||
|
raise exceptions.FirewallInternalDriverError(
|
||||||
|
driver=self.driver_name)
|
@ -20,6 +20,7 @@ from neutron_lib.exceptions import firewall_v2 as exceptions
|
|||||||
|
|
||||||
from vmware_nsx.extensions import projectpluginmap
|
from vmware_nsx.extensions import projectpluginmap
|
||||||
from vmware_nsx.plugins.nsx import utils as tvd_utils
|
from vmware_nsx.plugins.nsx import utils as tvd_utils
|
||||||
|
from vmware_nsx.services.fwaas.nsx_v import edge_fwaas_driver_v2 as v_driver
|
||||||
from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_v2 as t_driver
|
from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_v2 as t_driver
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -36,15 +37,13 @@ except ImportError:
|
|||||||
|
|
||||||
class EdgeFwaasTVDriverV2(fwaas_base_v2.FwaasDriverBase):
|
class EdgeFwaasTVDriverV2(fwaas_base_v2.FwaasDriverBase):
|
||||||
"""NSX-TV driver for Firewall As A Service - V2.
|
"""NSX-TV driver for Firewall As A Service - V2.
|
||||||
|
|
||||||
This driver is just a wrapper calling the relevant nsx-v3 driver
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(EdgeFwaasTVDriverV2, self).__init__()
|
super(EdgeFwaasTVDriverV2, self).__init__()
|
||||||
self.driver_name = FWAAS_DRIVER_NAME
|
self.driver_name = FWAAS_DRIVER_NAME
|
||||||
|
|
||||||
# supported drivers (Only NSX-T):
|
# supported drivers:
|
||||||
self.drivers = {}
|
self.drivers = {}
|
||||||
try:
|
try:
|
||||||
self.drivers[projectpluginmap.NsxPlugins.NSX_T] = (
|
self.drivers[projectpluginmap.NsxPlugins.NSX_T] = (
|
||||||
@ -53,10 +52,20 @@ class EdgeFwaasTVDriverV2(fwaas_base_v2.FwaasDriverBase):
|
|||||||
LOG.warning("EdgeFwaasTVDriverV2 failed to initialize the NSX-T "
|
LOG.warning("EdgeFwaasTVDriverV2 failed to initialize the NSX-T "
|
||||||
"driver")
|
"driver")
|
||||||
self.drivers[projectpluginmap.NsxPlugins.NSX_T] = None
|
self.drivers[projectpluginmap.NsxPlugins.NSX_T] = None
|
||||||
|
try:
|
||||||
|
self.drivers[projectpluginmap.NsxPlugins.NSX_V] = (
|
||||||
|
v_driver.EdgeFwaasVDriverV2())
|
||||||
|
except Exception:
|
||||||
|
LOG.warning("EdgeFwaasTVDriverV2 failed to initialize the NSX-V "
|
||||||
|
"driver")
|
||||||
|
self.drivers[projectpluginmap.NsxPlugins.NSX_V] = None
|
||||||
|
|
||||||
def get_T_driver(self):
|
def get_T_driver(self):
|
||||||
return self.drivers[projectpluginmap.NsxPlugins.NSX_T]
|
return self.drivers[projectpluginmap.NsxPlugins.NSX_T]
|
||||||
|
|
||||||
|
def get_V_driver(self):
|
||||||
|
return self.drivers[projectpluginmap.NsxPlugins.NSX_V]
|
||||||
|
|
||||||
def _get_driver_for_project(self, project):
|
def _get_driver_for_project(self, project):
|
||||||
plugin_type = tvd_utils.get_tvd_plugin_type_for_project(project)
|
plugin_type = tvd_utils.get_tvd_plugin_type_for_project(project)
|
||||||
if not self.drivers.get(plugin_type):
|
if not self.drivers.get(plugin_type):
|
||||||
@ -87,8 +96,12 @@ class EdgeFwaasTVDriverV2(fwaas_base_v2.FwaasDriverBase):
|
|||||||
d = self._get_driver_for_project(firewall_group['tenant_id'])
|
d = self._get_driver_for_project(firewall_group['tenant_id'])
|
||||||
return d.apply_default_policy(agent_mode, apply_list, firewall_group)
|
return d.apply_default_policy(agent_mode, apply_list, firewall_group)
|
||||||
|
|
||||||
def translate_addresses_to_target(self, cidrs, fwaas_rule_id=None):
|
def translate_addresses_to_target(self, cidrs, plugin_type,
|
||||||
|
fwaas_rule_id=None):
|
||||||
# This api is called directly from the core plugin
|
# This api is called directly from the core plugin
|
||||||
# Assuming nsx-T as it is the only one supported now.
|
if not self.drivers.get(plugin_type):
|
||||||
return self.get_T_driver().translate_addresses_to_target(
|
LOG.error("%s has no support for plugin %s",
|
||||||
cidrs, fwaas_rule_id=fwaas_rule_id)
|
self.driver_name, plugin_type)
|
||||||
|
else:
|
||||||
|
return self.drivers[plugin_type].translate_addresses_to_target(
|
||||||
|
cidrs, fwaas_rule_id=fwaas_rule_id)
|
||||||
|
142
vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver_v2.py
Normal file
142
vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver_v2.py
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
# Copyright 2018 VMware, Inc.
|
||||||
|
# All Rights Reserved
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from neutron_lib import context as n_context
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from neutron_lib.exceptions import firewall_v2 as exceptions
|
||||||
|
from neutron_lib.plugins import directory
|
||||||
|
|
||||||
|
from vmware_nsx.common import locking
|
||||||
|
from vmware_nsx.extensions import projectpluginmap
|
||||||
|
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
||||||
|
from vmware_nsx.services.fwaas.common import fwaas_driver_base
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
FWAAS_DRIVER_NAME = 'Fwaas V2 NSX-V driver'
|
||||||
|
|
||||||
|
|
||||||
|
class EdgeFwaasVDriverV2(fwaas_driver_base.EdgeFwaasDriverBaseV2):
|
||||||
|
"""NSX-V driver for Firewall As A Service - V2."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(EdgeFwaasVDriverV2, self).__init__(FWAAS_DRIVER_NAME)
|
||||||
|
self._core_plugin = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def core_plugin(self):
|
||||||
|
"""Get the NSX-V core plugin"""
|
||||||
|
if not self._core_plugin:
|
||||||
|
self._core_plugin = directory.get_plugin()
|
||||||
|
if self._core_plugin.is_tvd_plugin():
|
||||||
|
self._core_plugin = self._core_plugin.get_plugin_by_type(
|
||||||
|
projectpluginmap.NsxPlugins.NSX_V)
|
||||||
|
if not self._core_plugin:
|
||||||
|
# The NSX-V plugin was not initialized
|
||||||
|
return
|
||||||
|
# make sure plugin init was completed
|
||||||
|
if not self._core_plugin.init_is_complete:
|
||||||
|
self._core_plugin.init_complete(None, None, {})
|
||||||
|
return self._core_plugin
|
||||||
|
|
||||||
|
def should_apply_firewall_to_router(self, router_data,
|
||||||
|
raise_exception=True):
|
||||||
|
"""Return True if the firewall rules allowed to 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 _update_backend_routers(self, apply_list, fwg_id):
|
||||||
|
"""Update all the affected routers on the backend"""
|
||||||
|
LOG.info("Updating routers firewall for firewall group %s", fwg_id)
|
||||||
|
context = n_context.get_admin_context()
|
||||||
|
routers = set()
|
||||||
|
routers_mapping = {}
|
||||||
|
# the apply_list is a list of tuples: routerInfo, port-id
|
||||||
|
for router_info, port_id in apply_list:
|
||||||
|
# Skip dummy entries that were added only to avoid errors
|
||||||
|
if isinstance(router_info, str):
|
||||||
|
continue
|
||||||
|
# Skip unsupported routers
|
||||||
|
if not self.should_apply_firewall_to_router(router_info.router):
|
||||||
|
continue
|
||||||
|
|
||||||
|
lookup_id = None
|
||||||
|
router_id = router_info.router_id
|
||||||
|
if router_info.router.get('distributed'):
|
||||||
|
# Distributed router (need to update the plr edge)
|
||||||
|
lookup_id = self.core_plugin.edge_manager.get_plr_by_tlr_id(
|
||||||
|
context, router_id)
|
||||||
|
else:
|
||||||
|
# Exclusive router
|
||||||
|
lookup_id = router_id
|
||||||
|
if lookup_id:
|
||||||
|
# look for the edge id in the DB
|
||||||
|
edge_id = edge_utils.get_router_edge_id(context, lookup_id)
|
||||||
|
if edge_id:
|
||||||
|
routers_mapping[router_id] = {'edge_id': edge_id,
|
||||||
|
'lookup_id': lookup_id}
|
||||||
|
routers.add(router_id)
|
||||||
|
|
||||||
|
# update each router once using the core plugin
|
||||||
|
for router_id in routers:
|
||||||
|
router_db = self.core_plugin._get_router(context, router_id)
|
||||||
|
edge_id = routers_mapping[router_id]['edge_id']
|
||||||
|
LOG.info("Updating FWaaS rules for router %s on edge %s",
|
||||||
|
router_id, edge_id)
|
||||||
|
router_lookup_id = routers_mapping[router_id]['lookup_id']
|
||||||
|
try:
|
||||||
|
with locking.LockManager.get_lock(str(edge_id)):
|
||||||
|
self.core_plugin.update_router_firewall(
|
||||||
|
context, router_lookup_id, router_db)
|
||||||
|
except Exception as e:
|
||||||
|
# catch known library exceptions and raise Fwaas generic
|
||||||
|
# exception
|
||||||
|
LOG.error("Failed to update firewall rules on edge "
|
||||||
|
"%(edge_id)s for router %(rtr)s: %(e)s",
|
||||||
|
{'e': e, 'rtr': router_id, 'edge_id': edge_id})
|
||||||
|
raise exceptions.FirewallInternalDriverError(
|
||||||
|
driver=self.driver_name)
|
167
vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks_v2.py
Normal file
167
vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks_v2.py
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
# Copyright 2018 VMware, Inc.
|
||||||
|
# All Rights Reserved
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from vmware_nsx.db import nsxv_db
|
||||||
|
from vmware_nsx.extensions import projectpluginmap
|
||||||
|
from vmware_nsx.plugins.nsx_v.vshield import edge_firewall_driver
|
||||||
|
from vmware_nsx.services.fwaas.common import fwaas_callbacks_v2 as \
|
||||||
|
com_callbacks
|
||||||
|
from vmware_nsx.services.fwaas.nsx_tv import edge_fwaas_driver_v2 as tv_driver
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
RULE_NAME_PREFIX = 'Fwaas-'
|
||||||
|
|
||||||
|
|
||||||
|
class NsxvFwaasCallbacksV2(com_callbacks.NsxFwaasCallbacksV2):
|
||||||
|
"""NSX-V RPC callbacks for Firewall As A Service - V2."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(NsxvFwaasCallbacksV2, self).__init__()
|
||||||
|
# update the fwaas driver in case of TV plugin
|
||||||
|
self.internal_driver = None
|
||||||
|
if self.fwaas_enabled:
|
||||||
|
if self.fwaas_driver.driver_name == tv_driver.FWAAS_DRIVER_NAME:
|
||||||
|
self.internal_driver = self.fwaas_driver.get_V_driver()
|
||||||
|
else:
|
||||||
|
self.internal_driver = self.fwaas_driver
|
||||||
|
|
||||||
|
@property
|
||||||
|
def plugin_type(self):
|
||||||
|
return projectpluginmap.NsxPlugins.NSX_V
|
||||||
|
|
||||||
|
def should_apply_firewall_to_router(self, context, router, router_id):
|
||||||
|
"""Return True if the FWaaS rules should be added to this router."""
|
||||||
|
# in case of a distributed-router:
|
||||||
|
# router['id'] is the id of the neutron router (=tlr)
|
||||||
|
# and router_id is the plr/tlr (the one that is being updated)
|
||||||
|
|
||||||
|
# First check if there are rules attached to this router
|
||||||
|
if not super(NsxvFwaasCallbacksV2,
|
||||||
|
self).should_apply_firewall_to_router(
|
||||||
|
context, router['id']):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# get all the relevant router info
|
||||||
|
# ("router" does not have all the fields)
|
||||||
|
ctx_elevated = context.elevated()
|
||||||
|
router_data = self.core_plugin.get_router(ctx_elevated, router['id'])
|
||||||
|
if not router_data:
|
||||||
|
LOG.error("Couldn't read router %s data", router['id'])
|
||||||
|
return False
|
||||||
|
|
||||||
|
if router_data.get('distributed'):
|
||||||
|
if router_id == router['id']:
|
||||||
|
# Do not add firewall rules on the tlr router.
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Check if the FWaaS driver supports this router
|
||||||
|
if not self.internal_driver.should_apply_firewall_to_router(
|
||||||
|
router_data, raise_exception=False):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_fwaas_rules_for_router(self, context, router_id, edge_id):
|
||||||
|
"""Return the list of (translated) FWaaS rules for this router."""
|
||||||
|
ctx_elevated = context.elevated()
|
||||||
|
router_interfaces = self.core_plugin._get_router_interfaces(
|
||||||
|
ctx_elevated, router_id)
|
||||||
|
|
||||||
|
fw_rules = []
|
||||||
|
# Add firewall rules per port attached to a firewall group
|
||||||
|
for port in router_interfaces:
|
||||||
|
fwg = self.get_port_fwg(ctx_elevated, port['id'])
|
||||||
|
if fwg:
|
||||||
|
# get the interface vnic
|
||||||
|
edge_vnic_bind = nsxv_db.get_edge_vnic_binding(
|
||||||
|
context.session, edge_id, port['network_id'])
|
||||||
|
vnic_id = 'vnic-index-%s' % edge_vnic_bind.vnic_index
|
||||||
|
# Add the FWaaS rules for this port
|
||||||
|
fw_rules.extend(
|
||||||
|
self.get_port_translated_rules(vnic_id, fwg))
|
||||||
|
|
||||||
|
return fw_rules
|
||||||
|
|
||||||
|
def get_port_translated_rules(self, vnic_id, firewall_group):
|
||||||
|
"""Return the list of translated rules per port
|
||||||
|
|
||||||
|
Ingress/Egress firewall rules + default ingress/egress drop
|
||||||
|
"""
|
||||||
|
port_rules = []
|
||||||
|
logged = False
|
||||||
|
# Add the firewall group ingress/egress rules only if the fw is up
|
||||||
|
if firewall_group['admin_state_up']:
|
||||||
|
port_rules.extend(self.translate_rules(
|
||||||
|
firewall_group['ingress_rule_list'],
|
||||||
|
replace_dest=vnic_id,
|
||||||
|
logged=logged,
|
||||||
|
is_ingress=True))
|
||||||
|
port_rules.extend(self.translate_rules(
|
||||||
|
firewall_group['egress_rule_list'],
|
||||||
|
replace_src=vnic_id,
|
||||||
|
logged=logged,
|
||||||
|
is_ingress=False))
|
||||||
|
|
||||||
|
# Add ingress/egress block rules for this port
|
||||||
|
port_rules.extend([
|
||||||
|
{'name': "Block port ingress",
|
||||||
|
'action': edge_firewall_driver.FWAAS_DENY,
|
||||||
|
'destination_vnic_groups': [vnic_id],
|
||||||
|
'logged': logged},
|
||||||
|
{'name': "Block port egress",
|
||||||
|
'action': edge_firewall_driver.FWAAS_DENY,
|
||||||
|
'source_vnic_groups': [vnic_id],
|
||||||
|
'logged': logged}])
|
||||||
|
|
||||||
|
return port_rules
|
||||||
|
|
||||||
|
def translate_rules(self, fwaas_rules, replace_dest=None, replace_src=None,
|
||||||
|
logged=False, is_ingress=True):
|
||||||
|
translated_rules = []
|
||||||
|
for rule in fwaas_rules:
|
||||||
|
if not rule['enabled']:
|
||||||
|
# skip disabled rules
|
||||||
|
continue
|
||||||
|
# Make sure the rule has a name, and it starts with the prefix
|
||||||
|
# (backend max name length is 30)
|
||||||
|
if rule.get('name'):
|
||||||
|
rule['name'] = RULE_NAME_PREFIX + rule['name']
|
||||||
|
else:
|
||||||
|
rule['name'] = RULE_NAME_PREFIX + rule['id']
|
||||||
|
rule['name'] = rule['name'][:30]
|
||||||
|
if rule.get('id'):
|
||||||
|
# update rules ID to prevent DB duplications in
|
||||||
|
# NsxvEdgeFirewallRuleBinding
|
||||||
|
if is_ingress:
|
||||||
|
rule['id'] = ('ingress-%s' % rule['id'])[:36]
|
||||||
|
else:
|
||||||
|
rule['id'] = ('egress-%s' % rule['id'])[:36]
|
||||||
|
# source & destination should be lists
|
||||||
|
if replace_dest:
|
||||||
|
rule['destination_vnic_groups'] = [replace_dest]
|
||||||
|
elif rule.get('destination_ip_address'):
|
||||||
|
rule['destination_ip_address'] = [
|
||||||
|
rule['destination_ip_address']]
|
||||||
|
if replace_src:
|
||||||
|
rule['source_vnic_groups'] = [replace_src]
|
||||||
|
elif rule.get('source_ip_address'):
|
||||||
|
rule['source_ip_address'] = [rule['source_ip_address']]
|
||||||
|
if logged:
|
||||||
|
rule['logged'] = True
|
||||||
|
translated_rules.append(rule)
|
||||||
|
|
||||||
|
return translated_rules
|
@ -23,27 +23,21 @@ from neutron_lib.plugins import directory
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from vmware_nsx.extensions import projectpluginmap
|
from vmware_nsx.extensions import projectpluginmap
|
||||||
|
from vmware_nsx.services.fwaas.common import fwaas_driver_base
|
||||||
from vmware_nsxlib.v3 import nsx_constants as consts
|
from vmware_nsxlib.v3 import nsx_constants as consts
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
RULE_NAME_PREFIX = 'Fwaas-'
|
RULE_NAME_PREFIX = 'Fwaas-'
|
||||||
DEFAULT_RULE_NAME = 'Default LR Layer3 Rule'
|
DEFAULT_RULE_NAME = 'Default LR Layer3 Rule'
|
||||||
|
|
||||||
try:
|
|
||||||
from neutron_fwaas.services.firewall.service_drivers.agents.drivers \
|
|
||||||
import fwaas_base
|
|
||||||
except ImportError:
|
|
||||||
# FWaaS project no found
|
|
||||||
from vmware_nsx.services.fwaas.common import fwaas_mocks \
|
|
||||||
as fwaas_base
|
|
||||||
|
|
||||||
|
#TODO(asarfaty): this base class now serves only 1 driver and can be merged
|
||||||
class CommonEdgeFwaasV3Driver(fwaas_base.FwaasDriverBase):
|
# with it
|
||||||
|
class CommonEdgeFwaasV3Driver(fwaas_driver_base.EdgeFwaasDriverBaseV2):
|
||||||
"""Base class for NSX-V3 driver for Firewall As A Service - V1 & V2."""
|
"""Base class for NSX-V3 driver for Firewall As A Service - V1 & V2."""
|
||||||
|
|
||||||
def __init__(self, driver_exception, driver_name):
|
def __init__(self, driver_exception, driver_name):
|
||||||
super(CommonEdgeFwaasV3Driver, self).__init__()
|
super(CommonEdgeFwaasV3Driver, self).__init__(driver_name)
|
||||||
self.driver_name = driver_name
|
|
||||||
self.backend_support = True
|
self.backend_support = True
|
||||||
self.driver_exception = driver_exception
|
self.driver_exception = driver_exception
|
||||||
registry.subscribe(
|
registry.subscribe(
|
||||||
@ -139,7 +133,8 @@ class CommonEdgeFwaasV3Driver(fwaas_base.FwaasDriverBase):
|
|||||||
cidr,
|
cidr,
|
||||||
consts.IPV6 if net.version == 6 else consts.IPV4)
|
consts.IPV6 if net.version == 6 else consts.IPV4)
|
||||||
|
|
||||||
def translate_addresses_to_target(self, cidrs, fwaas_rule_id=None):
|
def translate_addresses_to_target(self, cidrs, plugin_type,
|
||||||
|
fwaas_rule_id=None):
|
||||||
translated_cidrs = []
|
translated_cidrs = []
|
||||||
for ip in cidrs:
|
for ip in cidrs:
|
||||||
res = self._translate_cidr(ip, fwaas_rule_id)
|
res = self._translate_cidr(ip, fwaas_rule_id)
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from neutron_lib import context as n_context
|
from neutron_lib import context as n_context
|
||||||
from oslo_log import helpers as log_helpers
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from neutron_lib.exceptions import firewall_v2 as exceptions
|
from neutron_lib.exceptions import firewall_v2 as exceptions
|
||||||
@ -35,36 +34,6 @@ class EdgeFwaasV3DriverV2(base_driver.CommonEdgeFwaasV3Driver):
|
|||||||
super(EdgeFwaasV3DriverV2, self).__init__(exception_cls,
|
super(EdgeFwaasV3DriverV2, self).__init__(exception_cls,
|
||||||
FWAAS_DRIVER_NAME)
|
FWAAS_DRIVER_NAME)
|
||||||
|
|
||||||
@log_helpers.log_method_call
|
|
||||||
def create_firewall_group(self, agent_mode, apply_list, firewall_group):
|
|
||||||
"""Create the Firewall with a given policy. """
|
|
||||||
self._validate_firewall_group(firewall_group)
|
|
||||||
self._update_backend_routers(apply_list, firewall_group['id'])
|
|
||||||
|
|
||||||
@log_helpers.log_method_call
|
|
||||||
def update_firewall_group(self, agent_mode, apply_list, firewall_group):
|
|
||||||
"""Remove previous policy and apply the new policy."""
|
|
||||||
self._validate_firewall_group(firewall_group)
|
|
||||||
self._update_backend_routers(apply_list, firewall_group['id'])
|
|
||||||
|
|
||||||
@log_helpers.log_method_call
|
|
||||||
def delete_firewall_group(self, agent_mode, apply_list, firewall_group):
|
|
||||||
"""Delete firewall.
|
|
||||||
|
|
||||||
Removes rules created by this instance from the backend firewall
|
|
||||||
And add the default allow rule.
|
|
||||||
"""
|
|
||||||
self._update_backend_routers(apply_list, firewall_group['id'])
|
|
||||||
|
|
||||||
@log_helpers.log_method_call
|
|
||||||
def apply_default_policy(self, agent_mode, apply_list, firewall_group):
|
|
||||||
"""Apply the default policy (deny all).
|
|
||||||
|
|
||||||
The backend firewall always has this policy (=deny all) as default,
|
|
||||||
so we only need to delete the current rules.
|
|
||||||
"""
|
|
||||||
self._update_backend_routers(apply_list, firewall_group['id'])
|
|
||||||
|
|
||||||
def _update_backend_routers(self, apply_list, fwg_id):
|
def _update_backend_routers(self, apply_list, fwg_id):
|
||||||
"""Update all the affected router on the backend"""
|
"""Update all the affected router on the backend"""
|
||||||
self.validate_backend_version()
|
self.validate_backend_version()
|
||||||
@ -121,22 +90,3 @@ class EdgeFwaasV3DriverV2(base_driver.CommonEdgeFwaasV3Driver):
|
|||||||
'direction': 'OUT'}])
|
'direction': 'OUT'}])
|
||||||
|
|
||||||
return port_rules
|
return port_rules
|
||||||
|
|
||||||
def _validate_firewall_group(self, firewall_group):
|
|
||||||
"""Validate the rules in the firewall group"""
|
|
||||||
for rule in firewall_group['egress_rule_list']:
|
|
||||||
if rule.get('source_ip_address'):
|
|
||||||
# this rule cannot be used as egress rule
|
|
||||||
LOG.error("Rule %(id)s cannot be used in an egress "
|
|
||||||
"policy because it has a source",
|
|
||||||
{'id': rule['id']})
|
|
||||||
raise exceptions.FirewallInternalDriverError(
|
|
||||||
driver=FWAAS_DRIVER_NAME)
|
|
||||||
for rule in firewall_group['ingress_rule_list']:
|
|
||||||
if rule.get('destination_ip_address'):
|
|
||||||
# this rule cannot be used as ingress rule
|
|
||||||
LOG.error("Rule %(id)s cannot be used in an ingress "
|
|
||||||
"policy because it has a destination",
|
|
||||||
{'id': rule['id']})
|
|
||||||
raise exceptions.FirewallInternalDriverError(
|
|
||||||
driver=FWAAS_DRIVER_NAME)
|
|
||||||
|
288
vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py
Normal file
288
vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
# Copyright 2018 VMware, Inc.
|
||||||
|
# All Rights Reserved
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import copy
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from neutron_lib.exceptions import firewall_v2 as exceptions
|
||||||
|
from neutron_lib.plugins import directory
|
||||||
|
|
||||||
|
from vmware_nsx.db import nsxv_models
|
||||||
|
from vmware_nsx.plugins.nsx_v.vshield import edge_firewall_driver
|
||||||
|
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
||||||
|
from vmware_nsx.services.fwaas.nsx_v import edge_fwaas_driver_v2
|
||||||
|
from vmware_nsx.services.fwaas.nsx_v import fwaas_callbacks_v2
|
||||||
|
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_v_plugin
|
||||||
|
|
||||||
|
FAKE_FW_ID = 'fake_fw_uuid'
|
||||||
|
FAKE_ROUTER_ID = 'fake_rtr_uuid'
|
||||||
|
FAKE_PORT_ID = 'fake_port_uuid'
|
||||||
|
FAKE_NET_ID = 'fake_net_uuid'
|
||||||
|
FAKE_DB_OBJ = nsxv_models.NsxvEdgeVnicBinding(vnic_index='1')
|
||||||
|
|
||||||
|
|
||||||
|
class NsxvFwaasTestCase(test_v_plugin.NsxVPluginV2TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(NsxvFwaasTestCase, self).setUp()
|
||||||
|
self.firewall = edge_fwaas_driver_v2.EdgeFwaasVDriverV2()
|
||||||
|
|
||||||
|
self.plugin = directory.get_plugin()
|
||||||
|
self.plugin.fwaas_callbacks = fwaas_callbacks_v2.\
|
||||||
|
NsxvFwaasCallbacksV2()
|
||||||
|
self.plugin.fwaas_callbacks.fwaas_enabled = True
|
||||||
|
self.plugin.fwaas_callbacks.fwaas_driver = self.firewall
|
||||||
|
self.plugin.fwaas_callbacks.internal_driver = self.firewall
|
||||||
|
self.plugin.init_is_complete = True
|
||||||
|
self.plugin.metadata_proxy_handler = None
|
||||||
|
|
||||||
|
# Start some mocks
|
||||||
|
self.router = {'id': FAKE_ROUTER_ID,
|
||||||
|
'external_gateway_info': {'network_id': 'external'}}
|
||||||
|
mock.patch.object(self.plugin, '_get_router',
|
||||||
|
return_value=self.router).start()
|
||||||
|
mock.patch.object(self.plugin, 'get_router',
|
||||||
|
return_value=self.router).start()
|
||||||
|
self.port = {'id': FAKE_PORT_ID, 'network_id': FAKE_NET_ID}
|
||||||
|
mock.patch.object(self.plugin, '_get_router_interfaces',
|
||||||
|
return_value=[self.port]).start()
|
||||||
|
mock.patch.object(self.plugin, 'get_port',
|
||||||
|
return_value=self.port).start()
|
||||||
|
mock.patch.object(self.plugin, '_get_subnet_fw_rules',
|
||||||
|
return_value=[]).start()
|
||||||
|
mock.patch.object(self.plugin, '_get_dnat_fw_rule',
|
||||||
|
return_value=[]).start()
|
||||||
|
mock.patch.object(self.plugin, '_get_allocation_pools_fw_rule',
|
||||||
|
return_value=[]).start()
|
||||||
|
mock.patch.object(self.plugin, '_get_nosnat_subnets_fw_rules',
|
||||||
|
return_value=[]).start()
|
||||||
|
|
||||||
|
def _fake_rules_v4(self, is_ingress=True, cidr='10.24.4.0/24'):
|
||||||
|
rule1 = {'enabled': True,
|
||||||
|
'action': 'allow',
|
||||||
|
'ip_version': 4,
|
||||||
|
'protocol': 'tcp',
|
||||||
|
'destination_port': '80',
|
||||||
|
'id': 'fake-fw-rule1',
|
||||||
|
'description': 'first rule',
|
||||||
|
'position': '0'}
|
||||||
|
rule2 = {'enabled': True,
|
||||||
|
'action': 'reject',
|
||||||
|
'ip_version': 4,
|
||||||
|
'protocol': 'tcp',
|
||||||
|
'destination_port': '22:24',
|
||||||
|
'source_port': '1:65535',
|
||||||
|
'id': 'fake-fw-rule2',
|
||||||
|
'position': '1'}
|
||||||
|
rule3 = {'enabled': True,
|
||||||
|
'action': 'deny',
|
||||||
|
'ip_version': 4,
|
||||||
|
'protocol': 'icmp',
|
||||||
|
'id': 'fake-fw-rule3',
|
||||||
|
'position': '2'}
|
||||||
|
rule4 = {'enabled': True,
|
||||||
|
'action': 'deny',
|
||||||
|
'ip_version': 4,
|
||||||
|
'id': 'fake-fw-rule4',
|
||||||
|
'position': '3'}
|
||||||
|
if is_ingress:
|
||||||
|
# source ips are allowed
|
||||||
|
rule1['source_ip_address'] = cidr
|
||||||
|
else:
|
||||||
|
# dest ips are allowed for egress rules
|
||||||
|
rule1['destination_ip_address'] = cidr
|
||||||
|
|
||||||
|
return [rule1, rule2, rule3, rule4]
|
||||||
|
|
||||||
|
def _fake_translated_rules(self, rules_list,
|
||||||
|
nsx_port_id,
|
||||||
|
is_ingress=True,
|
||||||
|
logged=False):
|
||||||
|
translated_rules = copy.copy(rules_list)
|
||||||
|
for rule in translated_rules:
|
||||||
|
if logged:
|
||||||
|
rule['logged'] = True
|
||||||
|
if is_ingress:
|
||||||
|
rule['destination_vnic_groups'] = ['vnic-index-1']
|
||||||
|
else:
|
||||||
|
rule['source_vnic_groups'] = ['vnic-index-1']
|
||||||
|
if rule.get('destination_ip_address'):
|
||||||
|
rule['destination_ip_address'] = [
|
||||||
|
rule['destination_ip_address']]
|
||||||
|
if rule.get('source_ip_address'):
|
||||||
|
rule['source_ip_address'] = [
|
||||||
|
rule['source_ip_address']]
|
||||||
|
rule['name'] = (fwaas_callbacks_v2.RULE_NAME_PREFIX +
|
||||||
|
(rule.get('name') or rule['id']))[:30]
|
||||||
|
if rule.get('id'):
|
||||||
|
if is_ingress:
|
||||||
|
rule['id'] = ('ingress-%s' % rule['id'])[:36]
|
||||||
|
else:
|
||||||
|
rule['id'] = ('egress-%s' % rule['id'])[:36]
|
||||||
|
|
||||||
|
return translated_rules
|
||||||
|
|
||||||
|
def _fake_empty_firewall_group(self):
|
||||||
|
fw_inst = {'id': FAKE_FW_ID,
|
||||||
|
'admin_state_up': True,
|
||||||
|
'tenant_id': 'tenant-uuid',
|
||||||
|
'ingress_rule_list': [],
|
||||||
|
'egress_rule_list': []}
|
||||||
|
return fw_inst
|
||||||
|
|
||||||
|
def _fake_firewall_group(self, rule_list, is_ingress=True,
|
||||||
|
admin_state_up=True):
|
||||||
|
_rule_list = copy.deepcopy(rule_list)
|
||||||
|
for rule in _rule_list:
|
||||||
|
rule['position'] = str(_rule_list.index(rule))
|
||||||
|
fw_inst = {'id': FAKE_FW_ID,
|
||||||
|
'admin_state_up': admin_state_up,
|
||||||
|
'tenant_id': 'tenant-uuid',
|
||||||
|
'ingress_rule_list': [],
|
||||||
|
'egress_rule_list': []}
|
||||||
|
if is_ingress:
|
||||||
|
fw_inst['ingress_rule_list'] = _rule_list
|
||||||
|
else:
|
||||||
|
fw_inst['egress_rule_list'] = _rule_list
|
||||||
|
return fw_inst
|
||||||
|
|
||||||
|
def _fake_firewall_group_with_admin_down(self, rule_list,
|
||||||
|
is_ingress=True):
|
||||||
|
return self._fake_firewall_group(
|
||||||
|
rule_list, is_ingress=is_ingress, admin_state_up=False)
|
||||||
|
|
||||||
|
def _fake_apply_list(self):
|
||||||
|
router_inst = self.router
|
||||||
|
router_info_inst = mock.Mock()
|
||||||
|
router_info_inst.router = router_inst
|
||||||
|
router_info_inst.router_id = FAKE_ROUTER_ID
|
||||||
|
apply_list = [(router_info_inst, FAKE_PORT_ID)]
|
||||||
|
return apply_list
|
||||||
|
|
||||||
|
def test_create_firewall_no_rules(self):
|
||||||
|
apply_list = self._fake_apply_list()
|
||||||
|
firewall = self._fake_empty_firewall_group()
|
||||||
|
with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg',
|
||||||
|
return_value=firewall),\
|
||||||
|
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||||
|
'_get_port_firewall_group_id',
|
||||||
|
return_value=FAKE_FW_ID),\
|
||||||
|
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||||
|
'_get_fw_group_from_plugin',
|
||||||
|
return_value=firewall),\
|
||||||
|
mock.patch("vmware_nsx.db.nsxv_db.get_edge_vnic_binding",
|
||||||
|
return_value=FAKE_DB_OBJ),\
|
||||||
|
mock.patch.object(edge_utils, "update_firewall") as update_fw,\
|
||||||
|
mock.patch.object(edge_utils, 'get_router_edge_id',
|
||||||
|
return_value='edge-1'):
|
||||||
|
self.firewall.create_firewall_group('nsx', apply_list, firewall)
|
||||||
|
# expecting 2 block rules for the logical port (egress & ingress)
|
||||||
|
# and last default allow all rule
|
||||||
|
expected_rules = [
|
||||||
|
{'name': "Block port ingress",
|
||||||
|
'action': edge_firewall_driver.FWAAS_DENY,
|
||||||
|
'destination_vnic_groups': ['vnic-index-1'],
|
||||||
|
'logged': False},
|
||||||
|
{'name': "Block port egress",
|
||||||
|
'action': edge_firewall_driver.FWAAS_DENY,
|
||||||
|
'source_vnic_groups': ['vnic-index-1'],
|
||||||
|
'logged': False}]
|
||||||
|
update_fw.assert_called_once_with(
|
||||||
|
self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID,
|
||||||
|
{'firewall_rule_list': expected_rules})
|
||||||
|
|
||||||
|
def _setup_firewall_with_rules(self, func, is_ingress=True):
|
||||||
|
apply_list = self._fake_apply_list()
|
||||||
|
rule_list = self._fake_rules_v4(is_ingress=is_ingress)
|
||||||
|
firewall = self._fake_firewall_group(rule_list, is_ingress=is_ingress)
|
||||||
|
with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg',
|
||||||
|
return_value=firewall),\
|
||||||
|
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||||
|
'_get_port_firewall_group_id',
|
||||||
|
return_value=FAKE_FW_ID),\
|
||||||
|
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||||
|
'_get_fw_group_from_plugin',
|
||||||
|
return_value=firewall),\
|
||||||
|
mock.patch("vmware_nsx.db.nsxv_db.get_edge_vnic_binding",
|
||||||
|
return_value=FAKE_DB_OBJ),\
|
||||||
|
mock.patch.object(edge_utils, "update_firewall") as update_fw,\
|
||||||
|
mock.patch.object(edge_utils, 'get_router_edge_id',
|
||||||
|
return_value='edge-1'):
|
||||||
|
func('nsx', apply_list, firewall)
|
||||||
|
expected_rules = self._fake_translated_rules(
|
||||||
|
rule_list,
|
||||||
|
'vnic-index-1', is_ingress=is_ingress) + [
|
||||||
|
{'name': "Block port ingress",
|
||||||
|
'action': edge_firewall_driver.FWAAS_DENY,
|
||||||
|
'destination_vnic_groups': ['vnic-index-1'],
|
||||||
|
'logged': False},
|
||||||
|
{'name': "Block port egress",
|
||||||
|
'action': edge_firewall_driver.FWAAS_DENY,
|
||||||
|
'source_vnic_groups': ['vnic-index-1'],
|
||||||
|
'logged': False}]
|
||||||
|
|
||||||
|
update_fw.assert_called_once_with(
|
||||||
|
self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID,
|
||||||
|
{'firewall_rule_list': expected_rules})
|
||||||
|
|
||||||
|
def test_create_firewall_with_ingress_rules(self):
|
||||||
|
self._setup_firewall_with_rules(self.firewall.create_firewall_group)
|
||||||
|
|
||||||
|
def test_update_firewall_with_ingress_rules(self):
|
||||||
|
self._setup_firewall_with_rules(self.firewall.update_firewall_group)
|
||||||
|
|
||||||
|
def test_create_firewall_with_egress_rules(self):
|
||||||
|
self._setup_firewall_with_rules(self.firewall.create_firewall_group,
|
||||||
|
is_ingress=False)
|
||||||
|
|
||||||
|
def test_update_firewall_with_egress_rules(self):
|
||||||
|
self._setup_firewall_with_rules(self.firewall.update_firewall_group,
|
||||||
|
is_ingress=False)
|
||||||
|
|
||||||
|
def test_create_firewall_with_illegal_rules(self):
|
||||||
|
"""Use ingress rules as the egress list and verify failure"""
|
||||||
|
apply_list = self._fake_apply_list()
|
||||||
|
rule_list = self._fake_rules_v4(is_ingress=True)
|
||||||
|
firewall = self._fake_firewall_group(rule_list, is_ingress=False)
|
||||||
|
self.assertRaises(exceptions.FirewallInternalDriverError,
|
||||||
|
self.firewall.create_firewall_group, 'nsx',
|
||||||
|
apply_list, firewall)
|
||||||
|
|
||||||
|
def test_delete_firewall(self):
|
||||||
|
apply_list = self._fake_apply_list()
|
||||||
|
firewall = self._fake_empty_firewall_group()
|
||||||
|
with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg',
|
||||||
|
return_value=None),\
|
||||||
|
mock.patch("vmware_nsx.db.db.get_nsx_switch_and_port_id",
|
||||||
|
return_value=('vnic-index-1', 0)),\
|
||||||
|
mock.patch.object(edge_utils, "update_firewall") as update_fw,\
|
||||||
|
mock.patch.object(edge_utils, 'get_router_edge_id',
|
||||||
|
return_value='edge-1'):
|
||||||
|
self.firewall.delete_firewall_group('nsx', apply_list, firewall)
|
||||||
|
update_fw.assert_called_once_with(
|
||||||
|
self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID,
|
||||||
|
{'firewall_rule_list': []})
|
||||||
|
|
||||||
|
def test_create_firewall_with_admin_down(self):
|
||||||
|
apply_list = self._fake_apply_list()
|
||||||
|
rule_list = self._fake_rules_v4()
|
||||||
|
firewall = self._fake_firewall_group_with_admin_down(rule_list)
|
||||||
|
with mock.patch.object(edge_utils, "update_firewall") as update_fw,\
|
||||||
|
mock.patch.object(edge_utils, 'get_router_edge_id',
|
||||||
|
return_value='edge-1'):
|
||||||
|
self.firewall.create_firewall_group('nsx', apply_list, firewall)
|
||||||
|
update_fw.assert_called_once_with(
|
||||||
|
self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID,
|
||||||
|
{'firewall_rule_list': []})
|
Loading…
x
Reference in New Issue
Block a user