1import pwd 2import grp 3import json 4import unittest 5from unit.applications.lang.go import TestApplicationGo 6from unit.feature.isolation import TestFeatureIsolation 7 8 9class TestGoIsolation(TestApplicationGo): 10 prerequisites = {'modules': ['go'], 'features': ['isolation']} 11 12 isolation = TestFeatureIsolation() 13 14 @classmethod 15 def setUpClass(cls, complete_check=True): 16 unit = super().setUpClass(complete_check=False) 17 18 TestFeatureIsolation().check(cls.available, unit.testdir) 19 20 return unit if not complete_check else unit.complete() 21 22 def isolation_key(self, key): 23 return key in self.available['features']['isolation'].keys() 24 25 def conf_isolation(self, isolation): 26 self.assertIn( 27 'success', 28 self.conf(isolation, 'applications/ns_inspect/isolation'), 29 'configure isolation', 30 ) 31 32 def test_isolation_values(self): 33 self.load('ns_inspect') 34 35 obj = self.getjson()['body'] 36 37 for ns, ns_value in self.available['features']['isolation'].items(): 38 if ns.upper() in obj['NS']: 39 self.assertEqual( 40 obj['NS'][ns.upper()], ns_value, '%s match' % ns 41 ) 42 43 def test_isolation_user(self): 44 if not self.isolation_key('unprivileged_userns_clone'): 45 print('unprivileged clone is not available') 46 raise unittest.SkipTest() 47 48 self.load('ns_inspect') 49 50 user_id = pwd.getpwnam('nobody').pw_uid 51 52 try: 53 group_id = grp.getgrnam('nogroup').gr_gid 54 except: 55 group_id = grp.getgrnam('nobody').gr_gid 56 57 obj = self.getjson()['body'] 58 59 self.assertTrue(obj['UID'] != 0, 'uid not zero') 60 self.assertTrue(obj['GID'] != 0, 'gid not zero') 61 62 if self.is_su: 63 self.assertEqual(obj['UID'], user_id, 'uid match') 64 self.assertEqual(obj['GID'], group_id, 'gid match') 65 else: 66 self.assertEqual(obj['UID'], self.uid, 'uid match') 67 self.assertEqual(obj['GID'], self.gid, 'gid match') 68 69 self.conf_isolation({"namespaces": {"credential": True}}) 70 71 obj = self.getjson()['body'] 72 73 # default uid and gid maps current user to nobody 74 self.assertEqual(obj['UID'], user_id, 'uid nobody') 75 self.assertEqual(obj['GID'], group_id, 'gid nobody') 76 77 self.conf_isolation( 78 { 79 "namespaces": {"credential": True}, 80 "uidmap": [ 81 {"container": user_id, "host": self.uid, "size": 1} 82 ], 83 "gidmap": [ 84 {"container": group_id, "host": self.gid, "size": 1} 85 ], 86 } 87 ) 88 89 obj = self.getjson()['body'] 90 91 self.assertEqual(obj['UID'], user_id, 'uid match') 92 self.assertEqual(obj['GID'], group_id, 'gid match') 93 94 def test_isolation_mnt(self): 95 if not self.isolation_key('mnt'): 96 print('mnt namespace is not supported') 97 raise unittest.SkipTest() 98 99 if not self.isolation_key('unprivileged_userns_clone'): 100 print('unprivileged clone is not available') 101 raise unittest.SkipTest() 102 103 self.load('ns_inspect') 104 self.conf_isolation( 105 {"namespaces": {"mount": True, "credential": True}} 106 ) 107 108 obj = self.getjson()['body'] 109 110 # all but user and mnt 111 allns = list(self.available['features']['isolation'].keys()) 112 allns.remove('user') 113 allns.remove('mnt') 114 115 for ns in allns: 116 if ns.upper() in obj['NS']: 117 self.assertEqual( 118 obj['NS'][ns.upper()], 119 self.available['features']['isolation'][ns], 120 '%s match' % ns, 121 ) 122 123 self.assertNotEqual( 124 obj['NS']['MNT'], self.isolation.getns('mnt'), 'mnt set' 125 ) 126 self.assertNotEqual( 127 obj['NS']['USER'], self.isolation.getns('user'), 'user set' 128 ) 129 130 def test_isolation_pid(self): 131 if not self.isolation_key('pid'): 132 print('pid namespace is not supported') 133 raise unittest.SkipTest() 134 135 if not self.isolation_key('unprivileged_userns_clone'): 136 print('unprivileged clone is not available') 137 raise unittest.SkipTest() 138 139 self.load('ns_inspect') 140 self.conf_isolation({"namespaces": {"pid": True, "credential": True}}) 141 142 obj = self.getjson()['body'] 143 144 self.assertEqual(obj['PID'], 1, 'pid of container is 1') 145 146 def test_isolation_namespace_false(self): 147 self.load('ns_inspect') 148 allns = list(self.available['features']['isolation'].keys()) 149 150 remove_list = ['unprivileged_userns_clone', 'ipc', 'cgroup'] 151 allns = [ns for ns in allns if ns not in remove_list] 152 153 namespaces = {} 154 for ns in allns: 155 if ns == 'user': 156 namespaces['credential'] = False 157 elif ns == 'mnt': 158 namespaces['mount'] = False 159 elif ns == 'net': 160 namespaces['network'] = False 161 elif ns == 'uts': 162 namespaces['uname'] = False 163 else: 164 namespaces[ns] = False 165 166 self.conf_isolation({"namespaces": namespaces}) 167 168 obj = self.getjson()['body'] 169 170 for ns in allns: 171 if ns.upper() in obj['NS']: 172 self.assertEqual( 173 obj['NS'][ns.upper()], 174 self.available['features']['isolation'][ns], 175 '%s match' % ns, 176 ) 177 178 179if __name__ == '__main__': 180 TestGoIsolation.main() 181