summaryrefslogtreecommitdiffstats
path: root/tests/unit/test_rootwrap.py
diff options
context:
space:
mode:
authorRoman Podolyaka <rpodolyaka@mirantis.com>2013-03-29 23:05:52 +0200
committerRoman Podolyaka <rpodolyaka@mirantis.com>2013-04-01 17:45:17 +0300
commitae0b2762e2f467d4d3389859a602650384a2c14e (patch)
tree1cad823e07e3146ad97dd69321c6e8b775a6bbd2 /tests/unit/test_rootwrap.py
parent05219b89b367b077a1e1f61a2767e71f7f44665a (diff)
downloadoslo-ae0b2762e2f467d4d3389859a602650384a2c14e.tar.gz
oslo-ae0b2762e2f467d4d3389859a602650384a2c14e.tar.xz
oslo-ae0b2762e2f467d4d3389859a602650384a2c14e.zip
Add PathFilter to rootwrap.
PathFilter is a type of filter that allows to check if path arguments of a command resolve to file system paths within given directories. Fixes bug 1098568. Change-Id: Ie2686ad2ff114075c6d8d804031b6e3fa60a43ca
Diffstat (limited to 'tests/unit/test_rootwrap.py')
-rw-r--r--tests/unit/test_rootwrap.py119
1 files changed, 119 insertions, 0 deletions
diff --git a/tests/unit/test_rootwrap.py b/tests/unit/test_rootwrap.py
index 8ee8e72..ea6ccbb 100644
--- a/tests/unit/test_rootwrap.py
+++ b/tests/unit/test_rootwrap.py
@@ -19,6 +19,9 @@ import logging
import logging.handlers
import os
import subprocess
+import uuid
+
+import fixtures
from openstack.common.rootwrap import filters
from openstack.common.rootwrap import wrapper
@@ -198,3 +201,119 @@ class RootwrapTestCase(utils.BaseTestCase):
raw.set('DEFAULT', 'syslog_log_level', 'INFO')
config = wrapper.RootwrapConfig(raw)
self.assertEqual(config.syslog_log_level, logging.INFO)
+
+
+class PathFilterTestCase(utils.BaseTestCase):
+ def setUp(self):
+ super(PathFilterTestCase, self).setUp()
+
+ tmpdir = fixtures.TempDir('/tmp')
+ self.useFixture(tmpdir)
+
+ self.f = filters.PathFilter('/bin/chown', 'root', 'nova', tmpdir.path)
+
+ gen_name = lambda: str(uuid.uuid4())
+
+ self.SIMPLE_FILE_WITHIN_DIR = os.path.join(tmpdir.path, 'some')
+ self.SIMPLE_FILE_OUTSIDE_DIR = os.path.join('/tmp', 'some')
+ self.TRAVERSAL_WITHIN_DIR = os.path.join(tmpdir.path, 'a', '..',
+ 'some')
+ self.TRAVERSAL_OUTSIDE_DIR = os.path.join(tmpdir.path, '..', 'some')
+
+ self.TRAVERSAL_SYMLINK_WITHIN_DIR = os.path.join(tmpdir.path,
+ gen_name())
+ os.symlink(os.path.join(tmpdir.path, 'a', '..', 'a'),
+ self.TRAVERSAL_SYMLINK_WITHIN_DIR)
+
+ self.TRAVERSAL_SYMLINK_OUTSIDE_DIR = os.path.join(tmpdir.path,
+ gen_name())
+ os.symlink(os.path.join(tmpdir.path, 'a', '..', '..', '..', 'etc'),
+ self.TRAVERSAL_SYMLINK_OUTSIDE_DIR)
+
+ self.SYMLINK_WITHIN_DIR = os.path.join(tmpdir.path, gen_name())
+ os.symlink(os.path.join(tmpdir.path, 'a'), self.SYMLINK_WITHIN_DIR)
+
+ self.SYMLINK_OUTSIDE_DIR = os.path.join(tmpdir.path, gen_name())
+ os.symlink(os.path.join('/tmp', 'some_file'), self.SYMLINK_OUTSIDE_DIR)
+
+ def test_argument_pass_constraint(self):
+ f = filters.PathFilter('/bin/chown', 'root', 'pass', 'pass')
+
+ args = ['chown', 'something', self.SIMPLE_FILE_OUTSIDE_DIR]
+ self.assertTrue(f.match(args))
+
+ def test_argument_equality_constraint(self):
+ f = filters.PathFilter('/bin/chown', 'root', 'nova', '/tmp/spam/eggs')
+
+ args = ['chown', 'nova', '/tmp/spam/eggs']
+ self.assertTrue(f.match(args))
+
+ args = ['chown', 'quantum', '/tmp/spam/eggs']
+ self.assertFalse(f.match(args))
+
+ def test_wrong_arguments_number(self):
+ args = ['chown', '-c', 'nova', self.SIMPLE_FILE_WITHIN_DIR]
+ self.assertFalse(self.f.match(args))
+
+ def test_wrong_exec_command(self):
+ args = ['wrong_exec', self.SIMPLE_FILE_WITHIN_DIR]
+ self.assertFalse(self.f.match(args))
+
+ def test_match(self):
+ args = ['chown', 'nova', self.SIMPLE_FILE_WITHIN_DIR]
+ self.assertTrue(self.f.match(args))
+
+ def test_match_traversal(self):
+ args = ['chown', 'nova', self.TRAVERSAL_WITHIN_DIR]
+ self.assertTrue(self.f.match(args))
+
+ def test_match_symlink(self):
+ args = ['chown', 'nova', self.SYMLINK_WITHIN_DIR]
+ self.assertTrue(self.f.match(args))
+
+ def test_match_traversal_symlink(self):
+ args = ['chown', 'nova', self.TRAVERSAL_SYMLINK_WITHIN_DIR]
+ self.assertTrue(self.f.match(args))
+
+ def test_reject(self):
+ args = ['chown', 'nova', self.SIMPLE_FILE_OUTSIDE_DIR]
+ self.assertFalse(self.f.match(args))
+
+ def test_reject_traversal(self):
+ args = ['chown', 'nova', self.TRAVERSAL_OUTSIDE_DIR]
+ self.assertFalse(self.f.match(args))
+
+ def test_reject_symlink(self):
+ args = ['chown', 'nova', self.SYMLINK_OUTSIDE_DIR]
+ self.assertFalse(self.f.match(args))
+
+ def test_reject_traversal_symlink(self):
+ args = ['chown', 'nova', self.TRAVERSAL_SYMLINK_OUTSIDE_DIR]
+ self.assertFalse(self.f.match(args))
+
+ def test_get_command(self):
+ args = ['chown', 'nova', self.SIMPLE_FILE_WITHIN_DIR]
+ expected = ['/bin/chown', 'nova', self.SIMPLE_FILE_WITHIN_DIR]
+
+ self.assertEqual(expected, self.f.get_command(args))
+
+ def test_get_command_traversal(self):
+ args = ['chown', 'nova', self.TRAVERSAL_WITHIN_DIR]
+ expected = ['/bin/chown', 'nova',
+ os.path.realpath(self.TRAVERSAL_WITHIN_DIR)]
+
+ self.assertEqual(expected, self.f.get_command(args))
+
+ def test_get_command_symlink(self):
+ args = ['chown', 'nova', self.SYMLINK_WITHIN_DIR]
+ expected = ['/bin/chown', 'nova',
+ os.path.realpath(self.SYMLINK_WITHIN_DIR)]
+
+ self.assertEqual(expected, self.f.get_command(args))
+
+ def test_get_command_traversal_symlink(self):
+ args = ['chown', 'nova', self.TRAVERSAL_SYMLINK_WITHIN_DIR]
+ expected = ['/bin/chown', 'nova',
+ os.path.realpath(self.TRAVERSAL_SYMLINK_WITHIN_DIR)]
+
+ self.assertEqual(expected, self.f.get_command(args))