NSX|P: Support fip ips in FWaaS groups

The default block rules rule has a group to match the network ips.
In case config firewall_match_internal_addr=False (match external)
we need to add the fip addresses as well.

Change-Id: Iec87b0032705811b81e02396137a183bc6a7c26c
This commit is contained in:
asarfaty 2020-05-11 16:22:55 +02:00
parent f7c679c6ec
commit 5e68678943
4 changed files with 105 additions and 26 deletions

View File

@ -3216,6 +3216,12 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
with excutils.save_and_reraise_exception():
self.delete_floatingip(context, new_fip['id'])
if (port_id and not cfg.CONF.nsx_p.firewall_match_internal_addr and
self.fwaas_callbacks):
# Might need to update a group related to this fip
self.fwaas_callbacks.update_segment_group(
context, router_id, port_data['network_id'])
return new_fip
def delete_floatingip(self, context, fip_id):
@ -3245,6 +3251,12 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
super(NsxPolicyPlugin, self).delete_floatingip(context, fip_id)
if (port_id and not cfg.CONF.nsx_p.firewall_match_internal_addr and
self.fwaas_callbacks):
# Might need to update a group related to this fip
self.fwaas_callbacks.update_segment_group(
context, router_id, port_data['network_id'])
def update_floatingip(self, context, fip_id, floatingip):
fip_data = floatingip['floatingip']
old_fip = self.get_floatingip(context, fip_id)

View File

