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