Remove rootwrap execution (1)

Replace rootwrap execution with privsep context execution.
This series of patches will progressively replace any
rootwrap call.

This patch replaces some "IpNetnsCommand" command execution
methods.

Change-Id: Ic5fdf221a2a2cd0951539b0e040d2a941feee287
Story: #2007686
Task: #41558
This commit is contained in:
Rodolfo Alonso Hernandez 2020-11-24 16:16:02 +00:00
parent f9c9d102aa
commit c89c1f53db
22 changed files with 237 additions and 100 deletions

View File

@ -192,7 +192,7 @@ class FipNamespace(namespaces.Namespace):
self.agent_gateway_port = ex_gw_port self.agent_gateway_port = ex_gw_port
cmd = ['sysctl', '-w', 'net.ipv4.conf.%s.proxy_arp=1' % interface_name] cmd = ['sysctl', '-w', 'net.ipv4.conf.%s.proxy_arp=1' % interface_name]
ip_wrapper.netns.execute(cmd, check_exit_code=False) ip_wrapper.netns.execute(cmd, check_exit_code=False, privsep_exec=True)
def create(self): def create(self):
LOG.debug("DVR: add fip namespace: %s", self.name) LOG.debug("DVR: add fip namespace: %s", self.name)

View File

@ -804,7 +804,8 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase):
'via', route['nexthop'], 'table', tbl_index] 'via', route['nexthop'], 'table', tbl_index]
ip_wrapper = ip_lib.IPWrapper(namespace=fip_ns_name) ip_wrapper = ip_lib.IPWrapper(namespace=fip_ns_name)
if ip_wrapper.netns.exists(fip_ns_name): if ip_wrapper.netns.exists(fip_ns_name):
ip_wrapper.netns.execute(cmd, check_exit_code=False) ip_wrapper.netns.execute(cmd, check_exit_code=False,
privsep_exec=True)
else: else:
LOG.debug("The FIP namespace %(ns)s does not exist for " LOG.debug("The FIP namespace %(ns)s does not exist for "
"router %(id)s", "router %(id)s",

View File

@ -94,18 +94,18 @@ class Namespace(object):
# these sysctl values. # these sysctl values.
ip_wrapper = self.ip_wrapper_root.ensure_namespace(self.name) ip_wrapper = self.ip_wrapper_root.ensure_namespace(self.name)
cmd = ['sysctl', '-w', 'net.ipv4.ip_forward=1'] cmd = ['sysctl', '-w', 'net.ipv4.ip_forward=1']
ip_wrapper.netns.execute(cmd) ip_wrapper.netns.execute(cmd, privsep_exec=True)
# 1. Reply only if the target IP address is local address configured # 1. Reply only if the target IP address is local address configured
# on the incoming interface; and # on the incoming interface; and
# 2. Always use the best local address # 2. Always use the best local address
cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1'] cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1']
ip_wrapper.netns.execute(cmd) ip_wrapper.netns.execute(cmd, privsep_exec=True)
cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2'] cmd = ['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2']
ip_wrapper.netns.execute(cmd) ip_wrapper.netns.execute(cmd, privsep_exec=True)
if self.use_ipv6: if self.use_ipv6:
cmd = ['sysctl', '-w', cmd = ['sysctl', '-w',
'net.ipv6.conf.all.forwarding=%d' % int(ipv6_forwarding)] 'net.ipv6.conf.all.forwarding=%d' % int(ipv6_forwarding)]
ip_wrapper.netns.execute(cmd) ip_wrapper.netns.execute(cmd, privsep_exec=True)
def delete(self): def delete(self):
try: try:

View File

@ -98,7 +98,7 @@ class ProcessManager(MonitoredProcess):
else: else:
self.disable('HUP') self.disable('HUP')
def disable(self, sig='9', get_stop_command=None): def disable(self, sig='9', get_stop_command=None, privsep_exec=False):
pid = self.pid pid = self.pid
if self.active: if self.active:
@ -106,10 +106,12 @@ class ProcessManager(MonitoredProcess):
cmd = get_stop_command(self.get_pid_file_name()) cmd = get_stop_command(self.get_pid_file_name())
ip_wrapper = ip_lib.IPWrapper(namespace=self.namespace) ip_wrapper = ip_lib.IPWrapper(namespace=self.namespace)
ip_wrapper.netns.execute(cmd, addl_env=self.cmd_addl_env, ip_wrapper.netns.execute(cmd, addl_env=self.cmd_addl_env,
run_as_root=self.run_as_root) run_as_root=self.run_as_root,
privsep_exec=privsep_exec)
else: else:
cmd = self.get_kill_cmd(sig, pid) cmd = self.get_kill_cmd(sig, pid)
utils.execute(cmd, run_as_root=self.run_as_root) utils.execute(cmd, run_as_root=self.run_as_root,
privsep_exec=privsep_exec)
# In the case of shutting down, remove the pid file # In the case of shutting down, remove the pid file
if sig == '9': if sig == '9':
utils.delete_if_exists(self.get_pid_file_name(), utils.delete_if_exists(self.get_pid_file_name(),

View File

@ -354,7 +354,7 @@ class IPDevice(SubProcessBase):
try: try:
ip_wrapper.netns.execute(["conntrack", "-D", "-d", ip_str], ip_wrapper.netns.execute(["conntrack", "-D", "-d", ip_str],
check_exit_code=True, check_exit_code=True,
extra_ok_codes=[1]) extra_ok_codes=[1], privsep_exec=True)
except RuntimeError: except RuntimeError:
LOG.exception("Failed deleting ingress connection state of" LOG.exception("Failed deleting ingress connection state of"
@ -364,7 +364,7 @@ class IPDevice(SubProcessBase):
try: try:
ip_wrapper.netns.execute(["conntrack", "-D", "-q", ip_str], ip_wrapper.netns.execute(["conntrack", "-D", "-q", ip_str],
check_exit_code=True, check_exit_code=True,
extra_ok_codes=[1]) extra_ok_codes=[1], privsep_exec=True)
except RuntimeError: except RuntimeError:
LOG.exception("Failed deleting egress connection state of" LOG.exception("Failed deleting egress connection state of"
" floatingip %s", ip_str) " floatingip %s", ip_str)
@ -376,7 +376,7 @@ class IPDevice(SubProcessBase):
'--dport', dport] '--dport', dport]
try: try:
ip_wrapper.netns.execute(cmd, check_exit_code=True, ip_wrapper.netns.execute(cmd, check_exit_code=True,
extra_ok_codes=[1]) extra_ok_codes=[1], privsep_exec=True)
except RuntimeError: except RuntimeError:
LOG.exception("Failed deleting ingress connection state of " LOG.exception("Failed deleting ingress connection state of "
@ -699,7 +699,8 @@ class IpNetnsCommand(IpCommandBase):
create_network_namespace(name) create_network_namespace(name)
wrapper = IPWrapper(namespace=name) wrapper = IPWrapper(namespace=name)
wrapper.netns.execute(['sysctl', '-w', wrapper.netns.execute(['sysctl', '-w',
'net.ipv4.conf.all.promote_secondaries=1']) 'net.ipv4.conf.all.promote_secondaries=1'],
privsep_exec=True)
return wrapper return wrapper
def delete(self, name): def delete(self, name):
@ -707,7 +708,7 @@ class IpNetnsCommand(IpCommandBase):
def execute(self, cmds, addl_env=None, check_exit_code=True, def execute(self, cmds, addl_env=None, check_exit_code=True,
log_fail_as_error=True, extra_ok_codes=None, log_fail_as_error=True, extra_ok_codes=None,
run_as_root=False): run_as_root=False, privsep_exec=False):
ns_params = [] ns_params = []
if self._parent.namespace: if self._parent.namespace:
run_as_root = True run_as_root = True
@ -721,7 +722,8 @@ class IpNetnsCommand(IpCommandBase):
return utils.execute(cmd, check_exit_code=check_exit_code, return utils.execute(cmd, check_exit_code=check_exit_code,
extra_ok_codes=extra_ok_codes, extra_ok_codes=extra_ok_codes,
log_fail_as_error=log_fail_as_error, log_fail_as_error=log_fail_as_error,
run_as_root=run_as_root) run_as_root=run_as_root,
privsep_exec=privsep_exec)
def exists(self, name): def exists(self, name):
return network_namespace_exists(name) return network_namespace_exists(name)
@ -1014,7 +1016,8 @@ def _arping(ns_name, iface_name, address, count, log_exception):
'-w', 2, address] '-w', 2, address]
try: try:
ip_wrapper.netns.execute(arping_cmd, ip_wrapper.netns.execute(arping_cmd,
extra_ok_codes=extra_ok_codes) extra_ok_codes=extra_ok_codes,
privsep_exec=True)
except Exception as exc: except Exception as exc:
# Since this is spawned in a thread and executed 2 seconds # Since this is spawned in a thread and executed 2 seconds
# apart, something may have been deleted while we were # apart, something may have been deleted while we were
@ -1101,7 +1104,8 @@ def sysctl(cmd, namespace=None, log_fail_as_error=True):
ip_wrapper = IPWrapper(namespace=namespace) ip_wrapper = IPWrapper(namespace=namespace)
try: try:
ip_wrapper.netns.execute(cmd, run_as_root=True, ip_wrapper.netns.execute(cmd, run_as_root=True,
log_fail_as_error=log_fail_as_error) log_fail_as_error=log_fail_as_error,
privsep_exec=True)
except RuntimeError as rte: except RuntimeError as rte:
LOG.warning( LOG.warning(
"Setting %(cmd)s in namespace %(ns)s failed: %(err)s.", "Setting %(cmd)s in namespace %(ns)s failed: %(err)s.",
@ -1127,7 +1131,8 @@ def get_ip_nonlocal_bind(namespace=None):
"""Get kernel option value of ip_nonlocal_bind in given namespace.""" """Get kernel option value of ip_nonlocal_bind in given namespace."""
cmd = ['sysctl', '-bn', IP_NONLOCAL_BIND] cmd = ['sysctl', '-bn', IP_NONLOCAL_BIND]
ip_wrapper = IPWrapper(namespace) ip_wrapper = IPWrapper(namespace)
return int(ip_wrapper.netns.execute(cmd, run_as_root=True)) return int(ip_wrapper.netns.execute(cmd, run_as_root=True,
privsep_exec=True))
def set_ip_nonlocal_bind(value, namespace=None, log_fail_as_error=True): def set_ip_nonlocal_bind(value, namespace=None, log_fail_as_error=True):
@ -1162,7 +1167,8 @@ def get_ipv6_forwarding(device, namespace=None):
"""Get kernel value of IPv6 forwarding for device in given namespace.""" """Get kernel value of IPv6 forwarding for device in given namespace."""
cmd = ['sysctl', '-b', "net.ipv6.conf.%s.forwarding" % device] cmd = ['sysctl', '-b', "net.ipv6.conf.%s.forwarding" % device]
ip_wrapper = IPWrapper(namespace) ip_wrapper = IPWrapper(namespace)
return int(ip_wrapper.netns.execute(cmd, run_as_root=True)) return int(ip_wrapper.netns.execute(cmd, run_as_root=True,
privsep_exec=True))
def _parse_ip_rule(rule, ip_version): def _parse_ip_rule(rule, ip_version):

View File

@ -33,7 +33,8 @@ class FloatingIPTcCommandBase(ip_lib.IPDevice):
def _execute_tc_cmd(self, cmd, **kwargs): def _execute_tc_cmd(self, cmd, **kwargs):
cmd = ['tc'] + cmd cmd = ['tc'] + cmd
ip_wrapper = ip_lib.IPWrapper(self.namespace) ip_wrapper = ip_lib.IPWrapper(self.namespace)
return ip_wrapper.netns.execute(cmd, run_as_root=True, **kwargs) return ip_wrapper.netns.execute(cmd, run_as_root=True,
privsep_exec=True, **kwargs)
def _get_qdisc_id_for_filter(self, direction): def _get_qdisc_id_for_filter(self, direction):
qdiscs = tc_lib.list_tc_qdiscs(self.name, namespace=self.namespace) qdiscs = tc_lib.list_tc_qdiscs(self.name, namespace=self.namespace)

View File

@ -35,7 +35,6 @@ from oslo_utils import excutils
from oslo_utils import fileutils from oslo_utils import fileutils
import psutil import psutil
from neutron.common import utils
from neutron.conf.agent import common as config from neutron.conf.agent import common as config
from neutron.privileged.agent.linux import utils as priv_utils from neutron.privileged.agent.linux import utils as priv_utils
from neutron import wsgi from neutron import wsgi
@ -79,16 +78,26 @@ def create_process(cmd, run_as_root=False, addl_env=None):
""" """
cmd = list(map(str, addl_env_args(addl_env) + cmd)) cmd = list(map(str, addl_env_args(addl_env) + cmd))
if run_as_root: if run_as_root:
# NOTE(ralonsoh): to be removed once the migration to privsep
# execution is done.
cmd = shlex.split(config.get_root_helper(cfg.CONF)) + cmd cmd = shlex.split(config.get_root_helper(cfg.CONF)) + cmd
LOG.debug("Running command: %s", cmd) LOG.debug("Running command: %s", cmd)
obj = utils.subprocess_popen(cmd, shell=False, obj = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
return obj, cmd return obj, cmd
def _execute_process(cmd, _process_input, addl_env, run_as_root):
obj, cmd = create_process(cmd, run_as_root=run_as_root, addl_env=addl_env)
_stdout, _stderr = obj.communicate(_process_input)
returncode = obj.returncode
obj.stdin.close()
_stdout = helpers.safe_decode_utf8(_stdout)
_stderr = helpers.safe_decode_utf8(_stderr)
return _stdout, _stderr, returncode
def execute_rootwrap_daemon(cmd, process_input, addl_env): def execute_rootwrap_daemon(cmd, process_input, addl_env):
cmd = list(map(str, addl_env_args(addl_env) + cmd)) cmd = list(map(str, addl_env_args(addl_env) + cmd))
# NOTE(twilson) oslo_rootwrap.daemon will raise on filter match # NOTE(twilson) oslo_rootwrap.daemon will raise on filter match
@ -99,31 +108,34 @@ def execute_rootwrap_daemon(cmd, process_input, addl_env):
LOG.debug("Running command (rootwrap daemon): %s", cmd) LOG.debug("Running command (rootwrap daemon): %s", cmd)
client = RootwrapDaemonHelper.get_client() client = RootwrapDaemonHelper.get_client()
try: try:
return client.execute(cmd, process_input) returncode, _stdout, _stderr = client.execute(cmd, process_input)
except Exception: except Exception:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
LOG.error("Rootwrap error running command: %s", cmd) LOG.error("Rootwrap error running command: %s", cmd)
_stdout = helpers.safe_decode_utf8(_stdout)
_stderr = helpers.safe_decode_utf8(_stderr)
return _stdout, _stderr, returncode
def execute(cmd, process_input=None, addl_env=None, def execute(cmd, process_input=None, addl_env=None,
check_exit_code=True, return_stderr=False, log_fail_as_error=True, check_exit_code=True, return_stderr=False, log_fail_as_error=True,
extra_ok_codes=None, run_as_root=False): extra_ok_codes=None, run_as_root=False, privsep_exec=False):
try: try:
if process_input is not None: if process_input is not None:
_process_input = encodeutils.to_utf8(process_input) _process_input = encodeutils.to_utf8(process_input)
else: else:
_process_input = None _process_input = None
if run_as_root and cfg.CONF.AGENT.root_helper_daemon:
returncode, _stdout, _stderr = ( if run_as_root and privsep_exec:
execute_rootwrap_daemon(cmd, process_input, addl_env)) _stdout, _stderr, returncode = priv_utils.execute_process(
cmd, _process_input, addl_env)
elif run_as_root and cfg.CONF.AGENT.root_helper_daemon:
_stdout, _stderr, returncode = execute_rootwrap_daemon(
cmd, process_input, addl_env)
else: else:
obj, cmd = create_process(cmd, run_as_root=run_as_root, _stdout, _stderr, returncode = _execute_process(
addl_env=addl_env) cmd, _process_input, addl_env, run_as_root)
_stdout, _stderr = obj.communicate(_process_input)
returncode = obj.returncode
obj.stdin.close()
_stdout = helpers.safe_decode_utf8(_stdout)
_stderr = helpers.safe_decode_utf8(_stderr)
extra_ok_codes = extra_ok_codes or [] extra_ok_codes = extra_ok_codes or []
if returncode and returncode not in extra_ok_codes: if returncode and returncode not in extra_ok_codes:
@ -202,10 +214,11 @@ def find_fork_top_parent(pid):
return pid return pid
def kill_process(pid, signal, run_as_root=False): def kill_process(pid, signal, run_as_root=False, privsep_exec=False):
"""Kill the process with the given pid using the given signal.""" """Kill the process with the given pid using the given signal."""
try: try:
execute(['kill', '-%d' % signal, pid], run_as_root=run_as_root) execute(['kill', '-%d' % signal, pid], run_as_root=run_as_root,
privsep_exec=privsep_exec)
except exceptions.ProcessExecutionError: except exceptions.ProcessExecutionError:
if process_is_running(pid): if process_is_running(pid):
raise raise

View File

@ -100,7 +100,7 @@ def kill_process(pid, signal, run_as_root=False):
def execute(cmd, process_input=None, addl_env=None, def execute(cmd, process_input=None, addl_env=None,
check_exit_code=True, return_stderr=False, log_fail_as_error=True, check_exit_code=True, return_stderr=False, log_fail_as_error=True,
extra_ok_codes=None, run_as_root=False): extra_ok_codes=None, run_as_root=False, privsep_exec=False):
if process_input is not None: if process_input is not None:
_process_input = encodeutils.to_utf8(process_input) _process_input = encodeutils.to_utf8(process_input)

View File

@ -15,6 +15,8 @@
import os import os
import re import re
from eventlet.green import subprocess
from neutron_lib.utils import helpers
from oslo_concurrency import processutils from oslo_concurrency import processutils
from oslo_utils import fileutils from oslo_utils import fileutils
@ -47,3 +49,36 @@ def _find_listen_pids_namespace(namespace):
@privileged.default.entrypoint @privileged.default.entrypoint
def delete_if_exists(path, remove=os.unlink): def delete_if_exists(path, remove=os.unlink):
fileutils.delete_if_exists(path, remove=remove) fileutils.delete_if_exists(path, remove=remove)
@privileged.default.entrypoint
def execute_process(cmd, _process_input, addl_env):
obj, cmd = _create_process(cmd, addl_env=addl_env)
_stdout, _stderr = obj.communicate(_process_input)
returncode = obj.returncode
obj.stdin.close()
_stdout = helpers.safe_decode_utf8(_stdout)
_stderr = helpers.safe_decode_utf8(_stderr)
return _stdout, _stderr, returncode
def _addl_env_args(addl_env):
"""Build arguments for adding additional environment vars with env"""
# NOTE (twilson) If using rootwrap, an EnvFilter should be set up for the
# command instead of a CommandFilter.
if addl_env is None:
return []
return ['env'] + ['%s=%s' % pair for pair in addl_env.items()]
def _create_process(cmd, addl_env=None):
"""Create a process object for the given command.
The return value will be a tuple of the process object and the
list of command arguments used to create it.
"""
cmd = list(map(str, _addl_env_args(addl_env) + list(cmd)))
obj = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return obj, cmd

View File

@ -620,7 +620,8 @@ class NamespaceFixture(fixtures.Fixture):
if self.ip_wrapper.netns.exists(self.name): if self.ip_wrapper.netns.exists(self.name):
for pid in ip_lib.list_namespace_pids(self.name): for pid in ip_lib.list_namespace_pids(self.name):
utils.kill_process(pid, signal.SIGKILL, utils.kill_process(pid, signal.SIGKILL,
run_as_root=True) run_as_root=True,
privsep_exec=True)
self.ip_wrapper.netns.delete(self.name) self.ip_wrapper.netns.delete(self.name)
except helpers.TestTimerTimeout: except helpers.TestTimerTimeout:
LOG.warning('Namespace %s was not deleted due to a timeout.', LOG.warning('Namespace %s was not deleted due to a timeout.',

View File

@ -134,8 +134,8 @@ class TcPolicyClassTestCase(functional_base.BaseSudoTestCase):
bytes = tc_classes[0]['stats']['bytes'] bytes = tc_classes[0]['stats']['bytes']
packets = tc_classes[0]['stats']['packets'] packets = tc_classes[0]['stats']['packets']
net_helpers.assert_ping(self.ns[1], netaddr.IPNetwork(self.ip[0]).ip, net_helpers.assert_ping(
count=1) self.ns[1], str(netaddr.IPNetwork(self.ip[0]).ip), count=1)
tc_classes = tc_lib.list_tc_policy_class(self.device[0], tc_classes = tc_lib.list_tc_policy_class(self.device[0],
namespace=self.ns[0]) namespace=self.ns[0])
self.assertGreater(tc_classes[0]['stats']['bytes'], bytes) self.assertGreater(tc_classes[0]['stats']['bytes'], bytes)
@ -268,7 +268,7 @@ class TcFiltersTestCase(functional_base.BaseSudoTestCase):
'device': self.device[0]}) 'device': self.device[0]})
net_helpers.assert_ping( net_helpers.assert_ping(
self.ns[1], netaddr.IPNetwork(self.ip_vxlan[0]).ip, count=1) self.ns[1], str(netaddr.IPNetwork(self.ip_vxlan[0]).ip), count=1)
tc_classes = tc_lib.list_tc_policy_class(self.device[0], tc_classes = tc_lib.list_tc_policy_class(self.device[0],
namespace=self.ns[0]) namespace=self.ns[0])
for tc_class in tc_classes: for tc_class in tc_classes:

View File

@ -2595,13 +2595,17 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
'qrouter-bar', self.conf, agent.driver, agent.use_ipv6) 'qrouter-bar', self.conf, agent.driver, agent.use_ipv6)
ns.create() ns.create()
calls = [mock.call(['sysctl', '-w', 'net.ipv4.ip_forward=1']), calls = [mock.call(['sysctl', '-w', 'net.ipv4.ip_forward=1'],
mock.call(['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1']), privsep_exec=True),
mock.call(['sysctl', '-w', 'net.ipv4.conf.all.arp_ignore=1'],
privsep_exec=True),
mock.call( mock.call(
['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2'])] ['sysctl', '-w', 'net.ipv4.conf.all.arp_announce=2'],
privsep_exec=True)]
if agent.use_ipv6: if agent.use_ipv6:
calls.append(mock.call( calls.append(mock.call(
['sysctl', '-w', 'net.ipv6.conf.all.forwarding=1'])) ['sysctl', '-w', 'net.ipv6.conf.all.forwarding=1'],
privsep_exec=True))
self.mock_ip.netns.execute.assert_has_calls(calls) self.mock_ip.netns.execute.assert_has_calls(calls)

View File

@ -217,13 +217,14 @@ class TestDvrFipNs(base.BaseTestCase):
bind_cmd = ['sysctl', '-w', 'net.ipv4.ip_nonlocal_bind=1'] bind_cmd = ['sysctl', '-w', 'net.ipv4.ip_nonlocal_bind=1']
expected = [mock.call(netns_cmd + bind_cmd, check_exit_code=True, expected = [mock.call(netns_cmd + bind_cmd, check_exit_code=True,
extra_ok_codes=None, log_fail_as_error=False, extra_ok_codes=None, log_fail_as_error=False,
run_as_root=True)] run_as_root=True, privsep_exec=True)]
if old_kernel: if old_kernel:
expected.append(mock.call(bind_cmd, check_exit_code=True, expected.append(mock.call(bind_cmd, check_exit_code=True,
extra_ok_codes=None, extra_ok_codes=None,
log_fail_as_error=True, log_fail_as_error=True,
run_as_root=True)) run_as_root=True,
privsep_exec=True))
execute.assert_has_calls(expected) execute.assert_has_calls(expected)

View File

@ -50,7 +50,8 @@ class TestDvrSnatNs(base.BaseTestCase):
loose_cmd = ['sysctl', '-w', 'net.netfilter.nf_conntrack_tcp_loose=0'] loose_cmd = ['sysctl', '-w', 'net.netfilter.nf_conntrack_tcp_loose=0']
expected = [mock.call(netns_cmd + loose_cmd, expected = [mock.call(netns_cmd + loose_cmd,
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True)] log_fail_as_error=True, run_as_root=True,
privsep_exec=True)]
create.assert_called_once_with(self.snat_ns.name) create.assert_called_once_with(self.snat_ns.name)
execute.assert_has_calls(expected) execute.assert_has_calls(expected)

View File

@ -110,8 +110,10 @@ class TestHybridIptablesHelper(base.BaseTestCase):
def test_overloaded_remove_conntrack(self): def test_overloaded_remove_conntrack(self):
with mock.patch.object(iptables_firewall.IptablesFirewallDriver, with mock.patch.object(iptables_firewall.IptablesFirewallDriver,
'_remove_conntrack_entries_from_port_deleted') as rcefpd, \ '_remove_conntrack_entries_from_port_deleted') as rcefpd, \
mock.patch("neutron.agent.linux.ip_conntrack.IpConntrackManager" mock.patch("neutron.agent.linux.ip_conntrack."
"._populate_initial_zone_map"): "IpConntrackManager._populate_initial_zone_map"), \
mock.patch.object(iptables_firewall.IptablesFirewallDriver,
'_check_netfilter_for_bridges'):
firewall = iptables.get_iptables_driver_instance() firewall = iptables.get_iptables_driver_instance()
firewall._remove_conntrack_entries_from_port_deleted(None) firewall._remove_conntrack_entries_from_port_deleted(None)
rcefpd.assert_not_called() rcefpd.assert_not_called()

View File

@ -138,7 +138,8 @@ class TestProcessManager(base.BaseTestCase):
check_exit_code=True, check_exit_code=True,
extra_ok_codes=None, extra_ok_codes=None,
run_as_root=False, run_as_root=False,
log_fail_as_error=True) log_fail_as_error=True,
privsep_exec=False)
def test_enable_with_namespace(self): def test_enable_with_namespace(self):
callback = mock.Mock() callback = mock.Mock()
@ -228,7 +229,8 @@ class TestProcessManager(base.BaseTestCase):
manager.disable() manager.disable()
utils.assert_has_calls([ utils.assert_has_calls([
mock.call.execute(['kill', '-9', 4], mock.call.execute(['kill', '-9', 4],
run_as_root=False)]) run_as_root=False,
privsep_exec=False)])
def test_disable_namespace(self): def test_disable_namespace(self):
with mock.patch.object(ep.ProcessManager, 'pid') as pid: with mock.patch.object(ep.ProcessManager, 'pid') as pid:
@ -242,7 +244,8 @@ class TestProcessManager(base.BaseTestCase):
manager.disable() manager.disable()
utils.assert_has_calls([ utils.assert_has_calls([
mock.call.execute(['kill', '-9', 4], mock.call.execute(['kill', '-9', 4],
run_as_root=True)]) run_as_root=True,
privsep_exec=False)])
def test_disable_not_active(self): def test_disable_not_active(self):
with mock.patch.object(ep.ProcessManager, 'pid') as pid: with mock.patch.object(ep.ProcessManager, 'pid') as pid:
@ -284,7 +287,8 @@ class TestProcessManager(base.BaseTestCase):
return_value=kill_script_exists): return_value=kill_script_exists):
manager.disable() manager.disable()
utils.execute.assert_called_with( utils.execute.assert_called_with(
expected_cmd, run_as_root=bool(namespace)) expected_cmd, run_as_root=bool(namespace),
privsep_exec=False)
def test_disable_custom_kill_script_no_namespace(self): def test_disable_custom_kill_script_no_namespace(self):
self._test_disable_custom_kill_script( self._test_disable_custom_kill_script(

View File

@ -858,7 +858,7 @@ class TestIpNetnsCommand(TestIPCmdBase):
['ip', 'netns', 'exec', 'ns', ['ip', 'netns', 'exec', 'ns',
'sysctl', '-w', 'net.ipv4.conf.all.promote_secondaries=1'], 'sysctl', '-w', 'net.ipv4.conf.all.promote_secondaries=1'],
run_as_root=True, check_exit_code=True, extra_ok_codes=None, run_as_root=True, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True) log_fail_as_error=True, privsep_exec=True)
@mock.patch.object(priv_lib, 'remove_netns') @mock.patch.object(priv_lib, 'remove_netns')
def test_delete_namespace(self, remove): def test_delete_namespace(self, remove):
@ -899,7 +899,8 @@ class TestIpNetnsCommand(TestIPCmdBase):
run_as_root=True, run_as_root=True,
check_exit_code=True, check_exit_code=True,
extra_ok_codes=None, extra_ok_codes=None,
log_fail_as_error=True) log_fail_as_error=True,
privsep_exec=False)
def test_execute_env_var_prepend(self): def test_execute_env_var_prepend(self):
self.parent.namespace = 'ns' self.parent.namespace = 'ns'
@ -911,7 +912,7 @@ class TestIpNetnsCommand(TestIPCmdBase):
['%s=%s' % (k, v) for k, v in env.items()] + ['%s=%s' % (k, v) for k, v in env.items()] +
['ip', 'link', 'list'], ['ip', 'link', 'list'],
run_as_root=True, check_exit_code=True, extra_ok_codes=None, run_as_root=True, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True) log_fail_as_error=True, privsep_exec=False)
def test_execute_nosudo_with_no_namespace(self): def test_execute_nosudo_with_no_namespace(self):
with mock.patch('neutron.agent.common.utils.execute') as execute: with mock.patch('neutron.agent.common.utils.execute') as execute:
@ -921,7 +922,8 @@ class TestIpNetnsCommand(TestIPCmdBase):
check_exit_code=True, check_exit_code=True,
extra_ok_codes=None, extra_ok_codes=None,
run_as_root=False, run_as_root=False,
log_fail_as_error=True) log_fail_as_error=True,
privsep_exec=False)
class TestDeviceExists(base.BaseTestCase): class TestDeviceExists(base.BaseTestCase):
@ -1378,12 +1380,18 @@ class TestArpPing(TestIPCmdBase):
self.assertTrue(spawn_n.called) self.assertTrue(spawn_n.called)
mIPWrapper.assert_has_calls([ mIPWrapper.assert_has_calls([
mock.call(namespace=mock.sentinel.ns_name), mock.call(namespace=mock.sentinel.ns_name),
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1]), mock.call().netns.execute(mock.ANY, extra_ok_codes=[1],
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1]), privsep_exec=True),
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2]), mock.call().netns.execute(mock.ANY, extra_ok_codes=[1],
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2]), privsep_exec=True),
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2]), mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2],
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2])]) privsep_exec=True),
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2],
privsep_exec=True),
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2],
privsep_exec=True),
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1, 2],
privsep_exec=True)])
ip_wrapper = mIPWrapper(namespace=mock.sentinel.ns_name) ip_wrapper = mIPWrapper(namespace=mock.sentinel.ns_name)
@ -1395,7 +1403,8 @@ class TestArpPing(TestIPCmdBase):
'-w', mock.ANY, '-w', mock.ANY,
address] address]
ip_wrapper.netns.execute.assert_any_call(arping_cmd, ip_wrapper.netns.execute.assert_any_call(arping_cmd,
extra_ok_codes=mock.ANY) extra_ok_codes=mock.ANY,
privsep_exec=True)
@mock.patch.object(ip_lib, 'IPWrapper') @mock.patch.object(ip_lib, 'IPWrapper')
@mock.patch('eventlet.spawn_n') @mock.patch('eventlet.spawn_n')
@ -1415,7 +1424,8 @@ class TestArpPing(TestIPCmdBase):
# should return early with a single call when ENODEV # should return early with a single call when ENODEV
mIPWrapper.assert_has_calls([ mIPWrapper.assert_has_calls([
mock.call(namespace=mock.sentinel.ns_name), mock.call(namespace=mock.sentinel.ns_name),
mock.call().netns.execute(mock.ANY, extra_ok_codes=[1]) mock.call().netns.execute(mock.ANY, extra_ok_codes=[1],
privsep_exec=True)
] * 1) ] * 1)
@mock.patch('eventlet.spawn_n') @mock.patch('eventlet.spawn_n')
@ -1458,7 +1468,7 @@ class TestSysctl(base.BaseTestCase):
dev.disable_ipv6() dev.disable_ipv6()
self.execute.assert_called_once_with( self.execute.assert_called_once_with(
['sysctl', '-w', 'net.ipv6.conf.tap0.disable_ipv6=1'], ['sysctl', '-w', 'net.ipv6.conf.tap0.disable_ipv6=1'],
log_fail_as_error=True, run_as_root=True) log_fail_as_error=True, run_as_root=True, privsep_exec=True)
def test_disable_ipv6_when_ipv6_globally_disabled(self): def test_disable_ipv6_when_ipv6_globally_disabled(self):
dev = ip_lib.IPDevice('tap0', 'ns1') dev = ip_lib.IPDevice('tap0', 'ns1')
@ -1483,7 +1493,8 @@ class TestConntrack(base.BaseTestCase):
'--dport', dport] '--dport', dport]
device.delete_socket_conntrack_state(ip_str, dport, protocol) device.delete_socket_conntrack_state(ip_str, dport, protocol)
self.execute.assert_called_once_with(expect_cmd, check_exit_code=True, self.execute.assert_called_once_with(expect_cmd, check_exit_code=True,
extra_ok_codes=[1]) extra_ok_codes=[1],
privsep_exec=True)
class ParseIpRuleTestCase(base.BaseTestCase): class ParseIpRuleTestCase(base.BaseTestCase):