@ -16,6 +16,7 @@
import random
import netaddr
from oslo_config import cfg
from oslo_log import log as logging
from neutron_lib.exceptions import firewall_v2 as exceptions
@ -179,14 +180,46 @@ class NsxpFwaasCallbacksV2(com_callbacks.NsxCommonv3FwaasCallbacksV2):
conditions=[expr], tags=tags)
return group_id
def _create_network_group(self, router_id, neutron_net_id):
def update_segment_group(self, context, router_id, neutron_net_id):
"""Update the segment group for fwaas rules in case fip changed"""
try:
group_id = '%s-%s' % (router_id, neutron_net_id)
self.nsxpolicy.group.get(policy_constants.DEFAULT_DOMAIN, group_id)
except Exception:
# no relevant group needs to be updated
return
self._create_network_group(context, router_id, neutron_net_id)
def _create_network_group(self, context, router_id, neutron_net_id):
scope_and_tag = "%s|%s" % ('os-neutron-net-id', neutron_net_id)
tags = []
tags = nsxlib_utils.add_v3_tag(tags, ROUTER_FW_TAG, router_id)
expr = self.nsxpolicy.group.build_condition(
cond_val=scope_and_tag,
cond_key=policy_constants.CONDITION_KEY_TAG,
cond_member_type=nsx_constants.TARGET_TYPE_LOGICAL_SWITCH)
if cfg.CONF.nsx_p.firewall_match_internal_addr:
expr = self.nsxpolicy.group.build_condition(
cond_val=scope_and_tag,
cond_key=policy_constants.CONDITION_KEY_TAG,
cond_member_type=nsx_constants.TARGET_TYPE_LOGICAL_SWITCH)
else:
# Need to add fips to the network cidr
group_ips = []
subnets = self.core_plugin.get_subnets_by_network(
context.elevated(), neutron_net_id)
for subnet in subnets:
group_ips.append(subnet['cidr'])
filters = {
'network_id': [neutron_net_id],
'device_owner': ['compute:nova']
}
vm_ports = self.core_plugin.get_ports(context.elevated(), filters)
for vm_port in vm_ports:
fip_filter = {'port_id': [vm_port['id']]}
fips = self.core_plugin.get_floatingips(
context.elevated(), fip_filter)
for fip in fips:
group_ips.append(fip['floating_ip_address'])
expr = self.nsxpolicy.group.build_ip_address_expression(
group_ips)
group_id = '%s-%s' % (router_id, neutron_net_id)
self.nsxpolicy.group.create_or_overwrite_with_conditions(
"Segment_%s" % neutron_net_id,
@ -254,14 +287,15 @@ class NsxpFwaasCallbacksV2(com_callbacks.NsxCommonv3FwaasCallbacksV2):
translated_rules.append(rule_entry)
return translated_rules
def _get_port_translated_rules(self, project_id, router_id, neutron_net_id,
def _get_port_translated_rules(self, context, project_id, router_id,
neutron_net_id,
firewall_group, plugin_rules):
"""Return the list of translated FWaaS rules per port
Add the egress/ingress rules of this port +
default drop rules in each direction for this port.
"""
net_group_id = self._create_network_group(
router_id, neutron_net_id)
context, router_id, neutron_net_id)
port_rules = []
# Add the firewall group ingress/egress rules only if the fw is up
if firewall_group['admin_state_up']:
@ -335,7 +369,7 @@ class NsxpFwaasCallbacksV2(com_callbacks.NsxCommonv3FwaasCallbacksV2):
# Add the FWaaS rules for this port:ingress/egress firewall
# rules + default ingress/egress drop rule for this port
fw_rules.extend(self._get_port_translated_rules(
project_id, router_id, port['network_id'], fwg,
context, project_id, router_id, port['network_id'], fwg,
plugin_rules))
# Add a default allow-all rule to all other traffic & ports

View File

@ -16,6 +16,7 @@ from neutron.db import db_base_plugin_v2
from neutron.db import l3_db
from neutron_lib.callbacks import registry
from neutron_lib import context
from oslo_config import cfg
from oslo_log import log as logging
from vmware_nsx.db import nsx_models
@ -23,10 +24,7 @@ from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
from vmware_nsx.shell.admin.plugins.nsxp.resources import utils as p_utils
from vmware_nsx.shell import resources as shell
from vmware_nsxlib.v3 import nsx_constants
from vmware_nsxlib.v3.policy import constants as policy_constants
from vmware_nsxlib.v3.policy import transaction as policy_trans
LOG = logging.getLogger(__name__)
@ -136,29 +134,37 @@ def update_nat_firewall_match(resource, event, trigger, **kwargs):
if firewall_match_str.lower() == 'internal':
new_firewall_match = policy_constants.NAT_FIREWALL_MATCH_INTERNAL
old_firewall_match = policy_constants.NAT_FIREWALL_MATCH_EXTERNAL
conf_match_internal = True
else:
new_firewall_match = policy_constants.NAT_FIREWALL_MATCH_EXTERNAL
old_firewall_match = policy_constants.NAT_FIREWALL_MATCH_INTERNAL
conf_match_internal = False
cfg.CONF.set_override('firewall_match_internal_addr',
conf_match_internal, 'nsx_p')
nsxpolicy = p_utils.get_connected_nsxpolicy()
plugin = RoutersPlugin()
ctx = context.get_admin_context()
neutron_routers = plugin.get_routers(ctx)
for router in neutron_routers:
rules = nsxpolicy.tier1_nat_rule.list(router['id'])
for rule in rules:
if not nsxpolicy.feature_supported(
nsx_constants.FEATURE_PARTIAL_UPDATES):
if rule['firewall_match'] == old_firewall_match:
with p_utils.NsxPolicyPluginWrapper() as plugin:
# Make sure FWaaS was initialized
plugin.init_fwaas_for_admin_utils()
ctx = context.get_admin_context()
neutron_routers = plugin.get_routers(ctx)
for router in neutron_routers:
rules = nsxpolicy.tier1_nat_rule.list(router['id'])
for rule in rules:
if rule.get('firewall_match') == old_firewall_match:
nsxpolicy.tier1_nat_rule.update(
router['id'], rule['id'],
firewall_match=new_firewall_match)
else:
with policy_trans.NsxPolicyTransaction():
if rule['firewall_match'] == old_firewall_match:
nsxpolicy.tier1_nat_rule.update(
router['id'], rule['id'],
firewall_match=new_firewall_match)
if plugin.fwaas_callbacks:
# get all router interface networks
interface_ports = plugin._get_router_interfaces(
ctx, router['id'])
for port in interface_ports:
plugin.fwaas_callbacks.update_segment_group(
ctx, router['id'], port['network_id'])
LOG.info("Done.")

View File

@ -15,6 +15,7 @@
from oslo_config import cfg
from neutron.db import l3_dvr_db # noqa
from neutron import manager
from neutron_lib import context
from neutron_lib.plugins import constants as const
from neutron_lib.plugins import directory
@ -23,6 +24,7 @@ from oslo_log import log as logging
from vmware_nsx.common import config
from vmware_nsx.plugins.nsx_p import plugin
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
from vmware_nsx.services.fwaas.nsx_p import fwaas_callbacks_v2
from vmware_nsx.shell.admin.plugins.common import formatters
LOG = logging.getLogger(__name__)
@ -85,3 +87,28 @@ class NsxPolicyPluginWrapper(plugin.NsxPolicyPlugin):
def __exit__(self, exc_type, exc_value, traceback):
directory.add_plugin(const.CORE, None)
def _init_fwaas_plugin(self, provider, callbacks_class, plugin_callbacks):
fwaas_plugin_class = manager.NeutronManager.load_class_for_provider(
'neutron.service_plugins', provider)
fwaas_plugin = fwaas_plugin_class()
self.fwaas_callbacks = callbacks_class(False)
# override the fwplugin_rpc since there is no RPC support in adminutils
if plugin_callbacks:
self.fwaas_callbacks.fwplugin_rpc = plugin_callbacks(fwaas_plugin)
self.init_is_complete = True
def init_fwaas_for_admin_utils(self):
# initialize the FWaaS plugin and callbacks
self.fwaas_callbacks = None
# This is an ugly patch to find out if fwaas is enabled
service_plugins = cfg.CONF.service_plugins
for srv_plugin in service_plugins:
if 'firewall' in srv_plugin or 'fwaas' in srv_plugin:
if 'v2' in srv_plugin:
# FWaaS V2
self._init_fwaas_plugin(
'firewall_v2',
fwaas_callbacks_v2.NsxpFwaasCallbacksV2,
None)
return