xref: /unit/test/test_go_isolation.py (revision 1296:77f76e7b800f)
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