summaryrefslogtreecommitdiffhomepage
path: root/test/test_go_isolation.py
diff options
context:
space:
mode:
authorAndrei Belov <defan@nginx.com>2020-11-19 21:19:57 +0300
committerAndrei Belov <defan@nginx.com>2020-11-19 21:19:57 +0300
commit7f9079a3cd4cdb6ac3fea53f10bd34fe8b82fe9c (patch)
treec79dc48a3260156f3f824ecd299e5a4934d749c5 /test/test_go_isolation.py
parent646d047e5d12515ceac02279b373601ce0752982 (diff)
parent806a9b2515c60b12a68cd97af04f7fa5cb4dffed (diff)
downloadunit-1.21.0-1.tar.gz
unit-1.21.0-1.tar.bz2
Merged with the default branch.1.21.0-1
Diffstat (limited to 'test/test_go_isolation.py')
-rw-r--r--test/test_go_isolation.py135
1 files changed, 98 insertions, 37 deletions
diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py
index 1e7243f6..8c4a6b9c 100644
--- a/test/test_go_isolation.py
+++ b/test/test_go_isolation.py
@@ -1,9 +1,13 @@
import grp
import os
import pwd
+import shutil
import pytest
+from conftest import option
+from conftest import unit_run
+from conftest import unit_stop
from unit.applications.lang.go import TestApplicationGo
from unit.feature.isolation import TestFeatureIsolation
@@ -14,11 +18,17 @@ class TestGoIsolation(TestApplicationGo):
@classmethod
def setup_class(cls, complete_check=True):
- unit = super().setup_class(complete_check=False)
+ check = super().setup_class(complete_check=False)
- TestFeatureIsolation().check(cls.available, unit.temp_dir)
+ unit = unit_run()
+ option.temp_dir = unit['temp_dir']
- return unit if not complete_check else unit.complete()
+ TestFeatureIsolation().check(option.available, unit['temp_dir'])
+
+ assert unit_stop() is None
+ shutil.rmtree(unit['temp_dir'])
+
+ return check if not complete_check else check()
def unpriv_creds(self):
nobody_uid = pwd.getpwnam('nobody').pw_uid
@@ -26,21 +36,21 @@ class TestGoIsolation(TestApplicationGo):
try:
nogroup_gid = grp.getgrnam('nogroup').gr_gid
nogroup = 'nogroup'
- except:
+ except KeyError:
nogroup_gid = grp.getgrnam('nobody').gr_gid
nogroup = 'nobody'
return (nobody_uid, nogroup_gid, nogroup)
def isolation_key(self, key):
- return key in self.available['features']['isolation'].keys()
+ return key in option.available['features']['isolation'].keys()
def test_isolation_values(self):
self.load('ns_inspect')
obj = self.getjson()['body']
- for ns, ns_value in self.available['features']['isolation'].items():
+ for ns, ns_value in option.available['features']['isolation'].items():
if ns.upper() in obj['NS']:
assert obj['NS'][ns.upper()] == ns_value, '%s match' % ns
@@ -198,7 +208,7 @@ class TestGoIsolation(TestApplicationGo):
obj = self.getjson()['body']
# all but user and mnt
- allns = list(self.available['features']['isolation'].keys())
+ allns = list(option.available['features']['isolation'].keys())
allns.remove('user')
allns.remove('mnt')
@@ -206,7 +216,7 @@ class TestGoIsolation(TestApplicationGo):
if ns.upper() in obj['NS']:
assert (
obj['NS'][ns.upper()]
- == self.available['features']['isolation'][ns]
+ == option.available['features']['isolation'][ns]
), ('%s match' % ns)
assert obj['NS']['MNT'] != self.isolation.getns('mnt'), 'mnt set'
@@ -216,13 +226,23 @@ class TestGoIsolation(TestApplicationGo):
if not self.isolation_key('pid'):
pytest.skip('pid namespace is not supported')
- if not (is_su or self.isolation_key('unprivileged_userns_clone')):
- pytest.skip('requires root or unprivileged_userns_clone')
+ if not is_su:
+ if not self.isolation_key('unprivileged_userns_clone'):
+ pytest.skip('unprivileged clone is not available')
- self.load(
- 'ns_inspect',
- isolation={'namespaces': {'pid': True, 'credential': True}},
- )
+ if not self.isolation_key('user'):
+ pytest.skip('user namespace is not supported')
+
+ if not self.isolation_key('mnt'):
+ pytest.skip('mnt namespace is not supported')
+
+ isolation = {'namespaces': {'pid': True}}
+
+ if not is_su:
+ isolation['namespaces']['mount'] = True
+ isolation['namespaces']['credential'] = True
+
+ self.load('ns_inspect', isolation=isolation)
obj = self.getjson()['body']
@@ -230,7 +250,7 @@ class TestGoIsolation(TestApplicationGo):
def test_isolation_namespace_false(self):
self.load('ns_inspect')
- allns = list(self.available['features']['isolation'].keys())
+ allns = list(option.available['features']['isolation'].keys())
remove_list = ['unprivileged_userns_clone', 'ipc', 'cgroup']
allns = [ns for ns in allns if ns not in remove_list]
@@ -256,20 +276,31 @@ class TestGoIsolation(TestApplicationGo):
if ns.upper() in obj['NS']:
assert (
obj['NS'][ns.upper()]
- == self.available['features']['isolation'][ns]
+ == option.available['features']['isolation'][ns]
), ('%s match' % ns)
- def test_go_isolation_rootfs_container(self):
- if not self.isolation_key('unprivileged_userns_clone'):
- pytest.skip('unprivileged clone is not available')
+ def test_go_isolation_rootfs_container(self, is_su, temp_dir):
+ if not is_su:
+ if not self.isolation_key('unprivileged_userns_clone'):
+ pytest.skip('unprivileged clone is not available')
- if not self.isolation_key('mnt'):
- pytest.skip('mnt namespace is not supported')
+ if not self.isolation_key('user'):
+ pytest.skip('user namespace is not supported')
- isolation = {
- 'namespaces': {'mount': True, 'credential': True},
- 'rootfs': self.temp_dir,
- }
+ if not self.isolation_key('mnt'):
+ pytest.skip('mnt namespace is not supported')
+
+ if not self.isolation_key('pid'):
+ pytest.skip('pid namespace is not supported')
+
+ isolation = {'rootfs': temp_dir}
+
+ if not is_su:
+ isolation['namespaces'] = {
+ 'mount': True,
+ 'credential': True,
+ 'pid': True
+ }
self.load('ns_inspect', isolation=isolation)
@@ -280,7 +311,7 @@ class TestGoIsolation(TestApplicationGo):
obj = self.getjson(url='/?file=/bin/sh')['body']
assert obj['FileExists'] == False, 'file should not exists'
- def test_go_isolation_rootfs_container_priv(self, is_su):
+ def test_go_isolation_rootfs_container_priv(self, is_su, temp_dir):
if not is_su:
pytest.skip('requires root')
@@ -289,7 +320,7 @@ class TestGoIsolation(TestApplicationGo):
isolation = {
'namespaces': {'mount': True},
- 'rootfs': self.temp_dir,
+ 'rootfs': temp_dir,
}
self.load('ns_inspect', isolation=isolation)
@@ -301,20 +332,50 @@ class TestGoIsolation(TestApplicationGo):
obj = self.getjson(url='/?file=/bin/sh')['body']
assert obj['FileExists'] == False, 'file should not exists'
- def test_go_isolation_rootfs_default_tmpfs(self):
- if not self.isolation_key('unprivileged_userns_clone'):
- pytest.skip('unprivileged clone is not available')
+ def test_go_isolation_rootfs_automount_tmpfs(self, is_su, temp_dir):
+ try:
+ open("/proc/self/mountinfo")
+ except:
+ pytest.skip('The system lacks /proc/self/mountinfo file')
- if not self.isolation_key('mnt'):
- pytest.skip('mnt namespace is not supported')
+ if not is_su:
+ if not self.isolation_key('unprivileged_userns_clone'):
+ pytest.skip('unprivileged clone is not available')
- isolation = {
- 'namespaces': {'mount': True, 'credential': True},
- 'rootfs': self.temp_dir,
+ if not self.isolation_key('user'):
+ pytest.skip('user namespace is not supported')
+
+ if not self.isolation_key('mnt'):
+ pytest.skip('mnt namespace is not supported')
+
+ if not self.isolation_key('pid'):
+ pytest.skip('pid namespace is not supported')
+
+ isolation = {'rootfs': temp_dir}
+
+ if not is_su:
+ isolation['namespaces'] = {
+ 'mount': True,
+ 'credential': True,
+ 'pid': True
+ }
+
+ self.load('ns_inspect', isolation=isolation)
+
+ obj = self.getjson(url='/?mounts=true')['body']
+
+ assert (
+ "/ /tmp" in obj['Mounts'] and "tmpfs" in obj['Mounts']
+ ), 'app has /tmp mounted on /'
+
+ isolation['automount'] = {
+ 'tmpfs': False
}
self.load('ns_inspect', isolation=isolation)
- obj = self.getjson(url='/?file=/tmp')['body']
+ obj = self.getjson(url='/?mounts=true')['body']
- assert obj['FileExists'] == True, 'app has /tmp'
+ assert (
+ "/ /tmp" not in obj['Mounts'] and "tmpfs" not in obj['Mounts']
+ ), 'app has no /tmp mounted'