Files
os-brick/os_brick/tests/privileged/test_rootwrap.py
Angus Lees dbf77fba10 Trivial rootwrap -> privsep replacement
This change replaces all uses of rootwrap with a trivial privsep-based
equivalent.  This replacement simply executes commands as the privsep
user *without any additional checks*.

There are 2 reasons why this is a reasonable thing to do:

1. We don't have a good workflow for merging rootwrap filter changes
   into parent projects (nova/cinder) for a loosely-coupled library like
   os-brick.

2. The previous situation was also insecure.  The os-brick.filters
   rootwrap config permitted commands like "dd" and "cp" with any
   arguments, as root.  This would have posed only a mild inconvenience
   to an attacker.  With privsep we can at least (in principle) limit
   the commands to the privsep uid/gid and Linux
   capabilities (CAP_SYS_ADMIN by default with this change).

This change addresses the urgency of (1).   Later refactors will take
greater advantage of privsep to address (2).

Change-Id: I0af542eba97d2f89b1c283bf1e1e985d9690f5de
Depends-On: I90dc41bc77993bd83b80c92286e015e14f290b45
 # nova: nova.conf: Set privsep_rootwrap.helper_command
Depends-On: I4e333e73ddfd45c045b9d32dac1506fc25858c4d
 # nova: Add os-brick rootwrap filter for privsep
Depends-On: I8a0b1728cc66c4861f69623b1b16b1f759b57b25
 # cinder: cinder.conf: Set privsep_rootwrap.helper_command
Depends-On: I3b2e337321875cf4abc0ab9b44fe17cf9327d88b
 # cinder: Add os-brick rootwrap filter for privsep
Depends-On: I4299c2fc059807610f83e12a2d470e020930c64c
 # privsep: Switch to msgpack for serialization
Depends-On: Ied1ef4fc945e18516b39d1f20d58425cb633dc74
 # requirements: require oslo.privsep>=1.5.0 for msgpack fix
2016-04-15 15:29:25 +00:00

60 lines
2.5 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
from oslo_concurrency import processutils as putils
from os_brick import privileged
from os_brick.privileged import rootwrap as priv_rootwrap
from os_brick.tests import base
class PrivRootwrapTestCase(base.TestCase):
def setUp(self):
super(PrivRootwrapTestCase, self).setUp()
# Bypass privsep and run these simple functions in-process
# (allows reading back the modified state of mocks)
privileged.default.set_client_mode(False)
self.addCleanup(privileged.default.set_client_mode, True)
@mock.patch('os_brick.privileged.rootwrap.execute_root')
@mock.patch('oslo_concurrency.processutils.execute')
def test_execute(self, mock_putils_exec, mock_exec_root):
priv_rootwrap.execute('echo', 'foo', run_as_root=False)
self.assertFalse(mock_exec_root.called)
priv_rootwrap.execute('echo', 'foo', run_as_root=True,
root_helper='baz', check_exit_code=0)
mock_exec_root.assert_called_once_with(
'echo', 'foo', check_exit_code=0)
@mock.patch('oslo_concurrency.processutils.execute')
def test_execute_root(self, mock_putils_exec):
priv_rootwrap.execute_root('echo', 'foo', check_exit_code=0)
mock_putils_exec.assert_called_once_with(
'echo', 'foo', check_exit_code=0, shell=False, run_as_root=False)
# Exact exception isn't particularly important, but these
# should be errors:
self.assertRaises(TypeError,
priv_rootwrap.execute_root, 'foo', shell=True)
self.assertRaises(TypeError,
priv_rootwrap.execute_root, 'foo', run_as_root=True)
@mock.patch('oslo_concurrency.processutils.execute',
side_effect=OSError(42, 'mock error'))
def test_oserror_raise(self, mock_putils_exec):
self.assertRaises(putils.ProcessExecutionError,
priv_rootwrap.execute, 'foo')