View File

@ -47,6 +47,8 @@ class KeepalivedBaseTestCase(base.BaseTestCase):
def setUp(self): def setUp(self):
super(KeepalivedBaseTestCase, self).setUp() super(KeepalivedBaseTestCase, self).setUp()
l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF) l3_config.register_l3_agent_config_opts(l3_config.OPTS, cfg.CONF)
self._mock_no_track_supported = mock.patch.object(
keepalived, '_is_keepalived_use_no_track_supported')
class KeepalivedGetFreeRangeTestCase(KeepalivedBaseTestCase): class KeepalivedGetFreeRangeTestCase(KeepalivedBaseTestCase):
@ -193,6 +195,7 @@ class KeepalivedConfTestCase(KeepalivedBaseTestCase,
self.assertEqual(self.expected, config.get_config_str()) self.assertEqual(self.expected, config.get_config_str())
def test_config_generation_no_track_not_supported(self): def test_config_generation_no_track_not_supported(self):
self._mock_no_track_supported.start().return_value = False
config = self._get_config() config = self._get_config()
with mock.patch.object( with mock.patch.object(
keepalived, '_is_keepalived_use_no_track_supported', keepalived, '_is_keepalived_use_no_track_supported',

View File

@ -171,7 +171,8 @@ class TestFloatingIPTcCommandBase(base.BaseTestCase):
run_as_root=True, run_as_root=True,
check_exit_code=True, check_exit_code=True,
log_fail_as_error=True, log_fail_as_error=True,
extra_ok_codes=None extra_ok_codes=None,
privsep_exec=True
) )
def _test__get_filterid_for_ip(self, filters): def _test__get_filterid_for_ip(self, filters):
@ -236,7 +237,8 @@ class TestFloatingIPTcCommandBase(base.BaseTestCase):
run_as_root=True, run_as_root=True,
check_exit_code=True, check_exit_code=True,
log_fail_as_error=True, log_fail_as_error=True,
extra_ok_codes=None extra_ok_codes=None,
privsep_exec=True
) )
def _test__get_qdisc_filters(self, filters): def _test__get_qdisc_filters(self, filters):
@ -277,7 +279,8 @@ class TestFloatingIPTcCommandBase(base.BaseTestCase):
run_as_root=True, run_as_root=True,
check_exit_code=True, check_exit_code=True,
log_fail_as_error=True, log_fail_as_error=True,
extra_ok_codes=None extra_ok_codes=None,
privsep_exec=True
) )
def test__get_or_create_qdisc(self): def test__get_or_create_qdisc(self):
@ -382,7 +385,8 @@ class TestFloatingIPTcCommand(base.BaseTestCase):
run_as_root=True, run_as_root=True,
check_exit_code=True, check_exit_code=True,
log_fail_as_error=True, log_fail_as_error=True,
extra_ok_codes=None extra_ok_codes=None,
privsep_exec=True
) )
def test_set_ip_rate_limit_no_qdisc_without_chain(self): def test_set_ip_rate_limit_no_qdisc_without_chain(self):
@ -409,7 +413,8 @@ class TestFloatingIPTcCommand(base.BaseTestCase):
run_as_root=True, run_as_root=True,
check_exit_code=True, check_exit_code=True,
log_fail_as_error=True, log_fail_as_error=True,
extra_ok_codes=None extra_ok_codes=None,
privsep_exec=True
) )
def test_get_filter_id_for_ip(self): def test_get_filter_id_for_ip(self):

