diff options
Diffstat (limited to 'nova')
-rwxr-xr-x | nova/rootwrap/filters.py | 17 | ||||
-rw-r--r-- | nova/tests/test_nova_rootwrap.py | 9 | ||||
-rw-r--r-- | nova/tests/test_utils.py | 12 | ||||
-rw-r--r-- | nova/utils.py | 9 |
4 files changed, 47 insertions, 0 deletions
diff --git a/nova/rootwrap/filters.py b/nova/rootwrap/filters.py index d16fc9a57..faaeb11f7 100755 --- a/nova/rootwrap/filters.py +++ b/nova/rootwrap/filters.py @@ -123,3 +123,20 @@ class KillFilter(CommandFilter): # Incorrect PID return False return True + + +class ReadFileFilter(CommandFilter): + """Specific filter for the utils.read_file_as_root call""" + + def __init__(self, file_path, *args): + self.file_path = file_path + super(ReadFileFilter, self).__init__("/bin/cat", "root", *args) + + def match(self, userargs): + if userargs[0] != 'cat': + return False + if userargs[1] != self.file_path: + return False + if len(userargs) != 2: + return False + return True diff --git a/nova/tests/test_nova_rootwrap.py b/nova/tests/test_nova_rootwrap.py index 4dc476615..38cce3b35 100644 --- a/nova/tests/test_nova_rootwrap.py +++ b/nova/tests/test_nova_rootwrap.py @@ -93,6 +93,15 @@ class RootwrapTestCase(test.TestCase): # Providing -9 signal should work self.assertTrue(f.match(usercmd)) + def test_ReadFileFilter(self): + goodfn = '/good/file.name' + f = filters.ReadFileFilter(goodfn) + usercmd = ['cat', '/bad/file'] + self.assertFalse(f.match(['cat', '/bad/file'])) + usercmd = ['cat', goodfn] + self.assertEqual(f.get_command(usercmd), ['/bin/cat', goodfn]) + self.assertTrue(f.match(usercmd)) + def test_skips(self): # Check that all filters are skipped and that the last matches usercmd = ["cat", "/"] diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py index 6c6e6fcd8..5da717bee 100644 --- a/nova/tests/test_utils.py +++ b/nova/tests/test_utils.py @@ -382,6 +382,18 @@ class GenericUtilsTestCase(test.TestCase): self.assertTrue([c for c in password if c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ']) + def test_read_file_as_root(self): + def fake_execute(*args, **kwargs): + if args[1] == 'bad': + raise exception.ProcessExecutionError + return 'fakecontents', None + + self.stubs.Set(utils, 'execute', fake_execute) + contents = utils.read_file_as_root('good') + self.assertEqual(contents, 'fakecontents') + self.assertRaises(exception.FileNotFound, + utils.read_file_as_root, 'bad') + class IsUUIDLikeTestCase(test.TestCase): def assertUUIDLike(self, val, expected): diff --git a/nova/utils.py b/nova/utils.py index c93b48fc6..a98897d82 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -1413,3 +1413,12 @@ def generate_mac_address(): random.randint(0x00, 0xff), random.randint(0x00, 0xff)] return ':'.join(map(lambda x: "%02x" % x, mac)) + + +def read_file_as_root(file_path): + """Secure helper to read file as root.""" + try: + out, _err = execute('cat', file_path, run_as_root=True) + return out + except exception.ProcessExecutionError: + raise exception.FileNotFound(file_path=file_path) |