From 54bf4694b9057264ebf49a299478b4fd325fafb7 Mon Sep 17 00:00:00 2001 From: Michael Still Date: Sun, 10 Feb 2019 23:43:57 +0000 Subject: [PATCH] Move iptables rule fetching and setting to privsep. Rules are fetched, edited, and set. Keep the edit logic in nova/network, but move the bits requiring elevated permissions to privsep. Change-Id: I1f8382c450b95d261f68ec8bae2a2077f9361fe0 --- nova/network/linux_net.py | 50 +++++--- nova/privsep/linux_net.py | 23 ++++ nova/tests/fixtures.py | 7 ++ nova/tests/unit/network/test_linux_net.py | 116 +++++++++++++----- nova/tests/unit/network/test_manager.py | 105 ++++++++++------ nova/tests/unit/test_quota.py | 14 ++- nova/tests/unit/virt/libvirt/test_firewall.py | 76 +++++++----- nova/tests/unit/virt/xenapi/test_xenapi.py | 8 +- nova/virt/xenapi/firewall.py | 3 +- 9 files changed, 284 insertions(+), 118 deletions(-) diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 6fbef8cb9b60..a71e225ee55c 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -261,11 +261,14 @@ class IptablesManager(object): """ - def __init__(self, execute=None): - if not execute: - self.execute = _execute - else: - self.execute = execute + def __init__(self, redirect_privsep_calls_to=None): + # NOTE(mikal): This is only used by the xenapi hypervisor driver, + # which wants to intercept our calls to iptables and redirect them + # to an agent running in dom0. + # TODO(mikal): We really should make the dom0 agent feel more like + # privsep. They really are the same thing, just one is from a simpler + # time in our past. + self.redirect_privsep = redirect_privsep_calls_to self.ipv4 = {'filter': IptablesTable(), 'nat': IptablesTable(), @@ -358,23 +361,42 @@ class IptablesManager(object): rules. This happens atomically, thanks to iptables-restore. """ - s = [('iptables', self.ipv4)] + s = [(True, self.ipv4)] if CONF.use_ipv6: - s += [('ip6tables', self.ipv6)] + s += [(False, self.ipv6)] + + for is_ipv4, tables in s: + if not self.redirect_privsep: + all_tables, _err = nova.privsep.linux_net.iptables_get_rules( + ipv4=is_ipv4) + else: + if is_ipv4: + cmd = 'iptables-save' + else: + cmd = 'ip6tables-save' + all_tables, _err = self.redirect_privsep( + cmd, '-c', run_as_root=True, attempts=5) - for cmd, tables in s: - all_tables, _err = self.execute('%s-save' % (cmd,), '-c', - run_as_root=True, - attempts=5) all_lines = all_tables.split('\n') for table_name, table in tables.items(): start, end = self._find_table(all_lines, table_name) all_lines[start:end] = self._modify_rules( all_lines[start:end], table, table_name) table.dirty = False - self.execute('%s-restore' % (cmd,), '-c', run_as_root=True, - process_input=six.b('\n'.join(all_lines)), - attempts=5) + + if not self.redirect_privsep: + nova.privsep.linux_net.iptables_set_rules(all_lines, + ipv4=is_ipv4) + else: + if is_ipv4: + cmd = 'iptables-restore' + else: + cmd = 'ip6tables-restore' + self.redirect_privsep( + cmd, '-c', run_as_root=True, + process_input=six.b('\n'.join(all_lines)), + attempts=5) + LOG.debug("IPTablesManager.apply completed with success") def _find_table(self, lines, table_name): diff --git a/nova/privsep/linux_net.py b/nova/privsep/linux_net.py index e78aefb65b96..90172c1c6a16 100644 --- a/nova/privsep/linux_net.py +++ b/nova/privsep/linux_net.py @@ -19,6 +19,7 @@ Linux network specific helpers. import os +import six from oslo_concurrency import processutils from oslo_log import log as logging @@ -266,3 +267,25 @@ def add_vlan(bridge_interface, interface, vlan_num): processutils.execute('ip', 'link', 'add', 'link', bridge_interface, 'name', interface, 'type', 'vlan', 'id', vlan_num, check_exit_code=[0, 2, 254]) + + +@nova.privsep.sys_admin_pctxt.entrypoint +def iptables_get_rules(ipv4=True): + if ipv4: + cmd = 'iptables' + else: + cmd = 'ip6tables' + + return processutils.execute('%s-save' % cmd, '-c', attempts=5) + + +@nova.privsep.sys_admin_pctxt.entrypoint +def iptables_set_rules(rules, ipv4=True): + if ipv4: + cmd = 'iptables' + else: + cmd = 'ip6tables' + + processutils.execute('%s-restore' % cmd, '-c', + process_input=six.b('\n'.join(rules)), + attempts=5) diff --git a/nova/tests/fixtures.py b/nova/tests/fixtures.py index 80f801cb7706..070223e89fae 100644 --- a/nova/tests/fixtures.py +++ b/nova/tests/fixtures.py @@ -95,6 +95,13 @@ class ServiceFixture(fixtures.Fixture): self.ctxt = context.get_admin_context() if self.cell: context.set_target_cell(self.ctxt, self.cell) + + # NOTE(mikal): we don't have root to manipulate iptables, so just + # zero that bit out. + self.useFixture(fixtures.MonkeyPatch( + 'nova.network.linux_net.IptablesManager._apply', + lambda _: None)) + with mock.patch('nova.context.get_admin_context', return_value=self.ctxt): self.service = service.Service.create(**self.kwargs) diff --git a/nova/tests/unit/network/test_linux_net.py b/nova/tests/unit/network/test_linux_net.py index 6ce993f4fb70..a74405918746 100644 --- a/nova/tests/unit/network/test_linux_net.py +++ b/nova/tests/unit/network/test_linux_net.py @@ -373,7 +373,13 @@ class LinuxNetworkTestCase(test.NoDBTestCase): get_associated) @mock.patch.object(linux_net.iptables_manager.ipv4['nat'], 'add_rule') - def _test_add_snat_rule(self, expected, is_external, mock_add_rule): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def _test_add_snat_rule(self, expected, is_external, + mock_iptables_set_rules, mock_iptables_get_rules, + mock_add_rule): def verify_add_rule(chain, rule): self.assertEqual('snat', chain) @@ -415,7 +421,13 @@ class LinuxNetworkTestCase(test.NoDBTestCase): @mock.patch.object(fileutils, 'ensure_tree') @mock.patch.object(os, 'chmod') - def test_update_dhcp_for_nw00(self, mock_chmod, mock_ensure_tree): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_update_dhcp_for_nw00(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_chmod, + mock_ensure_tree): with mock.patch.object(self.driver, 'write_to_file') \ as mock_write_to_file: self.flags(use_single_default_gateway=True) @@ -428,7 +440,13 @@ class LinuxNetworkTestCase(test.NoDBTestCase): @mock.patch.object(fileutils, 'ensure_tree') @mock.patch.object(os, 'chmod') - def test_update_dhcp_for_nw01(self, mock_chmod, mock_ensure_tree): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_update_dhcp_for_nw01(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_chmod, + mock_ensure_tree): with mock.patch.object(self.driver, 'write_to_file') \ as mock_write_to_file: self.flags(use_single_default_gateway=True) @@ -594,9 +612,14 @@ class LinuxNetworkTestCase(test.NoDBTestCase): @mock.patch('nova.privsep.linux_net.routes_show', return_value=('fake', 0)) @mock.patch('nova.privsep.linux_net.lookup_ip', return_value=('', '')) - def test_linux_bridge_driver_plug(self, mock_lookup_ip, mock_routes_show, - mock_enabled, mock_add_bridge, - mock_add_rule): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_linux_bridge_driver_plug( + self, mock_iptables_set_rules, mock_iptables_get_rules, + mock_lookup_ip, mock_routes_show, mock_enabled, mock_add_bridge, + mock_add_rule): """Makes sure plug doesn't drop FORWARD by default. Ensures bug 890195 doesn't reappear. @@ -644,7 +667,12 @@ class LinuxNetworkTestCase(test.NoDBTestCase): @mock.patch.object(linux_net.LinuxBridgeInterfaceDriver, 'ensure_vlan_bridge') - def test_vlan_override(self, mock_ensure_vlan_bridge): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_vlan_override(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_ensure_vlan_bridge): """Makes sure vlan_interface flag overrides network bridge_interface. Allows heterogeneous networks a la bug 833426 @@ -675,7 +703,12 @@ class LinuxNetworkTestCase(test.NoDBTestCase): self.assertEqual(3, mock_ensure_vlan_bridge.call_count) @mock.patch.object(linux_net.LinuxBridgeInterfaceDriver, 'ensure_bridge') - def test_flat_override(self, mock_ensure_bridge): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_flat_override(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_ensure_bridge): """Makes sure flat_interface flag overrides network bridge_interface. Allows heterogeneous networks a la bug 833426 @@ -707,7 +740,13 @@ class LinuxNetworkTestCase(test.NoDBTestCase): @mock.patch('os.chmod') @mock.patch.object(linux_net, '_add_dhcp_mangle_rule') @mock.patch.object(linux_net, '_execute') - def _test_dnsmasq_execute(self, mock_execute, mock_add_dhcp_mangle_rule, + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def _test_dnsmasq_execute(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_execute, + mock_add_dhcp_mangle_rule, mock_chmod, mock_write_to_file, mock_dnsmasq_pid_for, extra_expected=None): network_ref = {'id': 'fake', @@ -775,7 +814,12 @@ class LinuxNetworkTestCase(test.NoDBTestCase): def test_dnsmasq_execute(self): self._test_dnsmasq_execute() - def test_dnsmasq_execute_dns_servers(self): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_dnsmasq_execute_dns_servers(self, mock_iptables_set_rules, + mock_iptables_get_rules): self.flags(dns_server=['1.1.1.1', '2.2.2.2']) expected = [ '--no-resolv', @@ -793,15 +837,14 @@ class LinuxNetworkTestCase(test.NoDBTestCase): self._test_dnsmasq_execute(extra_expected=expected) @mock.patch('nova.privsep.linux_net.modify_ebtables') - def test_isolated_host(self, mock_modify_ebtables): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_isolated_host(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_modify_ebtables): self.flags(fake_network=False, share_dhcp_address=True) - executes = [] - - def fake_execute(*args, **kwargs): - executes.append(args) - return "", "" - driver = linux_net.LinuxBridgeInterfaceDriver() def fake_ensure(bridge, interface, network, gateway): @@ -810,7 +853,6 @@ class LinuxNetworkTestCase(test.NoDBTestCase): self.stub_out('nova.network.linux_net.iptables_manager', linux_net.IptablesManager()) self.stub_out('nova.network.linux_net.binary_name', 'test') - self.stub_out('nova.utils.execute', fake_execute) self.stub_out( 'nova.network.linux_net.LinuxBridgeInterfaceDriver.ensure_bridge', fake_ensure) @@ -823,13 +865,12 @@ class LinuxNetworkTestCase(test.NoDBTestCase): 'bridge_interface': iface} driver.plug(network, 'fakemac') - expected = [ - ('iptables-save', '-c'), - ('iptables-restore', '-c'), - ('ip6tables-save', '-c'), - ('ip6tables-restore', '-c'), - ] - self.assertEqual(expected, executes) + mock_iptables_get_rules.assert_has_calls([ + mock.call(ipv4=True), + mock.call(ipv4=False)]) + mock_iptables_set_rules.assert_has_calls([ + mock.call(mock.ANY, ipv4=True), + mock.call(mock.ANY, ipv4=False)]) mock_modify_ebtables.assert_has_calls([ mock.call('filter', ['INPUT', '-p', 'ARP', '-i', iface, '--arp-ip-dst', @@ -1084,7 +1125,12 @@ class LinuxNetworkTestCase(test.NoDBTestCase): self.assertFalse(manager.iptables_apply_deferred) @mock.patch.object(linux_net.iptables_manager.ipv4['filter'], 'add_rule') - def _test_add_metadata_accept_rule(self, expected, mock_add_rule): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def _test_add_metadata_accept_rule(self, expected, mock_iptables_set_rules, + mock_iptables_get_rules, mock_add_rule): def verify_add_rule(chain, rule): self.assertEqual('INPUT', chain) self.assertEqual(expected, rule) @@ -1094,7 +1140,14 @@ class LinuxNetworkTestCase(test.NoDBTestCase): mock_add_rule.assert_called_once() @mock.patch.object(linux_net.iptables_manager.ipv6['filter'], 'add_rule') - def _test_add_metadata_accept_ipv6_rule(self, expected, mock_add_rule): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def _test_add_metadata_accept_ipv6_rule(self, expected, + mock_iptables_set_rules, + mock_iptables_get_rules, + mock_add_rule): def verify_add_rule(chain, rule): self.assertEqual('INPUT', chain) self.assertEqual(expected, rule) @@ -1132,7 +1185,14 @@ class LinuxNetworkTestCase(test.NoDBTestCase): self._test_add_metadata_accept_ipv6_rule(expected) @mock.patch.object(linux_net.iptables_manager.ipv4['nat'], 'add_rule') - def _test_add_metadata_forward_rule(self, expected, mock_add_rule): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def _test_add_metadata_forward_rule(self, expected, + mock_iptables_set_rules, + mock_iptables_get_rules, + mock_add_rule): def verify_add_rule(chain, rule): self.assertEqual('PREROUTING', chain) self.assertEqual(expected, rule) diff --git a/nova/tests/unit/network/test_manager.py b/nova/tests/unit/network/test_manager.py index fdf8753319ba..397462b4ac34 100644 --- a/nova/tests/unit/network/test_manager.py +++ b/nova/tests/unit/network/test_manager.py @@ -947,12 +947,15 @@ class VlanNetworkTestCase(test.TestCase): @mock.patch('nova.privsep.linux_net.ipv4_forwarding_check', return_value=False) @mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner') - def test_vpn_allocate_fixed_ip(self, mock_forwarding_enable, - mock_forwarding_check, - mock_address_command, - mock_change_ip, mock_lookup_ip, - mock_routes_show, mock_enabled, - mock_add_bridge): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_vpn_allocate_fixed_ip( + self, mock_iptables_set_rules, mock_iptables_get_rules, + mock_forwarding_enable, mock_forwarding_check, + mock_address_command, mock_change_ip, mock_lookup_ip, + mock_routes_show, mock_enabled, mock_add_bridge): self.mox.StubOutWithMock(db, 'fixed_ip_associate') self.mox.StubOutWithMock(db, 'fixed_ip_update') self.mox.StubOutWithMock(db, @@ -994,11 +997,15 @@ class VlanNetworkTestCase(test.TestCase): @mock.patch('nova.privsep.linux_net.ipv4_forwarding_check', return_value=False) @mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner') - def test_allocate_fixed_ip(self, mock_forwarding_enable, - mock_forwarding_check, mock_address_command, - mock_change_ip, mock_lookup_ip, - mock_routes_show, mock_enabled, - mock_add_bridge): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_allocate_fixed_ip( + self, mock_iptables_set_rules, mock_iptables_get_rules, + mock_forwarding_enable, mock_forwarding_check, + mock_address_command, mock_change_ip, mock_lookup_ip, + mock_routes_show, mock_enabled, mock_add_bridge): self.stubs.Set(self.network, '_do_trigger_security_group_members_refresh_for_instance', lambda *a, **kw: None) @@ -1725,8 +1732,13 @@ class VlanNetworkTestCase(test.TestCase): @mock.patch('nova.privsep.linux_net.ipv4_forwarding_check', return_value=False) @mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner') + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) def test_add_fixed_ip_instance_without_vpn_requested_networks( - self, mock_forwarding_enable, mock_forwarding_check, + self, mock_iptables_set_rules, mock_iptables_get_rules, + mock_forwarding_enable, mock_forwarding_check, mock_address_command, mock_change_ip, mock_lookup_ip, mock_routes_show, mock_enabled, mock_add_bridge): self.stubs.Set(self.network, @@ -1773,8 +1785,13 @@ class VlanNetworkTestCase(test.TestCase): @mock.patch('nova.privsep.linux_net.unbind_ip') @mock.patch('nova.privsep.linux_net.clean_conntrack') @mock.patch('nova.privsep.linux_net.modify_ebtables') + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) def test_ip_association_and_allocation_of_other_project( - self, modify_ebtables, clean_conntrack, unbind_ip, bind_ip, + self, mock_iptables_set_rules, mock_iptables_get_rules, + modify_ebtables, clean_conntrack, unbind_ip, bind_ip, net_get, fixed_get): """Makes sure that we cannot deallocaate or disassociate a public IP of other project. @@ -2895,16 +2912,17 @@ class AllocateTestCase(test.TestCase): @mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner') @mock.patch('nova.privsep.linux_net.modify_ebtables') @mock.patch('nova.privsep.linux_net.add_vlan') - def test_allocate_for_instance(self, mock_add_vlan, - mock_modify_ebtables, - mock_forwarding_enable, - mock_forwarding_check, - mock_clean_conntrack, - mock_address_command, - mock_change_ip, mock_lookup_ip, - mock_routes_show, mock_unbind, mock_bind, - mock_set_macaddr, mock_set_enabled, - mock_set_mtu, mock_add_bridge): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_allocate_for_instance( + self, mock_iptables_set_rules, mock_iptables_get_rules, + mock_add_vlan, mock_modify_ebtables, mock_forwarding_enable, + mock_forwarding_check, mock_clean_conntrack, mock_address_command, + mock_change_ip, mock_lookup_ip, mock_routes_show, mock_unbind, + mock_bind, mock_set_macaddr, mock_set_enabled, mock_set_mtu, + mock_add_bridge): address = "10.10.10.10" self.flags(auto_assign_floating_ip=True) @@ -2980,15 +2998,16 @@ class AllocateTestCase(test.TestCase): return_value=False) @mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner') @mock.patch('nova.privsep.linux_net.add_vlan') - def test_allocate_for_instance_with_mac(self, mock_add_vlan, - mock_forwarding_enable, - mock_forwarding_check, - mock_address_command, - mock_change_ip, - mock_lookup_ip, - mock_routes_show, - mock_set_addr, mock_enabled, - mock_set_mtu, mock_add_bridge): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_allocate_for_instance_with_mac( + self, mock_iptables_set_rules, mock_iptables_get_rules, + mock_add_vlan, mock_forwarding_enable, + mock_forwarding_check, mock_address_command, + mock_change_ip, mock_lookup_ip, mock_routes_show, + mock_set_addr, mock_enabled, mock_set_mtu, mock_add_bridge): available_macs = set(['ca:fe:de:ad:be:ef']) inst = db.instance_create(self.context, {'host': HOST, 'display_name': HOST, @@ -3146,10 +3165,13 @@ class FloatingIPTestCase(test.TestCase): @mock.patch('nova.privsep.linux_net.unbind_ip') @mock.patch('nova.privsep.linux_net.clean_conntrack') @mock.patch('nova.privsep.linux_net.modify_ebtables') - def test_deallocation_deleted_instance(self, - mock_modify_ebtables, - mock_clean_conntrack, - mock_unbind_ip): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_deallocation_deleted_instance( + self, mock_iptables_set_rules, mock_iptables_get_rules, + mock_modify_ebtables, mock_clean_conntrack, mock_unbind_ip): self.stubs.Set(self.network, '_teardown_network_on_host', lambda *args, **kwargs: None) instance = objects.Instance(context=self.context) @@ -3172,10 +3194,13 @@ class FloatingIPTestCase(test.TestCase): @mock.patch('nova.privsep.linux_net.unbind_ip') @mock.patch('nova.privsep.linux_net.clean_conntrack') @mock.patch('nova.privsep.linux_net.modify_ebtables') - def test_deallocation_duplicate_floating_ip(self, - mock_modify_ebtables, - mock_clean_conntrack, - mock_unbind_ip): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_deallocation_duplicate_floating_ip( + self, mock_iptables_set_rules, mock_iptables_get_rules, + mock_modify_ebtables, mock_clean_conntrack, mock_unbind_ip): self.stubs.Set(self.network, '_teardown_network_on_host', lambda *args, **kwargs: None) instance = objects.Instance(context=self.context) diff --git a/nova/tests/unit/test_quota.py b/nova/tests/unit/test_quota.py index e178f0c39aea..5490ee5f9e11 100644 --- a/nova/tests/unit/test_quota.py +++ b/nova/tests/unit/test_quota.py @@ -153,7 +153,12 @@ class QuotaIntegrationTestCase(test.TestCase): self._create_instance(flavor_name='m1.xlarge') @mock.patch('nova.privsep.linux_net.bind_ip') - def test_too_many_addresses(self, mock_bind_ip): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_too_many_addresses(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_bind_ip): # This test is specifically relying on nova-network. self.flags(use_neutron=False, network_manager='nova.network.manager.FlatDHCPManager') @@ -173,7 +178,12 @@ class QuotaIntegrationTestCase(test.TestCase): db.floating_ip_destroy(context.get_admin_context(), address) @mock.patch('nova.privsep.linux_net.bind_ip') - def test_auto_assigned(self, mock_bind_ip): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_auto_assigned(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_bind_ip): # This test is specifically relying on nova-network. self.flags(use_neutron=False, network_manager='nova.network.manager.FlatDHCPManager') diff --git a/nova/tests/unit/virt/libvirt/test_firewall.py b/nova/tests/unit/virt/libvirt/test_firewall.py index 07f458302c76..d35cefb71aca 100644 --- a/nova/tests/unit/virt/libvirt/test_firewall.py +++ b/nova/tests/unit/virt/libvirt/test_firewall.py @@ -149,10 +149,15 @@ class IptablesFirewallTestCase(test.NoDBTestCase): inst.info_cache.deleted = False return inst - @mock.patch.object(linux_net.iptables_manager, "execute") @mock.patch.object(objects.InstanceList, "get_by_security_group_id") @mock.patch.object(objects.SecurityGroupRuleList, "get_by_instance") - def test_static_filters(self, mock_secrule, mock_instlist, fake_execute): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_static_filters(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_secrule, + mock_instlist): UUID = "2674993b-6adb-4733-abd9-a7c10cc1f146" SRC_UUID = "0e0a76b2-7c52-4bc0-9a60-d83017e42c1a" instance_ref = self._create_instance_ref(UUID) @@ -215,7 +220,7 @@ class IptablesFirewallTestCase(test.NoDBTestCase): mock_secrule.return_value = objects.SecurityGroupRuleList( objects=[r1, r2, r3, r4, r5]) - def _fake_instlist(ctxt, id): + def fake_instlist(ctxt, id): if id == src_secgroup.id: insts = objects.InstanceList() insts.objects.append(src_instance_ref) @@ -224,32 +229,26 @@ class IptablesFirewallTestCase(test.NoDBTestCase): insts = objects.InstanceList() insts.objects.append(instance_ref) return insts + mock_instlist.side_effect = fake_instlist - mock_instlist.side_effect = _fake_instlist - - def fake_iptables_execute(*cmd, **kwargs): - process_input = kwargs.get('process_input') - if process_input is not None and isinstance(process_input, bytes): - process_input = process_input.decode('utf-8') - if cmd == ('ip6tables-save', '-c'): - return '\n'.join(self.in6_filter_rules), None - if cmd == ('iptables-save', '-c'): + def fake_iptables_get(ipv4=True): + if ipv4: return '\n'.join(self.in_rules), None - if cmd == ('iptables-restore', '-c'): - lines = process_input.split('\n') - if '*filter' in lines: - self.out_rules = lines - return '', '' - if cmd == ('ip6tables-restore', '-c',): - lines = process_input.split('\n') - if '*filter' in lines: - self.out6_rules = lines - return '', '' + else: + return '\n'.join(self.in6_filter_rules), None + mock_iptables_get_rules.side_effect = fake_iptables_get + + def fake_iptables_set(rules, ipv4=True): + if '*filter' in rules: + if ipv4: + self.out_rules = rules + else: + self.out6_rules = rules + return '', '' + mock_iptables_set_rules.side_effect = fake_iptables_set network_model = _fake_network_info(self, 1) - fake_execute.side_effect = fake_iptables_execute - self.stub_out('nova.objects.Instance.get_network_info', lambda instance: network_model) @@ -322,7 +321,12 @@ class IptablesFirewallTestCase(test.NoDBTestCase): self.assertEqual(len(rulesv6), 1) @mock.patch.object(objects.SecurityGroupRuleList, "get_by_instance") - def test_multinic_iptables(self, mock_secrule): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_multinic_iptables(self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_secrule): mock_secrule.return_value = objects.SecurityGroupRuleList() ipv4_rules_per_addr = 1 @@ -356,8 +360,14 @@ class IptablesFirewallTestCase(test.NoDBTestCase): @mock.patch.object(firewall.IptablesFirewallDriver, 'add_filters_for_instance') @mock.patch.object(linux_net.IptablesTable, 'has_chain') - def test_do_refresh_security_group_rules(self, mock_has_chain, - mock_add_filters, mock_instance_rules): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_do_refresh_security_group_rules( + self, mock_iptables_set_rules, + mock_iptables_get_rules, mock_has_chain, + mock_add_filters, mock_instance_rules): instance_ref = self._create_instance_ref() mock_instance_rules.return_value = (None, None) @@ -402,11 +412,13 @@ class IptablesFirewallTestCase(test.NoDBTestCase): @mock.patch.object(fakelibvirt.virConnect, "nwfilterDefineXML") @mock.patch.object(objects.InstanceList, "get_by_security_group_id") @mock.patch.object(objects.SecurityGroupRuleList, "get_by_instance") - def test_unfilter_instance_undefines_nwfilter(self, - mock_secrule, - mock_instlist, - mock_define, - mock_lookup): + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_unfilter_instance_undefines_nwfilter( + self, mock_iptables_set_rules, mock_iptables_get_rules, + mock_secrule, mock_instlist, mock_define, mock_lookup): fakefilter = NWFilterFakes() mock_lookup.side_effect = fakefilter.nwfilterLookupByName mock_define.side_effect = fakefilter.filterDefineXMLMock diff --git a/nova/tests/unit/virt/xenapi/test_xenapi.py b/nova/tests/unit/virt/xenapi/test_xenapi.py index d46ec929a7ac..7f138084215c 100644 --- a/nova/tests/unit/virt/xenapi/test_xenapi.py +++ b/nova/tests/unit/virt/xenapi/test_xenapi.py @@ -1145,7 +1145,13 @@ class XenAPIVMTestCase(stubs.XenAPITestBase, return_value=False) @mock.patch('nova.privsep.linux_net._enable_ipv4_forwarding_inner') @mock.patch('nova.privsep.linux_net.add_vlan') - def test_spawn_vlanmanager(self, mock_add_vlan, mock_forwarding_enable, + @mock.patch('nova.privsep.linux_net.iptables_get_rules', + return_value=('', '')) + @mock.patch('nova.privsep.linux_net.iptables_set_rules', + return_value=('', '')) + def test_spawn_vlanmanager(self, mock_iptables_set_rules, + mock_iptables_get_rules, + mock_add_vlan, mock_forwarding_enable, mock_forwarding_check, mock_address_command_horrid, mock_change_ip, mock_set_macaddr, diff --git a/nova/virt/xenapi/firewall.py b/nova/virt/xenapi/firewall.py index 485b1da01b05..dddf8cb95935 100644 --- a/nova/virt/xenapi/firewall.py +++ b/nova/virt/xenapi/firewall.py @@ -44,7 +44,8 @@ class Dom0IptablesFirewallDriver(firewall.IptablesFirewallDriver): super(Dom0IptablesFirewallDriver, self).__init__(**kwargs) self._session = xenapi_session # Create IpTablesManager with executor through plugin - self.iptables = linux_net.IptablesManager(self._plugin_execute) + self.iptables = linux_net.IptablesManager( + redirect_privsep_calls_to=self._plugin_execute) self.iptables.ipv4['filter'].add_chain('sg-fallback') self.iptables.ipv4['filter'].add_rule('sg-fallback', '-j DROP') self.iptables.ipv6['filter'].add_chain('sg-fallback')