View File

@ -25,6 +25,7 @@ from oslo_config import cfg
import oslo_i18n import oslo_i18n
from neutron.agent.linux import utils from neutron.agent.linux import utils
from neutron.privileged.agent.linux import utils as priv_utils
from neutron.tests import base from neutron.tests import base
@ -46,7 +47,15 @@ class AgentUtilsExecuteTest(base.BaseTestCase):
result = utils.execute(["ls", self.test_file]) result = utils.execute(["ls", self.test_file])
self.assertEqual(result, expected) self.assertEqual(result, expected)
def test_with_helper(self): def test_with_root_privileges_privsep(self):
with mock.patch.object(priv_utils, 'execute_process') as \
mock_execute_process:
mock_execute_process.return_value = ['', '', 0]
utils.execute(['ls', self.test_file], run_as_root=True,
privsep_exec=True)
mock_execute_process.assert_called_once()
def test_with_root_privileges_rootwrap(self):
expected = "ls %s\n" % self.test_file expected = "ls %s\n" % self.test_file
self.mock_popen.return_value = [expected, ""] self.mock_popen.return_value = [expected, ""]
self.config(group='AGENT', root_helper='echo') self.config(group='AGENT', root_helper='echo')
@ -54,7 +63,7 @@ class AgentUtilsExecuteTest(base.BaseTestCase):
self.assertEqual(result, expected) self.assertEqual(result, expected)
@mock.patch.object(utils.RootwrapDaemonHelper, 'get_client') @mock.patch.object(utils.RootwrapDaemonHelper, 'get_client')
def test_with_helper_exception(self, get_client): def test_with_root_privileges_rootwrap_exception(self, get_client):
client_inst = mock.Mock() client_inst = mock.Mock()
client_inst.execute.side_effect = RuntimeError client_inst.execute.side_effect = RuntimeError
get_client.return_value = client_inst get_client.return_value = client_inst
@ -229,10 +238,11 @@ class TestKillProcess(base.BaseTestCase):
side_effect=exc) as mock_execute: side_effect=exc) as mock_execute:
with mock.patch.object(utils, 'process_is_running', with mock.patch.object(utils, 'process_is_running',
return_value=not pid_killed): return_value=not pid_killed):
utils.kill_process(pid, kill_signal, run_as_root=True) utils.kill_process(pid, kill_signal, run_as_root=True,
privsep_exec=False)
mock_execute.assert_called_with(['kill', '-%d' % kill_signal, pid], mock_execute.assert_called_with(['kill', '-%d' % kill_signal, pid],
run_as_root=True) run_as_root=True, privsep_exec=False)
def test_kill_process_returns_none_for_valid_pid(self): def test_kill_process_returns_none_for_valid_pid(self):
self._test_kill_process('1') self._test_kill_process('1')

