NSX|V: Add allow icmp6 multicast rules in edge firewall

Vsphere7 started to block this traffic so adding those rules to be
backwards compatible.
In addition, add admin utility to fix existing edge firewalls:
nsxadmin -r routers -o nsx-update-fw

Change-Id: Ia5c2832e377a1a17ef279191ee91b6fec8f65443
This commit is contained in:
asarfaty 2020-07-07 14:05:15 +02:00 committed by Adit Sarfaty
parent 44206cac04
commit 0520483e2c
9 changed files with 92 additions and 3 deletions

View File

@ -186,6 +186,10 @@ Routers
nsxadmin -r routers -o migrate-vdr-dhcp
- Recreate the rules in the edge firewall of all routers
nsxadmin -r routers -o nsx-update-fw
Networks
~~~~~~~~

View File

@ -331,6 +331,9 @@ class RouterSharedDriver(router_driver.RouterBaseDriver):
if self.plugin.metadata_proxy_handler:
fw_rules += nsx_v_md_proxy.get_router_fw_rules()
# Add ipv6 icmp multicast rule (blocked in Vsphere 7 & up)
fw_rules.extend(self.plugin._get_firewall_icmpv6_rules())
# TODO(asarfaty): Add fwaas rules when fwaas supports shared routers
fw = {'firewall_rule_list': fw_rules}
edge_utils.update_firewall(self.nsx_v, context, target_router_id,

View File

@ -4255,6 +4255,16 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
self.update_router_firewall(context, router_id, router_db)
def _get_firewall_icmpv6_rules(self):
# Add ipv6 icmp multicast rule (blocked in Vsphere 7 & up)
application_ids = self.nsx_v.get_icmpv6_multicast_application_ids()
rules = [{
'name': 'IPV6-ICMP-multicast',
'action': 'allow',
'enabled': True,
'application': {'applicationId': application_ids}}]
return rules
def update_router_firewall(self, context, router_id, router_db):
"""Recreate all rules in the router edge firewall
@ -4280,6 +4290,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
if subnet_rules:
fw_rules.extend(subnet_rules)
# Add ipv6 icmp multicast rule (blocked in Vsphere 7 & up)
fw_rules.extend(self._get_firewall_icmpv6_rules())
# If metadata service is enabled, block access to inter-edge network
if self.metadata_proxy_handler and not distributed:
fw_rules += nsx_v_md_proxy.get_router_fw_rules()

View File

@ -40,6 +40,7 @@ class EdgeFirewallDriver(object):
def __init__(self):
super(EdgeFirewallDriver, self).__init__()
self._icmp_echo_application_ids = None
self._icmpv6_multicast_application_ids = None
def _convert_firewall_action(self, action):
if action == FWAAS_ALLOW:
@ -429,6 +430,20 @@ class EdgeFirewallDriver(object):
res_name='ICMP Echo', res_id='')
return self._icmp_echo_application_ids
def get_icmpv6_multicast_application_ids(self):
# check cached list first
# (if backend version changes, neutron should be restarted)
if self._icmpv6_multicast_application_ids:
return self._icmpv6_multicast_application_ids
self._icmpv6_multicast_application_ids = self.get_application_ids(
['IPv6-ICMP Version 2 Multicast Listener',
'IPv6-ICMP Multicast Listener Query'])
if not self._icmpv6_multicast_application_ids:
raise nsx_exc.NsxResourceNotFound(
res_name='ICMPv6 Multicast', res_id='')
return self._icmpv6_multicast_application_ids
def get_application_ids(self, application_names):
results = self.vcns.list_applications()
application_ids = []

View File

@ -224,6 +224,43 @@ def migrate_distributed_routers_dhcp(resource, event, trigger, **kwargs):
_update_vdr_fw_config(nsxv, binding['edge_id'])
@admin_utils.output_header
def update_edge_firewalls(resource, event, trigger, **kwargs):
context = n_context.get_admin_context()
updated_routers = []
with utils.NsxVPluginWrapper() as plugin:
shared_dr = plugin._router_managers.get_tenant_router_driver(
context, 'shared')
routers = plugin.get_routers(context)
for router in routers:
if router['id'] in updated_routers:
continue
if router.get('distributed', False):
# Distributes firewall - Update plr and tlr
router_db = plugin._get_router(context, router['id'])
plugin._update_subnets_and_dnat_firewall(context, router_db)
plr_id = plugin.edge_manager.get_plr_by_tlr_id(
context, router['id'])
if plr_id:
plugin._update_subnets_and_dnat_firewall(
context, router, router_id=plr_id)
updated_routers.append(router['id'])
elif router.get('router_type') == 'shared':
# Shared router
router_ids = shared_dr.edge_manager.get_routers_on_same_edge(
context, router['id'])
shared_dr._update_subnets_and_dnat_firewall_on_routers(
context, router['id'], router_ids)
updated_routers.extend(router_ids)
else:
# Exclusive router
router_db = plugin._get_router(context, router['id'])
plugin._update_subnets_and_dnat_firewall(context, router_db)
updated_routers.append(router['id'])
LOG.info("Updated edge firewall rules for routers: %s", updated_routers)
def _update_vdr_fw_config(nsxv, edge_id):
fw_config = nsxv.get_firewall(edge_id)[1]
@ -374,6 +411,10 @@ registry.subscribe(redistribute_routers,
constants.ROUTERS,
shell.Operations.NSX_REDISTRIBURE.value)
registry.subscribe(update_edge_firewalls,
constants.ROUTERS,
shell.Operations.NSX_UPDATE_FW.value)
registry.subscribe(list_orphaned_vnics,
constants.ORPHANED_VNICS,
shell.Operations.NSX_LIST.value)

View File

@ -56,6 +56,7 @@ class Operations(enum.Enum):
NSX_ENABLE_STANDBY_RELOCATION = 'nsx-enable-standby-relocation'
NSX_UPDATE_IP = 'nsx-update-ip'
NSX_UPDATE_TAGS = 'nsx-update-tags'
NSX_UPDATE_FW = 'nsx-update-fw'
NSX_RECREATE = 'nsx-recreate'
NSX_REDISTRIBURE = 'nsx-redistribute'
NSX_REORDER = 'nsx-reorder'
@ -234,7 +235,8 @@ nsxv_resources = {
constants.ROUTERS: Resource(constants.ROUTERS,
[Operations.NSX_RECREATE.value,
Operations.NSX_REDISTRIBURE.value,
Operations.MIGRATE_VDR_DHCP.value]),
Operations.MIGRATE_VDR_DHCP.value,
Operations.NSX_UPDATE_FW.value]),
constants.ORPHANED_VNICS: Resource(constants.ORPHANED_VNICS,
[Operations.NSX_LIST.value,
Operations.NSX_CLEAN.value]),

View File

@ -67,6 +67,8 @@ class NsxvFwaasTestCase(test_v_plugin.NsxVPluginV2TestCase):
return_value=self.port).start()
mock.patch.object(self.plugin, '_get_subnet_fw_rules',
return_value=[]).start()
mock.patch.object(self.plugin, '_get_firewall_icmpv6_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',

View File

@ -2506,6 +2506,11 @@ class L3NatTest(test_l3_plugin.L3BaseForIntTests, NsxVPluginV2TestCase):
class L3NatTestCaseBase(test_l3_plugin.L3NatTestCaseMixin):
def setUp(self, **kwargs):
super(L3NatTestCaseBase, self).setUp(**kwargs)
mock.patch.object(self.plugin, '_get_firewall_icmpv6_rules',
return_value=[]).start()
def test_create_floatingip_with_specific_ip(self):
with self.subnet(cidr='10.0.0.0/24',
enable_dhcp=False) as s:

View File

@ -1467,9 +1467,13 @@ class FakeVcns(object):
return {'policies': policies}
def list_applications(self):
applications = [{'name': 'ICMP Echo', 'objectID': 'application-333'},
applications = [{'name': 'ICMP Echo', 'objectId': 'application-333'},
{'name': 'IPv6-ICMP Echo',
'objectID': 'application-1001'}]
'objectId': 'application-1001'},
{'name': 'IPv6-ICMP Version 2 Multicast Listener',
'objectId': 'application-3'},
{'name': 'IPv6-ICMP Multicast Listener Query',
'objectId': 'application-4'}]
return applications