xref: /unit/test/unit/check/isolation.py (revision 1848:4bd548074e2c)
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.proto import TestApplicationProto
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        conf = {
69            "listeners": {"*:7080": {"pass": "applications/empty"}},
70            "applications": {
71                "empty": {
72                    "type": "ruby",
73                    "processes": {"spare": 0},
74                    "working_directory": option.test_dir + "/ruby/empty",
75                    "script": option.test_dir + "/ruby/empty/config.ru",
76                    "isolation": {"namespaces": {"credential": True}},
77                }
78            },
79        }
80
81    elif 'java' in available['modules']:
82        TestApplicationJava().prepare_env('empty')
83
84        conf = {
85            "listeners": {"*:7080": {"pass": "applications/empty"}},
86            "applications": {
87                "empty": {
88                    "unit_jars": option.current_dir + "/build",
89                    "type": "java",
90                    "processes": {"spare": 0},
91                    "working_directory": option.test_dir + "/java/empty/",
92                    "webapp": option.temp_dir + "/java",
93                    "isolation": {"namespaces": {"credential": True}},
94                }
95            },
96        }
97
98    elif 'node' in available['modules']:
99        TestApplicationNode().prepare_env('basic')
100
101        conf = {
102            "listeners": {"*:7080": {"pass": "applications/basic"}},
103            "applications": {
104                "basic": {
105                    "type": "external",
106                    "processes": {"spare": 0},
107                    "working_directory": option.temp_dir + "/node",
108                    "executable": "app.js",
109                    "isolation": {"namespaces": {"credential": True}},
110                }
111            },
112        }
113
114    elif 'perl' in available['modules']:
115        conf = {
116            "listeners": {"*:7080": {"pass": "applications/body_empty"}},
117            "applications": {
118                "body_empty": {
119                    "type": "perl",
120                    "processes": {"spare": 0},
121                    "working_directory": option.test_dir + "/perl/body_empty",
122                    "script": option.test_dir + "/perl/body_empty/psgi.pl",
123                    "isolation": {"namespaces": {"credential": True}},
124                }
125            },
126        }
127
128    else:
129        return
130
131    resp = http.put(
132        url='/config',
133        sock_type='unix',
134        addr=option.temp_dir + '/control.unit.sock',
135        body=json.dumps(conf),
136    )
137
138    if 'success' not in resp['body']:
139        return
140
141    userns = getns('user')
142    if not userns:
143        return
144
145    available['features']['isolation'] = {'user': userns}
146
147    unp_clone_path = '/proc/sys/kernel/unprivileged_userns_clone'
148    if os.path.exists(unp_clone_path):
149        with open(unp_clone_path, 'r') as f:
150            if str(f.read()).rstrip() == '1':
151                available['features']['isolation'][
152                    'unprivileged_userns_clone'
153                ] = True
154
155    for ns in allns:
156        ns_value = getns(ns)
157        if ns_value:
158            available['features']['isolation'][ns] = ns_value
159