diff --git a/doc/source/admin_util.rst b/doc/source/admin_util.rst index ec7350f276..3a3d0ea5ef 100644 --- a/doc/source/admin_util.rst +++ b/doc/source/admin_util.rst @@ -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 ~~~~~~~~ diff --git a/vmware_nsx/plugins/nsx_v/drivers/shared_router_driver.py b/vmware_nsx/plugins/nsx_v/drivers/shared_router_driver.py index e354c718f1..4ba4c31964 100644 --- a/vmware_nsx/plugins/nsx_v/drivers/shared_router_driver.py +++ b/vmware_nsx/plugins/nsx_v/drivers/shared_router_driver.py @@ -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, diff --git a/vmware_nsx/plugins/nsx_v/plugin.py b/vmware_nsx/plugins/nsx_v/plugin.py index 112e5348e8..60adedac60 100644 --- a/vmware_nsx/plugins/nsx_v/plugin.py +++ b/vmware_nsx/plugins/nsx_v/plugin.py @@ -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() diff --git a/vmware_nsx/plugins/nsx_v/vshield/edge_firewall_driver.py b/vmware_nsx/plugins/nsx_v/vshield/edge_firewall_driver.py index b9d7414f2b..d916548ea9 100644 --- a/vmware_nsx/plugins/nsx_v/vshield/edge_firewall_driver.py +++ b/vmware_nsx/plugins/nsx_v/vshield/edge_firewall_driver.py @@ -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 = [] diff --git a/vmware_nsx/shell/admin/plugins/nsxv/resources/routers.py b/vmware_nsx/shell/admin/plugins/nsxv/resources/routers.py index 0a7e286222..efb4740caf 100644 --- a/vmware_nsx/shell/admin/plugins/nsxv/resources/routers.py +++ b/vmware_nsx/shell/admin/plugins/nsxv/resources/routers.py @@ -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) diff --git a/vmware_nsx/shell/resources.py b/vmware_nsx/shell/resources.py index 7ed642df1a..6fda8a9f7e 100644 --- a/vmware_nsx/shell/resources.py +++ b/vmware_nsx/shell/resources.py @@ -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' @@ -230,7 +231,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]), diff --git a/vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py b/vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py index 75bda89651..378a95f7a7 100644 --- a/vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py +++ b/vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py @@ -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', diff --git a/vmware_nsx/tests/unit/nsx_v/test_plugin.py b/vmware_nsx/tests/unit/nsx_v/test_plugin.py index 2c555e5aeb..bcae68b321 100644 --- a/vmware_nsx/tests/unit/nsx_v/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v/test_plugin.py @@ -2510,6 +2510,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: diff --git a/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py b/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py index 9eed5eafab..09789cc7d4 100644 --- a/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py +++ b/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py @@ -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