11654Szelenkov@nginx.comimport shutil 21654Szelenkov@nginx.com 31596Szelenkov@nginx.comimport pytest 41490St.nateldemoura@f5.com 51654Szelenkov@nginx.comfrom conftest import unit_run 61654Szelenkov@nginx.comfrom conftest import unit_stop 71490St.nateldemoura@f5.comfrom unit.applications.lang.python import TestApplicationPython 81490St.nateldemoura@f5.comfrom unit.feature.isolation import TestFeatureIsolation 9*1730Szelenkov@nginx.comfrom unit.option import option 101490St.nateldemoura@f5.com 111490St.nateldemoura@f5.com 121490St.nateldemoura@f5.comclass TestPythonIsolation(TestApplicationPython): 131490St.nateldemoura@f5.com prerequisites = {'modules': {'python': 'any'}, 'features': ['isolation']} 141490St.nateldemoura@f5.com 151490St.nateldemoura@f5.com @classmethod 161596Szelenkov@nginx.com def setup_class(cls, complete_check=True): 171654Szelenkov@nginx.com check = super().setup_class(complete_check=False) 181490St.nateldemoura@f5.com 191654Szelenkov@nginx.com unit = unit_run() 201654Szelenkov@nginx.com option.temp_dir = unit['temp_dir'] 211654Szelenkov@nginx.com 221654Szelenkov@nginx.com TestFeatureIsolation().check(option.available, unit['temp_dir']) 231490St.nateldemoura@f5.com 241654Szelenkov@nginx.com assert unit_stop() is None 251654Szelenkov@nginx.com shutil.rmtree(unit['temp_dir']) 261490St.nateldemoura@f5.com 271654Szelenkov@nginx.com return check if not complete_check else check() 281654Szelenkov@nginx.com 291654Szelenkov@nginx.com def test_python_isolation_rootfs(self, is_su, temp_dir): 301654Szelenkov@nginx.com isolation_features = option.available['features']['isolation'].keys() 311490St.nateldemoura@f5.com 321596Szelenkov@nginx.com if not is_su: 331490St.nateldemoura@f5.com if not 'unprivileged_userns_clone' in isolation_features: 341596Szelenkov@nginx.com pytest.skip('requires unprivileged userns or root') 351490St.nateldemoura@f5.com 361673St.nateldemoura@f5.com if 'user' not in isolation_features: 371673St.nateldemoura@f5.com pytest.skip('user namespace is not supported') 381673St.nateldemoura@f5.com 391673St.nateldemoura@f5.com if 'mnt' not in isolation_features: 401673St.nateldemoura@f5.com pytest.skip('mnt namespace is not supported') 411673St.nateldemoura@f5.com 421673St.nateldemoura@f5.com if 'pid' not in isolation_features: 431673St.nateldemoura@f5.com pytest.skip('pid namespace is not supported') 441490St.nateldemoura@f5.com 451673St.nateldemoura@f5.com isolation = {'rootfs': temp_dir} 461490St.nateldemoura@f5.com 471673St.nateldemoura@f5.com if not is_su: 481673St.nateldemoura@f5.com isolation['namespaces'] = { 491673St.nateldemoura@f5.com 'mount': True, 501673St.nateldemoura@f5.com 'credential': True, 511673St.nateldemoura@f5.com 'pid': True 521673St.nateldemoura@f5.com } 531490St.nateldemoura@f5.com 541490St.nateldemoura@f5.com self.load('ns_inspect', isolation=isolation) 551490St.nateldemoura@f5.com 561596Szelenkov@nginx.com assert ( 571654Szelenkov@nginx.com self.getjson(url='/?path=' + temp_dir)['body']['FileExists'] 581596Szelenkov@nginx.com == False 591596Szelenkov@nginx.com ), 'temp_dir does not exists in rootfs' 601490St.nateldemoura@f5.com 611596Szelenkov@nginx.com assert ( 621596Szelenkov@nginx.com self.getjson(url='/?path=/proc/self')['body']['FileExists'] 631673St.nateldemoura@f5.com == True 641596Szelenkov@nginx.com ), 'no /proc/self' 651490St.nateldemoura@f5.com 661596Szelenkov@nginx.com assert ( 671596Szelenkov@nginx.com self.getjson(url='/?path=/dev/pts')['body']['FileExists'] == False 681596Szelenkov@nginx.com ), 'no /dev/pts' 691596Szelenkov@nginx.com 701596Szelenkov@nginx.com assert ( 711596Szelenkov@nginx.com self.getjson(url='/?path=/sys/kernel')['body']['FileExists'] 721596Szelenkov@nginx.com == False 731596Szelenkov@nginx.com ), 'no /sys/kernel' 741490St.nateldemoura@f5.com 751490St.nateldemoura@f5.com ret = self.getjson(url='/?path=/app/python/ns_inspect') 761490St.nateldemoura@f5.com 771596Szelenkov@nginx.com assert ( 781596Szelenkov@nginx.com ret['body']['FileExists'] == True 791596Szelenkov@nginx.com ), 'application exists in rootfs' 801622St.nateldemoura@f5.com 811654Szelenkov@nginx.com def test_python_isolation_rootfs_no_language_deps(self, is_su, temp_dir): 821654Szelenkov@nginx.com isolation_features = option.available['features']['isolation'].keys() 831622St.nateldemoura@f5.com 841622St.nateldemoura@f5.com if not is_su: 851622St.nateldemoura@f5.com if not 'unprivileged_userns_clone' in isolation_features: 861622St.nateldemoura@f5.com pytest.skip('requires unprivileged userns or root') 871622St.nateldemoura@f5.com 881673St.nateldemoura@f5.com if 'user' not in isolation_features: 891673St.nateldemoura@f5.com pytest.skip('user namespace is not supported') 901673St.nateldemoura@f5.com 911673St.nateldemoura@f5.com if 'mnt' not in isolation_features: 921673St.nateldemoura@f5.com pytest.skip('mnt namespace is not supported') 931673St.nateldemoura@f5.com 941673St.nateldemoura@f5.com if 'pid' not in isolation_features: 951673St.nateldemoura@f5.com pytest.skip('pid namespace is not supported') 961673St.nateldemoura@f5.com 971622St.nateldemoura@f5.com isolation = { 981654Szelenkov@nginx.com 'rootfs': temp_dir, 991622St.nateldemoura@f5.com 'automount': {'language_deps': False} 1001622St.nateldemoura@f5.com } 1011622St.nateldemoura@f5.com 1021673St.nateldemoura@f5.com if not is_su: 1031673St.nateldemoura@f5.com isolation['namespaces'] = { 1041673St.nateldemoura@f5.com 'mount': True, 1051673St.nateldemoura@f5.com 'credential': True, 1061673St.nateldemoura@f5.com 'pid': True 1071673St.nateldemoura@f5.com } 1081673St.nateldemoura@f5.com 1091622St.nateldemoura@f5.com self.load('empty', isolation=isolation) 1101622St.nateldemoura@f5.com 1111622St.nateldemoura@f5.com assert (self.get()['status'] != 200), 'disabled language_deps' 1121622St.nateldemoura@f5.com 1131622St.nateldemoura@f5.com isolation['automount']['language_deps'] = True 1141622St.nateldemoura@f5.com 1151622St.nateldemoura@f5.com self.load('empty', isolation=isolation) 1161622St.nateldemoura@f5.com 1171622St.nateldemoura@f5.com assert (self.get()['status'] == 200), 'enabled language_deps' 118