View File

@ -66,34 +66,40 @@ class TestLinuxBridgeARPSpoofing(base.BaseTestCase):
expected = [ expected = [
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'], mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.ANY, mock.ANY,
mock.ANY, mock.ANY,
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
'neutronMAC-%s' % vif, '-P', 'DROP'], 'neutronMAC-%s' % vif, '-P', 'DROP'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.ANY, mock.ANY,
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
'PREROUTING', '-i', vif, '-j', mac_chain], 'PREROUTING', '-i', vif, '-j', mac_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
mac_chain, '-i', vif, mac_chain, '-i', vif,
'--among-src', '%s' % ','.join(sorted(mac_addresses)), '--among-src', '%s' % ','.join(sorted(mac_addresses)),
'-j', 'RETURN'], '-j', 'RETURN'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.ANY, mock.ANY,
mock.ANY, mock.ANY,
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
spoof_chain, '-P', 'DROP'], spoof_chain, '-P', 'DROP'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
spoof_chain], spoof_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
] ]
for addr in sorted(ip_addresses): for addr in sorted(ip_addresses):
expected.extend([ expected.extend([
@ -101,7 +107,8 @@ class TestLinuxBridgeARPSpoofing(base.BaseTestCase):
spoof_chain, '-p', 'ARP', spoof_chain, '-p', 'ARP',
'--arp-ip-src', addr, '-j', 'ACCEPT'], '--arp-ip-src', addr, '-j', 'ACCEPT'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
]) ])
expected.extend([ expected.extend([
mock.ANY, mock.ANY,
@ -109,7 +116,8 @@ class TestLinuxBridgeARPSpoofing(base.BaseTestCase):
'PREROUTING', '-i', vif, '-j', 'PREROUTING', '-i', vif, '-j',
spoof_chain, '-p', 'ARP'], spoof_chain, '-p', 'ARP'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
]) ])
arp_protect.setup_arp_spoofing_protection(vif, port) arp_protect.setup_arp_spoofing_protection(vif, port)
@ -129,56 +137,68 @@ class TestLinuxBridgeARPSpoofing(base.BaseTestCase):
expected = [ expected = [
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'], mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.ANY, mock.ANY,
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-D', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-D',
'PREROUTING', '-i', VIF, '-j', spoof_chain, 'PREROUTING', '-i', VIF, '-j', spoof_chain,
'-p', 'ARP'], '-p', 'ARP'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
spoof_chain], spoof_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-X', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-X',
spoof_chain], spoof_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.ANY, mock.ANY,
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
mac_chain], mac_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.call(['ebtables', '-t', 'nat', '--concurrent', '-X', mock.call(['ebtables', '-t', 'nat', '--concurrent', '-X',
mac_chain], mac_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-L'], mock.call(['ebtables', '-t', 'filter', '--concurrent', '-L'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.ANY, mock.ANY,
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-D', mock.call(['ebtables', '-t', 'filter', '--concurrent', '-D',
'FORWARD', '-i', VIF, '-j', spoof_chain, 'FORWARD', '-i', VIF, '-j', spoof_chain,
'-p', 'ARP'], '-p', 'ARP'],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-F', mock.call(['ebtables', '-t', 'filter', '--concurrent', '-F',
spoof_chain], spoof_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-X', mock.call(['ebtables', '-t', 'filter', '--concurrent', '-X',
spoof_chain], spoof_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.ANY, mock.ANY,
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-F', mock.call(['ebtables', '-t', 'filter', '--concurrent', '-F',
mac_chain], mac_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
mock.call(['ebtables', '-t', 'filter', '--concurrent', '-X', mock.call(['ebtables', '-t', 'filter', '--concurrent', '-X',
mac_chain], mac_chain],
check_exit_code=True, extra_ok_codes=None, check_exit_code=True, extra_ok_codes=None,
log_fail_as_error=True, run_as_root=True), log_fail_as_error=True, run_as_root=True,
privsep_exec=False),
] ]
arp_protect.delete_arp_spoofing_protection([VIF]) arp_protect.delete_arp_spoofing_protection([VIF])

View File

@ -0,0 +1,17 @@
---
other:
- |
As defined in `Migrate from oslo.rootwrap to oslo.privsep
<https://opendev.org/openstack/governance/src/branch/master/goals/selected/wallaby/migrate-to-privsep.rst>`_,
all OpenStack proyects should migrate from oslo.rootwrap to oslo.privsep
because "oslo.privsep offers a superior security model, faster and more
secure".
This migration will end with the deprecation and removal of oslo.rootwrap
from Neutron. To ensure the quality of the Neutron code, this migration
will be done sequentially in several patches, checking none of them breaks
the current functionality.
In order to easily migrate to execute all external commands inside a
privsep context, a new input variable "privsep_exec", that defaults to
"False", is added to ``neutron.agent.linux.utils.execute``. That will
divert the code to a privsep decorated executor.
Once the migration finishes, this new input parameter will be removed.