test_go_isolation.py (1635:97afbb6c5a15) test_go_isolation.py (1654:fc7d0578e124)
1import grp
2import os
3import pwd
1import grp
2import os
3import pwd
4import shutil
4
5import pytest
6
5
6import pytest
7
8from conftest import option
9from conftest import unit_run
10from conftest import unit_stop
7from unit.applications.lang.go import TestApplicationGo
8from unit.feature.isolation import TestFeatureIsolation
9
10class TestGoIsolation(TestApplicationGo):
11 prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']}
12
13 isolation = TestFeatureIsolation()
14
15 @classmethod
16 def setup_class(cls, complete_check=True):
11from unit.applications.lang.go import TestApplicationGo
12from unit.feature.isolation import TestFeatureIsolation
13
14class TestGoIsolation(TestApplicationGo):
15 prerequisites = {'modules': {'go': 'any'}, 'features': ['isolation']}
16
17 isolation = TestFeatureIsolation()
18
19 @classmethod
20 def setup_class(cls, complete_check=True):
17 unit = super().setup_class(complete_check=False)
21 check = super().setup_class(complete_check=False)
18
22
19 TestFeatureIsolation().check(cls.available, unit.temp_dir)
23 unit = unit_run()
24 option.temp_dir = unit['temp_dir']
20
25
21 return unit if not complete_check else unit.complete()
26 TestFeatureIsolation().check(option.available, unit['temp_dir'])
22
27
28 assert unit_stop() is None
29 shutil.rmtree(unit['temp_dir'])
30
31 return check if not complete_check else check()
32
23 def unpriv_creds(self):
24 nobody_uid = pwd.getpwnam('nobody').pw_uid
25
26 try:
27 nogroup_gid = grp.getgrnam('nogroup').gr_gid
28 nogroup = 'nogroup'
29 except:
30 nogroup_gid = grp.getgrnam('nobody').gr_gid
31 nogroup = 'nobody'
32
33 return (nobody_uid, nogroup_gid, nogroup)
34
35 def isolation_key(self, key):
33 def unpriv_creds(self):
34 nobody_uid = pwd.getpwnam('nobody').pw_uid
35
36 try:
37 nogroup_gid = grp.getgrnam('nogroup').gr_gid
38 nogroup = 'nogroup'
39 except:
40 nogroup_gid = grp.getgrnam('nobody').gr_gid
41 nogroup = 'nobody'
42
43 return (nobody_uid, nogroup_gid, nogroup)
44
45 def isolation_key(self, key):
36 return key in self.available['features']['isolation'].keys()
46 return key in option.available['features']['isolation'].keys()
37
38 def test_isolation_values(self):
39 self.load('ns_inspect')
40
41 obj = self.getjson()['body']
42
47
48 def test_isolation_values(self):
49 self.load('ns_inspect')
50
51 obj = self.getjson()['body']
52
43 for ns, ns_value in self.available['features']['isolation'].items():
53 for ns, ns_value in option.available['features']['isolation'].items():
44 if ns.upper() in obj['NS']:
45 assert obj['NS'][ns.upper()] == ns_value, '%s match' % ns
46
47 def test_isolation_unpriv_user(self, is_su):
48 if not self.isolation_key('unprivileged_userns_clone'):
49 pytest.skip('unprivileged clone is not available')
50
51 if is_su:

--- 141 unchanged lines hidden (view full) ---

193 self.load(
194 'ns_inspect',
195 isolation={'namespaces': {'mount': True, 'credential': True}},
196 )
197
198 obj = self.getjson()['body']
199
200 # all but user and mnt
54 if ns.upper() in obj['NS']:
55 assert obj['NS'][ns.upper()] == ns_value, '%s match' % ns
56
57 def test_isolation_unpriv_user(self, is_su):
58 if not self.isolation_key('unprivileged_userns_clone'):
59 pytest.skip('unprivileged clone is not available')
60
61 if is_su:

