summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--test/conftest.py4
-rw-r--r--test/test_go_isolation.py24
-rw-r--r--test/test_php_isolation.py17
-rw-r--r--test/test_python_isolation.py17
-rw-r--r--test/test_python_isolation_chroot.py1
-rw-r--r--test/test_ruby_isolation.py17
-rw-r--r--test/unit/check/isolation.py158
-rw-r--r--test/unit/feature/isolation.py160
-rw-r--r--test/unit/main.py46
-rw-r--r--test/unit/utils.py12
10 files changed, 197 insertions, 259 deletions
diff --git a/test/conftest.py b/test/conftest.py
index 6783f16d..07d5f059 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -17,6 +17,7 @@ import pytest
from unit.check.go import check_go
from unit.check.node import check_node
from unit.check.tls import check_openssl
+from unit.check.isolation import check_isolation
from unit.option import option
from unit.utils import public_dir
from unit.utils import waitforfiles
@@ -123,6 +124,7 @@ def pytest_sessionstart(session):
option.available = {'modules': {}, 'features': {}}
unit = unit_run()
+ option.temp_dir = unit['temp_dir']
# read unit.log
@@ -161,6 +163,8 @@ def pytest_sessionstart(session):
k: v for k, v in option.available['modules'].items() if v is not None
}
+ check_isolation()
+
unit_stop()
_check_alerts()
diff --git a/test/test_go_isolation.py b/test/test_go_isolation.py
index ac12c8ca..48c1b80c 100644
--- a/test/test_go_isolation.py
+++ b/test/test_go_isolation.py
@@ -5,31 +5,13 @@ import shutil
import pytest
-from conftest import unit_run
-from conftest import unit_stop
from unit.applications.lang.go import TestApplicationGo
-from unit.feature.isolation import TestFeatureIsolation
from unit.option import option
+from unit.utils import getns
class TestGoIsolation(TestApplicationGo):
prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']}
- isolation = TestFeatureIsolation()
-
- @classmethod
- def setup_class(cls, complete_check=True):
- check = super().setup_class(complete_check=False)
-
- unit = unit_run()
- option.temp_dir = unit['temp_dir']
-
- 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
@@ -219,8 +201,8 @@ class TestGoIsolation(TestApplicationGo):
== option.available['features']['isolation'][ns]
), ('%s match' % ns)
- assert obj['NS']['MNT'] != self.isolation.getns('mnt'), 'mnt set'
- assert obj['NS']['USER'] != self.isolation.getns('user'), 'user set'
+ assert obj['NS']['MNT'] != getns('mnt'), 'mnt set'
+ assert obj['NS']['USER'] != getns('user'), 'user set'
def test_isolation_pid(self, is_su):
if not self.isolation_key('pid'):
diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py
index 1d0b0614..b0fea383 100644
--- a/test/test_php_isolation.py
+++ b/test/test_php_isolation.py
@@ -2,30 +2,13 @@ import shutil
import pytest
-from conftest import unit_run
-from conftest import unit_stop
from unit.applications.lang.php import TestApplicationPHP
-from unit.feature.isolation import TestFeatureIsolation
from unit.option import option
class TestPHPIsolation(TestApplicationPHP):
prerequisites = {'modules': {'php': 'any'}, 'features': ['isolation']}
- @classmethod
- def setup_class(cls, complete_check=True):
- check = super().setup_class(complete_check=False)
-
- unit = unit_run()
- option.temp_dir = unit['temp_dir']
-
- 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 test_php_isolation_rootfs(self, is_su, temp_dir):
isolation_features = option.available['features']['isolation'].keys()
diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py
index 66ff2f16..ad830269 100644
--- a/test/test_python_isolation.py
+++ b/test/test_python_isolation.py
@@ -2,30 +2,13 @@ import shutil
import pytest
-from conftest import unit_run
-from conftest import unit_stop
from unit.applications.lang.python import TestApplicationPython
-from unit.feature.isolation import TestFeatureIsolation
from unit.option import option
class TestPythonIsolation(TestApplicationPython):
prerequisites = {'modules': {'python': 'any'}, 'features': ['isolation']}
- @classmethod
- def setup_class(cls, complete_check=True):
- check = super().setup_class(complete_check=False)
-
- unit = unit_run()
- option.temp_dir = unit['temp_dir']
-
- 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 test_python_isolation_rootfs(self, is_su, temp_dir):
isolation_features = option.available['features']['isolation'].keys()
diff --git a/test/test_python_isolation_chroot.py b/test/test_python_isolation_chroot.py
index 8018d5b9..7f559bcc 100644
--- a/test/test_python_isolation_chroot.py
+++ b/test/test_python_isolation_chroot.py
@@ -1,7 +1,6 @@
import pytest
from unit.applications.lang.python import TestApplicationPython
-from unit.feature.isolation import TestFeatureIsolation
class TestPythonIsolation(TestApplicationPython):
diff --git a/test/test_ruby_isolation.py b/test/test_ruby_isolation.py
index 8c382e5a..fab428e9 100644
--- a/test/test_ruby_isolation.py
+++ b/test/test_ruby_isolation.py
@@ -3,30 +3,13 @@ import shutil
import os
import pytest
-from conftest import unit_run
-from conftest import unit_stop
from unit.applications.lang.ruby import TestApplicationRuby
-from unit.feature.isolation import TestFeatureIsolation
from unit.option import option
class TestRubyIsolation(TestApplicationRuby):
prerequisites = {'modules': {'ruby': 'any'}, 'features': ['isolation']}
- @classmethod
- def setup_class(cls, complete_check=True):
- check = super().setup_class(complete_check=False)
-
- unit = unit_run()
- option.temp_dir = unit['temp_dir']
-
- 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 test_ruby_isolation_rootfs(self, is_su):
isolation_features = option.available['features']['isolation'].keys()
diff --git a/test/unit/check/isolation.py b/test/unit/check/isolation.py
new file mode 100644
index 00000000..bb8feed1
--- /dev/null
+++ b/test/unit/check/isolation.py
@@ -0,0 +1,158 @@
+import json
+import os
+
+from unit.applications.lang.go import TestApplicationGo
+from unit.applications.lang.java import TestApplicationJava
+from unit.applications.lang.node import TestApplicationNode
+from unit.applications.proto import TestApplicationProto
+from unit.http import TestHTTP
+from unit.option import option
+from unit.utils import getns
+
+allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net']
+http = TestHTTP()
+
+def check_isolation():
+ test_conf = {"namespaces": {"credential": True}}
+ available = option.available
+
+ conf = ''
+ if 'go' in available['modules']:
+ TestApplicationGo().prepare_env('empty', 'app')
+
+ conf = {
+ "listeners": {"*:7080": {"pass": "applications/empty"}},
+ "applications": {
+ "empty": {
+ "type": "external",
+ "processes": {"spare": 0},
+ "working_directory": option.test_dir + "/go/empty",
+ "executable": option.temp_dir + "/go/app",
+ "isolation": {"namespaces": {"credential": True}},
+ },
+ },
+ }
+
+ elif 'python' in available['modules']:
+ conf = {
+ "listeners": {"*:7080": {"pass": "applications/empty"}},
+ "applications": {
+ "empty": {
+ "type": "python",
+ "processes": {"spare": 0},
+ "path": option.test_dir + "/python/empty",
+ "working_directory": option.test_dir + "/python/empty",
+ "module": "wsgi",
+ "isolation": {"namespaces": {"credential": True}},
+ }
+ },
+ }
+
+ elif 'php' in available['modules']:
+ conf = {
+ "listeners": {"*:7080": {"pass": "applications/phpinfo"}},
+ "applications": {
+ "phpinfo": {
+ "type": "php",
+ "processes": {"spare": 0},
+ "root": option.test_dir + "/php/phpinfo",
+ "working_directory": option.test_dir + "/php/phpinfo",
+ "index": "index.php",
+ "isolation": {"namespaces": {"credential": True}},
+ }
+ },
+ }
+
+ elif 'ruby' in available['modules']:
+ conf = {
+ "listeners": {"*:7080": {"pass": "applications/empty"}},
+ "applications": {
+ "empty": {
+ "type": "ruby",
+ "processes": {"spare": 0},
+ "working_directory": option.test_dir + "/ruby/empty",
+ "script": option.test_dir + "/ruby/empty/config.ru",
+ "isolation": {"namespaces": {"credential": True}},
+ }
+ },
+ }
+
+ elif 'java' in available['modules']:
+ TestApplicationJava().prepare_env('empty')
+
+ conf = {
+ "listeners": {"*:7080": {"pass": "applications/empty"}},
+ "applications": {
+ "empty": {
+ "unit_jars": option.current_dir + "/build",
+ "type": "java",
+ "processes": {"spare": 0},
+ "working_directory": option.test_dir + "/java/empty/",
+ "webapp": option.temp_dir + "/java",
+ "isolation": {"namespaces": {"credential": True}},
+ }
+ },
+ }
+
+ elif 'node' in available['modules']:
+ TestApplicationNode().prepare_env('basic')
+
+ conf = {
+ "listeners": {"*:7080": {"pass": "applications/basic"}},
+ "applications": {
+ "basic": {
+ "type": "external",
+ "processes": {"spare": 0},
+ "working_directory": option.temp_dir + "/node",
+ "executable": "app.js",
+ "isolation": {"namespaces": {"credential": True}},
+ }
+ },
+ }
+
+ elif 'perl' in available['modules']:
+ conf = {
+ "listeners": {"*:7080": {"pass": "applications/body_empty"}},
+ "applications": {
+ "body_empty": {
+ "type": "perl",
+ "processes": {"spare": 0},
+ "working_directory": option.test_dir
+ + "/perl/body_empty",
+ "script": option.test_dir + "/perl/body_empty/psgi.pl",
+ "isolation": {"namespaces": {"credential": True}},
+ }
+ },
+ }
+
+ else:
+ return
+
+ resp = http.put(
+ url='/config',
+ sock_type='unix',
+ addr=option.temp_dir + '/control.unit.sock',
+ body=json.dumps(conf),
+ )
+
+ if 'success' not in resp:
+ return
+
+ userns = getns('user')
+ if not userns:
+ return
+
+ available['features']['isolation'] = {'user': userns}
+
+ unp_clone_path = '/proc/sys/kernel/unprivileged_userns_clone'
+ if os.path.exists(unp_clone_path):
+ with open(unp_clone_path, 'r') as f:
+ if str(f.read()).rstrip() == '1':
+ available['features']['isolation'][
+ 'unprivileged_userns_clone'
+ ] = True
+
+ for ns in allns:
+ ns_value = getns(ns)
+ if ns_value:
+ available['features']['isolation'][ns] = ns_value
diff --git a/test/unit/feature/isolation.py b/test/unit/feature/isolation.py
deleted file mode 100644
index d8f68919..00000000
--- a/test/unit/feature/isolation.py
+++ /dev/null
@@ -1,160 +0,0 @@
-import os
-
-from unit.applications.lang.go import TestApplicationGo
-from unit.applications.lang.java import TestApplicationJava
-from unit.applications.lang.node import TestApplicationNode
-from unit.applications.proto import TestApplicationProto
-from unit.option import option
-
-
-class TestFeatureIsolation(TestApplicationProto):
- allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net']
-
- def check(self, available, temp_dir):
- test_conf = {"namespaces": {"credential": True}}
-
- conf = ''
- if 'go' in available['modules']:
- TestApplicationGo().prepare_env('empty', 'app')
-
- conf = {
- "listeners": {"*:7080": {"pass": "applications/empty"}},
- "applications": {
- "empty": {
- "type": "external",
- "processes": {"spare": 0},
- "working_directory": option.test_dir + "/go/empty",
- "executable": option.temp_dir + "/go/app",
- "isolation": {"namespaces": {"credential": True}},
- },
- },
- }
-
- elif 'python' in available['modules']:
- conf = {
- "listeners": {"*:7080": {"pass": "applications/empty"}},
- "applications": {
- "empty": {
- "type": "python",
- "processes": {"spare": 0},
- "path": option.test_dir + "/python/empty",
- "working_directory": option.test_dir + "/python/empty",
- "module": "wsgi",
- "isolation": {"namespaces": {"credential": True}},
- }
- },
- }
-
- elif 'php' in available['modules']:
- conf = {
- "listeners": {"*:7080": {"pass": "applications/phpinfo"}},
- "applications": {
- "phpinfo": {
- "type": "php",
- "processes": {"spare": 0},
- "root": option.test_dir + "/php/phpinfo",
- "working_directory": option.test_dir + "/php/phpinfo",
- "index": "index.php",
- "isolation": {"namespaces": {"credential": True}},
- }
- },
- }
-
- elif 'ruby' in available['modules']:
- conf = {
- "listeners": {"*:7080": {"pass": "applications/empty"}},
- "applications": {
- "empty": {
- "type": "ruby",
- "processes": {"spare": 0},
- "working_directory": option.test_dir + "/ruby/empty",
- "script": option.test_dir + "/ruby/empty/config.ru",
- "isolation": {"namespaces": {"credential": True}},
- }
- },
- }
-
- elif 'java' in available['modules']:
- TestApplicationJava().prepare_env('empty')
-
- conf = {
- "listeners": {"*:7080": {"pass": "applications/empty"}},
- "applications": {
- "empty": {
- "unit_jars": option.current_dir + "/build",
- "type": "java",
- "processes": {"spare": 0},
- "working_directory": option.test_dir + "/java/empty/",
- "webapp": option.temp_dir + "/java",
- "isolation": {"namespaces": {"credential": True}},
- }
- },
- }
-
- elif 'node' in available['modules']:
- TestApplicationNode().prepare_env('basic')
-
- conf = {
- "listeners": {"*:7080": {"pass": "applications/basic"}},
- "applications": {
- "basic": {
- "type": "external",
- "processes": {"spare": 0},
- "working_directory": option.temp_dir + "/node",
- "executable": "app.js",
- "isolation": {"namespaces": {"credential": True}},
- }
- },
- }
-
- elif 'perl' in available['modules']:
- conf = {
- "listeners": {"*:7080": {"pass": "applications/body_empty"}},
- "applications": {
- "body_empty": {
- "type": "perl",
- "processes": {"spare": 0},
- "working_directory": option.test_dir
- + "/perl/body_empty",
- "script": option.test_dir + "/perl/body_empty/psgi.pl",
- "isolation": {"namespaces": {"credential": True}},
- }
- },
- }
-
- else:
- return
-
- if 'success' not in self.conf(conf):
- return
-
- userns = self.getns('user')
- if not userns:
- return
-
- available['features']['isolation'] = {'user': userns}
-
- unp_clone_path = '/proc/sys/kernel/unprivileged_userns_clone'
- if os.path.exists(unp_clone_path):
- with open(unp_clone_path, 'r') as f:
- if str(f.read()).rstrip() == '1':
- available['features']['isolation'][
- 'unprivileged_userns_clone'
- ] = True
-
- for ns in self.allns:
- ns_value = self.getns(ns)
- if ns_value:
- available['features']['isolation'][ns] = ns_value
-
- def getns(self, nstype):
- # read namespace id from symlink file:
- # it points to: '<nstype>:[<ns id>]'
- # # eg.: 'pid:[4026531836]'
- nspath = '/proc/self/ns/' + nstype
- data = None
-
- if os.path.exists(nspath):
- data = int(os.readlink(nspath)[len(nstype) + 2 : -1])
-
- return data
diff --git a/test/unit/main.py b/test/unit/main.py
index fce6a322..749ff3ab 100644
--- a/test/unit/main.py
+++ b/test/unit/main.py
@@ -4,39 +4,33 @@ from unit.option import option
class TestUnit():
@classmethod
- def setup_class(cls, complete_check=True):
- def check():
- missed = []
+ def setup_class(cls):
+ missed = []
- # check modules
+ # check modules
- if 'modules' in cls.prerequisites:
- available_modules = list(option.available['modules'].keys())
+ if 'modules' in cls.prerequisites:
+ available_modules = list(option.available['modules'].keys())
- for module in cls.prerequisites['modules']:
- if module in available_modules:
- continue
+ for module in cls.prerequisites['modules']:
+ if module in available_modules:
+ continue
- missed.append(module)
+ missed.append(module)
- if missed:
- pytest.skip('Unit has no ' + ', '.join(missed) + ' module(s)')
+ if missed:
+ pytest.skip('Unit has no ' + ', '.join(missed) + ' module(s)')
- # check features
+ # check features
- if 'features' in cls.prerequisites:
- available_features = list(option.available['features'].keys())
+ if 'features' in cls.prerequisites:
+ available_features = list(option.available['features'].keys())
- for feature in cls.prerequisites['features']:
- if feature in available_features:
- continue
+ for feature in cls.prerequisites['features']:
+ if feature in available_features:
+ continue
- missed.append(feature)
+ missed.append(feature)
- if missed:
- pytest.skip(', '.join(missed) + ' feature(s) not supported')
-
- if complete_check:
- check()
- else:
- return check
+ if missed:
+ pytest.skip(', '.join(missed) + ' feature(s) not supported')
diff --git a/test/unit/utils.py b/test/unit/utils.py
index f24e9728..1307a4f6 100644
--- a/test/unit/utils.py
+++ b/test/unit/utils.py
@@ -48,3 +48,15 @@ def waitforsocket(port):
pytest.fail('Can\'t connect to the 127.0.0.1:' + port)
+
+def getns(nstype):
+ # read namespace id from symlink file:
+ # it points to: '<nstype>:[<ns id>]'
+ # # eg.: 'pid:[4026531836]'
+ nspath = '/proc/self/ns/' + nstype
+ data = None
+
+ if os.path.exists(nspath):
+ data = int(os.readlink(nspath)[len(nstype) + 2 : -1])
+
+ return data