Enhance IptablesFirewallDriver with remote address groups

This change enhances the IptablesFirewallDriver with support for remote
address groups. Previously, this feature was only available in the
OVSFirewallDriver. This commit harmonizes the capabilities across both
firewall drivers, and by inheritance also to OVSHybridIptablesFirewallDriver.

Background -
The Neutron API allows operators to configure remote address groups [1],
however the OVSHybridIptablesFirewallDriver and IptablesFirewallDriver do
not implement these remote group restrictions. When configuring security
group rules with remote address groups, connections get enabled
based on other rule parameters, ignoring the configured remote address
group restrictions.
This behaviour undocumented, and may lead to more-open-than-configured network
access.

Closes-Bug: #2058138
Change-Id: I76b3cb46ee603fa5e829537af41316bb42a6f30f
(cherry picked from commit 5e1188ef38)
(cherry picked from commit 0eccc52f82)
This commit is contained in:
Robert Breker 2024-03-17 14:43:50 +00:00 committed by Robert Breker
parent cc818385a1
commit 377e1f6838
3 changed files with 33 additions and 3 deletions

View File

@ -599,9 +599,15 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
rule, port, direction))
return port_rules
def _get_any_remote_group_id_in_rule(self, rule):
remote_group_id = rule.get('remote_group_id')
if not remote_group_id:
remote_group_id = rule.get('remote_address_group_id')
return remote_group_id
def _expand_sg_rule_with_remote_ips(self, rule, port, direction):
"""Expand a remote group rule to rule per remote group IP."""
remote_group_id = rule.get('remote_group_id')
remote_group_id = self._get_any_remote_group_id_in_rule(rule)
if remote_group_id:
ethertype = rule['ethertype']
port_ips = port.get('fixed_ips', [])
@ -623,7 +629,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
for sg_id in sg_ids:
for rule in self.sg_rules.get(sg_id, []):
if not direction or rule['direction'] == direction:
remote_sg_id = rule.get('remote_group_id')
remote_sg_id = self._get_any_remote_group_id_in_rule(rule)
ether_type = rule.get('ethertype')
if remote_sg_id and ether_type:
remote_sg_ids[ether_type].add(remote_sg_id)
@ -703,7 +709,7 @@ class IptablesFirewallDriver(firewall.FirewallDriver):
return args
def _convert_sg_rule_to_iptables_args(self, sg_rule):
remote_gid = sg_rule.get('remote_group_id')
remote_gid = self._get_any_remote_group_id_in_rule(sg_rule)
if self.enable_ipset and remote_gid:
return self._generate_ipset_rule_args(sg_rule, remote_gid)
else:

View File

@ -2375,6 +2375,22 @@ class IptablesFirewallEnhancedIpsetTestCase(BaseIptablesFirewallTestCase):
self.firewall.ipset.assert_has_calls(calls, True)
def test__get_any_remote_group_id_in_rule_with_remote_group(self):
sg_rule = {'direction': 'ingress',
'remote_group_id': FAKE_SGID,
'ethertype': _IPv4}
self.assertEqual(FAKE_SGID,
self.firewall._get_any_remote_group_id_in_rule(sg_rule))
def test__get_any_remote_group_id_in_rule_with_remote_address_group(self):
sg_rule = {'direction': 'ingress',
'remote_address_group_id': FAKE_SGID,
'ethertype': _IPv6}
self.assertEqual(FAKE_SGID,
self.firewall._get_any_remote_group_id_in_rule(sg_rule))
def test_sg_rule_expansion_with_remote_ips(self):
other_ips = [('10.0.0.2', 'fa:16:3e:aa:bb:c1'),
('10.0.0.3', 'fa:16:3e:aa:bb:c2'),

View File

@ -0,0 +1,8 @@
---
features:
- |
Remote address group support was added to the iptables-based firewall
drivers (IptablesFirewallDriver and OVSHybridIptablesFirewallDriver),
Previously it was only available in the OVSFirewallDriver.
For more information, see bug
`2058138 <https://bugs.launchpad.net/neutron/+bug/2058138>`_.