--- 141 unchanged lines hidden (view full) ---

203 self.load(
204 'ns_inspect',
205 isolation={'namespaces': {'mount': True, 'credential': True}},
206 )
207
208 obj = self.getjson()['body']
209
210 # all but user and mnt
201 allns = list(self.available['features']['isolation'].keys())
211 allns = list(option.available['features']['isolation'].keys())
202 allns.remove('user')
203 allns.remove('mnt')
204
205 for ns in allns:
206 if ns.upper() in obj['NS']:
207 assert (
208 obj['NS'][ns.upper()]
212 allns.remove('user')
213 allns.remove('mnt')
214
215 for ns in allns:
216 if ns.upper() in obj['NS']:
217 assert (
218 obj['NS'][ns.upper()]
209 == self.available['features']['isolation'][ns]
219 == option.available['features']['isolation'][ns]
210 ), ('%s match' % ns)
211
212 assert obj['NS']['MNT'] != self.isolation.getns('mnt'), 'mnt set'
213 assert obj['NS']['USER'] != self.isolation.getns('user'), 'user set'
214
215 def test_isolation_pid(self, is_su):
216 if not self.isolation_key('pid'):
217 pytest.skip('pid namespace is not supported')

--- 7 unchanged lines hidden (view full) ---

225 )
226
227 obj = self.getjson()['body']
228
229 assert obj['PID'] == 1, 'pid of container is 1'
230
231 def test_isolation_namespace_false(self):
232 self.load('ns_inspect')
220 ), ('%s match' % ns)
221
222 assert obj['NS']['MNT'] != self.isolation.getns('mnt'), 'mnt set'
223 assert obj['NS']['USER'] != self.isolation.getns('user'), 'user set'
224
225 def test_isolation_pid(self, is_su):
226 if not self.isolation_key('pid'):
227 pytest.skip('pid namespace is not supported')

--- 7 unchanged lines hidden (view full) ---

235 )
236
237 obj = self.getjson()['body']
238
239 assert obj['PID'] == 1, 'pid of container is 1'
240
241 def test_isolation_namespace_false(self):
242 self.load('ns_inspect')
233 allns = list(self.available['features']['isolation'].keys())
243 allns = list(option.available['features']['isolation'].keys())
234
235 remove_list = ['unprivileged_userns_clone', 'ipc', 'cgroup']
236 allns = [ns for ns in allns if ns not in remove_list]
237
238 namespaces = {}
239 for ns in allns:
240 if ns == 'user':
241 namespaces['credential'] = False

--- 9 unchanged lines hidden (view full) ---

