Add radvd_user config option
In some deployments, the "neutron" user does not have the permissions to modify the kernel interfaces. In those cases the radvd user should be defined. This patch introduces a new config option: "radvd_user". This config option is the username passed to radvd, used to drop root privileges and change user ID to username and group ID to the primary group of username. If no user specified (by default is an empty string), the user executing the L3 agent will be passed. If "root" specified, because radvd is spawned as root, no "username" parameter will be passed. Conflicts: neutron/tests/unit/agent/l3/test_agent.py Change-Id: Ie9a6fbf04d453a3c1c0bddf9ecaa3d4d6467e8ff Closes-Bug: #1844688 (cherry picked from commit6a5a75d5a6
) (cherry picked from commit5b6b040d07
) (cherry picked from commit9921c96218
)
This commit is contained in:
parent
f57e0e6029
commit
0b13f70f57
@ -143,8 +143,12 @@ class DaemonMonitor(object):
|
||||
|
||||
def _spawn_radvd(self, radvd_conf):
|
||||
def callback(pid_file):
|
||||
# drop radvd daemon privileges and run as the neutron user
|
||||
radvd_user = pwd.getpwuid(os.geteuid()).pw_name
|
||||
if not self._agent_conf.radvd_user:
|
||||
radvd_user = pwd.getpwuid(os.geteuid()).pw_name
|
||||
elif self._agent_conf.radvd_user == 'root':
|
||||
radvd_user = None
|
||||
else:
|
||||
radvd_user = self._agent_conf.radvd_user
|
||||
# we need to use -m syslog and f.e. not -m stderr (the default)
|
||||
# or -m stderr_syslog so that radvd 2.0+ will close stderr and
|
||||
# exit after daemonization; otherwise, the current thread will
|
||||
@ -153,8 +157,9 @@ class DaemonMonitor(object):
|
||||
radvd_cmd = [RADVD_SERVICE_CMD,
|
||||
'-C', '%s' % radvd_conf,
|
||||
'-p', '%s' % pid_file,
|
||||
'-u', '%s' % radvd_user,
|
||||
'-m', 'syslog']
|
||||
if radvd_user:
|
||||
radvd_cmd += ['-u', '%s' % radvd_user]
|
||||
return radvd_cmd
|
||||
|
||||
pm = self._get_radvd_process_manager(callback)
|
||||
|
@ -101,6 +101,14 @@ OPTS = [
|
||||
help=_('Iptables mangle mark used to mark ingress from '
|
||||
'external network. This mark will be masked with '
|
||||
'0xffff so that only the lower 16 bits will be used.')),
|
||||
cfg.StrOpt('radvd_user',
|
||||
default='',
|
||||
help=_('The username passed to radvd, used to drop root '
|
||||
'privileges and change user ID to username and group ID '
|
||||
'to the primary group of username. If no user specified '
|
||||
'(by default), the user executing the L3 agent will be '
|
||||
'passed. If "root" specified, because radvd is spawned '
|
||||
'as root, no "username" parameter will be passed.')),
|
||||
]
|
||||
|
||||
OPTS += config.EXT_NET_BRIDGE_OPTS
|
||||
|
@ -16,6 +16,8 @@
|
||||
import copy
|
||||
from itertools import chain as iter_chain
|
||||
from itertools import combinations as iter_combinations
|
||||
import os
|
||||
import pwd
|
||||
|
||||
import eventlet
|
||||
import fixtures
|
||||
@ -3093,10 +3095,11 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
|
||||
self.assertFalse(ri.remove_floating_ip.called)
|
||||
|
||||
@mock.patch('os.geteuid', return_value='490')
|
||||
@mock.patch('pwd.getpwuid', return_value=FakeUser('neutron'))
|
||||
def test_spawn_radvd(self, geteuid, getpwuid):
|
||||
router = l3_test_common.prepare_router_data(ip_version=6)
|
||||
@mock.patch.object(os, 'geteuid', return_value=mock.ANY)
|
||||
@mock.patch.object(pwd, 'getpwuid')
|
||||
def test_spawn_radvd(self, mock_getpwuid, *args):
|
||||
router = l3_test_common.prepare_router_data(
|
||||
ip_version=lib_constants.IP_VERSION_6)
|
||||
|
||||
conffile = '/fake/radvd.conf'
|
||||
pidfile = '/fake/radvd.pid'
|
||||
@ -3122,19 +3125,25 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
|
||||
agent.process_monitor,
|
||||
l3_test_common.FakeDev,
|
||||
self.conf)
|
||||
radvd.enable(router['_interfaces'])
|
||||
|
||||
cmd = execute.call_args[0][0]
|
||||
|
||||
self.assertIn('radvd', cmd)
|
||||
|
||||
_join = lambda *args: ' '.join(args)
|
||||
|
||||
cmd = _join(*cmd)
|
||||
self.assertIn(_join('-C', conffile), cmd)
|
||||
self.assertIn(_join('-p', pidfile), cmd)
|
||||
self.assertIn(_join('-u', 'neutron'), cmd)
|
||||
self.assertIn(_join('-m', 'syslog'), cmd)
|
||||
test_users = [('', 'stack', '-u stack'),
|
||||
('neutron', mock.ANY, '-u neutron'),
|
||||
('root', mock.ANY, None)]
|
||||
for radvd_user, os_user, to_check in test_users:
|
||||
self.conf.set_override('radvd_user', radvd_user)
|
||||
mock_getpwuid.return_value = FakeUser(os_user)
|
||||
radvd.enable(router['_interfaces'])
|
||||
cmd = execute.call_args[0][0]
|
||||
_join = lambda *args: ' '.join(args)
|
||||
cmd = _join(*cmd)
|
||||
self.assertIn('radvd', cmd)
|
||||
self.assertIn(_join('-C', conffile), cmd)
|
||||
self.assertIn(_join('-p', pidfile), cmd)
|
||||
self.assertIn(_join('-m', 'syslog'), cmd)
|
||||
if to_check:
|
||||
self.assertIn(to_check, cmd)
|
||||
else:
|
||||
self.assertNotIn('-u', cmd)
|
||||
|
||||
def test_generate_radvd_mtu_conf(self):
|
||||
router = l3_test_common.prepare_router_data()
|
||||
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
other:
|
||||
- |
|
||||
A new config option, ``radvd_user``, was added to l3_agent.ini for the L3
|
||||
agent. This option defines the username passed to radvd, used to drop
|
||||
"root" privileges and change user ID to username and group ID to the
|
||||
primary group of the user. If no user specified (by default), the user
|
||||
executing the L3 agent will be passed. If "root" specified, because radvd
|
||||
is spawned as root, no "username" parameter will be passed.
|
||||
(For more information see bug `1844688
|
||||
<https://bugs.launchpad.net/neutron/+bug/1844688>`_.)
|
Loading…
Reference in New Issue
Block a user