xref: /unit/test/unit/check/isolation.py (revision 1971:3410f9d2a662)
1import json
2import os
3
4from unit.applications.lang.go import TestApplicationGo
5from unit.applications.lang.java import TestApplicationJava
6from unit.applications.lang.node import TestApplicationNode
7from unit.applications.lang.ruby import TestApplicationRuby
8from unit.applications.proto import TestApplicationProto
9from unit.http import TestHTTP
10from unit.option import option
11from unit.utils import getns
12
13allns = ['pid', 'mnt', 'ipc', 'uts', 'cgroup', 'net']
14http = TestHTTP()
15
16
17def check_isolation():
18    test_conf = {"namespaces": {"credential": True}}
19    available = option.available
20
21    conf = ''
22    if 'go' in available['modules']:
23        TestApplicationGo().prepare_env('empty', 'app')
24
25        conf = {
26            "listeners": {"*:7080": {"pass": "applications/empty"}},
27            "applications": {
28                "empty": {
29                    "type": "external",
30                    "processes": {"spare": 0},
31                    "working_directory": option.test_dir + "/go/empty",
32                    "executable": option.temp_dir + "/go/app",
33                    "isolation": {"namespaces": {"credential": True}},
34                },
35            },
36        }
37
38    elif 'python' in available['modules']:
39        conf = {
40            "listeners": {"*:7080": {"pass": "applications/empty"}},
41            "applications": {
42                "empty": {
43                    "type": "python",
44                    "processes": {"spare": 0},
45                    "path": option.test_dir + "/python/empty",
46                    "working_directory": option.test_dir + "/python/empty",
47                    "module": "wsgi",
48                    "isolation": {"namespaces": {"credential": True}},
49                }
50            },
51        }
52
53    elif 'php' in available['modules']:
54        conf = {
55            "listeners": {"*:7080": {"pass": "applications/phpinfo"}},
56            "applications": {
57                "phpinfo": {
58                    "type": "php",
59                    "processes": {"spare": 0},
60                    "root": option.test_dir + "/php/phpinfo",
61                    "working_directory": option.test_dir + "/php/phpinfo",
62                    "index": "index.php",
63                    "isolation": {"namespaces": {"credential": True}},
64                }
65            },
66        }
67
68    elif 'ruby' in available['modules']:
69        TestApplicationRuby().prepare_env('empty')
70
71        conf = {
72            "listeners": {"*:7080": {"pass": "applications/empty"}},
73            "applications": {
74                "empty": {
75                    "type": "ruby",
76                    "processes": {"spare": 0},
77                    "working_directory": option.temp_dir + "/ruby/empty",
78                    "script": option.temp_dir + "/ruby/empty/config.ru",
79                    "isolation": {"namespaces": {"credential": True}},
80                }
81            },
82        }
83
84    elif 'java' in available['modules']:
85        TestApplicationJava().prepare_env('empty')
86
87        conf = {
88            "listeners": {"*:7080": {"pass": "applications/empty"}},
89            "applications": {
90                "empty": {
91                    "unit_jars": option.current_dir + "/build",
92                    "type": "java",
93                    "processes": {"spare": 0},
94                    "working_directory": option.test_dir + "/java/empty/",
95                    "webapp": option.temp_dir + "/java",
96                    "isolation": {"namespaces": {"credential": True}},
97                }
98            },
99        }
100
101    elif 'node' in available['modules']:
102        TestApplicationNode().prepare_env('basic')
103
104        conf = {
105            "listeners": {"*:7080": {"pass": "applications/basic"}},
106            "applications": {
107                "basic": {
108                    "type": "external",
109                    "processes": {"spare": 0},
110                    "working_directory": option.temp_dir + "/node",
111                    "executable": "app.js",
112                    "isolation": {"namespaces": {"credential": True}},
113                }
114            },
115        }
116
117    elif 'perl' in available['modules']:
118        conf = {
119            "listeners": {"*:7080": {"pass": "applications/body_empty"}},
120            "applications": {
121                "body_empty": {
122                    "type": "perl",
123                    "processes": {"spare": 0},
124                    "working_directory": option.test_dir + "/perl/body_empty",
125                    "script": option.test_dir + "/perl/body_empty/psgi.pl",
126                    "isolation": {"namespaces": {"credential": True}},
127                }
128            },
129        }
130
131    else:
132        return
133
134    resp = http.put(
135        url='/config',
136        sock_type='unix',
137        addr=option.temp_dir + '/control.unit.sock',
138        body=json.dumps(conf),
139    )
140
141    if 'success' not in resp['body']:
142        return
143
144    userns = getns('user')
145    if not userns:
146        return
147
148    available['features']['isolation'] = {'user': userns}
149
150    unp_clone_path = '/proc/sys/kernel/unprivileged_userns_clone'
151    if os.path.exists(unp_clone_path):
152        with open(unp_clone_path, 'r') as f:
153            if str(f.read()).rstrip() == '1':
154                available['features']['isolation'][
155                    'unprivileged_userns_clone'
156                ] = True
157
158    for ns in allns:
159        ns_value = getns(ns)
160        if ns_value:
161            available['features']['isolation'][ns] = ns_value
162