251 self.load('ns_inspect', isolation={'namespaces': namespaces})
252
253 obj = self.getjson()['body']
254
255 for ns in allns:
256 if ns.upper() in obj['NS']:
257 assert (
258 obj['NS'][ns.upper()]
244
245 remove_list = ['unprivileged_userns_clone', 'ipc', 'cgroup']
246 allns = [ns for ns in allns if ns not in remove_list]
247
248 namespaces = {}
249 for ns in allns:
250 if ns == 'user':
251 namespaces['credential'] = False

--- 9 unchanged lines hidden (view full) ---

261 self.load('ns_inspect', isolation={'namespaces': namespaces})
262
263 obj = self.getjson()['body']
264
265 for ns in allns:
266 if ns.upper() in obj['NS']:
267 assert (
268 obj['NS'][ns.upper()]
259 == self.available['features']['isolation'][ns]
269 == option.available['features']['isolation'][ns]
260 ), ('%s match' % ns)
261
270 ), ('%s match' % ns)
271
262 def test_go_isolation_rootfs_container(self):
272 def test_go_isolation_rootfs_container(self, temp_dir):
263 if not self.isolation_key('unprivileged_userns_clone'):
264 pytest.skip('unprivileged clone is not available')
265
266 if not self.isolation_key('mnt'):
267 pytest.skip('mnt namespace is not supported')
268
269 isolation = {
270 'namespaces': {'mount': True, 'credential': True},
273 if not self.isolation_key('unprivileged_userns_clone'):
274 pytest.skip('unprivileged clone is not available')
275
276 if not self.isolation_key('mnt'):
277 pytest.skip('mnt namespace is not supported')
278
279 isolation = {
280 'namespaces': {'mount': True, 'credential': True},
271 'rootfs': self.temp_dir,
281 'rootfs': temp_dir,
272 }
273
274 self.load('ns_inspect', isolation=isolation)
275
276 obj = self.getjson(url='/?file=/go/app')['body']
277
278 assert obj['FileExists'] == True, 'app relative to rootfs'
279
280 obj = self.getjson(url='/?file=/bin/sh')['body']
281 assert obj['FileExists'] == False, 'file should not exists'
282
282 }
283
284 self.load('ns_inspect', isolation=isolation)
285
286 obj = self.getjson(url='/?file=/go/app')['body']
287
288 assert obj['FileExists'] == True, 'app relative to rootfs'
289
290 obj = self.getjson(url='/?file=/bin/sh')['body']
291 assert obj['FileExists'] == False, 'file should not exists'
292
283 def test_go_isolation_rootfs_container_priv(self, is_su):
293 def test_go_isolation_rootfs_container_priv(self, is_su, temp_dir):
284 if not is_su:
285 pytest.skip('requires root')
286
287 if not self.isolation_key('mnt'):
288 pytest.skip('mnt namespace is not supported')
289
290 isolation = {
291 'namespaces': {'mount': True},
294 if not is_su:
295 pytest.skip('requires root')
296
297 if not self.isolation_key('mnt'):
298 pytest.skip('mnt namespace is not supported')
299
300 isolation = {
301 'namespaces': {'mount': True},
292 'rootfs': self.temp_dir,
302 'rootfs': temp_dir,
293 }
294
295 self.load('ns_inspect', isolation=isolation)
296
297 obj = self.getjson(url='/?file=/go/app')['body']
298
299 assert obj['FileExists'] == True, 'app relative to rootfs'
300
301 obj = self.getjson(url='/?file=/bin/sh')['body']
302 assert obj['FileExists'] == False, 'file should not exists'
303
303 }
304
305 self.load('ns_inspect', isolation=isolation)
306
307 obj = self.getjson(url='/?file=/go/app')['body']
308
309 assert obj['FileExists'] == True, 'app relative to rootfs'
310
311 obj = self.getjson(url='/?file=/bin/sh')['body']
312 assert obj['FileExists'] == False, 'file should not exists'
313
304 def test_go_isolation_rootfs_default_tmpfs(self):
314 def test_go_isolation_rootfs_default_tmpfs(self, temp_dir):
305 if not self.isolation_key('unprivileged_userns_clone'):
306 pytest.skip('unprivileged clone is not available')
307
308 if not self.isolation_key('mnt'):
309 pytest.skip('mnt namespace is not supported')
310
311 isolation = {
312 'namespaces': {'mount': True, 'credential': True},
315 if not self.isolation_key('unprivileged_userns_clone'):
316 pytest.skip('unprivileged clone is not available')
317
318 if not self.isolation_key('mnt'):
319 pytest.skip('mnt namespace is not supported')
320
321 isolation = {
322 'namespaces': {'mount': True, 'credential': True},
313 'rootfs': self.temp_dir,
323 'rootfs': temp_dir,
314 }
315
316 self.load('ns_inspect', isolation=isolation)
317
318 obj = self.getjson(url='/?file=/tmp')['body']
319
320 assert obj['FileExists'] == True, 'app has /tmp'
324 }
325
326 self.load('ns_inspect', isolation=isolation)
327
328 obj = self.getjson(url='/?file=/tmp')['body']
329
330 assert obj['FileExists'] == True, 'app has /tmp'