xref: /unit/test/test_go_isolation.py (revision 1307)
11293St.nateldemoura@f5.comimport pwd
21293St.nateldemoura@f5.comimport grp
31182St.nateldemoura@f5.comimport json
41182St.nateldemoura@f5.comimport unittest
51182St.nateldemoura@f5.comfrom unit.applications.lang.go import TestApplicationGo
61182St.nateldemoura@f5.comfrom unit.feature.isolation import TestFeatureIsolation
71182St.nateldemoura@f5.com
81182St.nateldemoura@f5.com
91182St.nateldemoura@f5.comclass TestGoIsolation(TestApplicationGo):
101182St.nateldemoura@f5.com    prerequisites = {'modules': ['go'], 'features': ['isolation']}
111182St.nateldemoura@f5.com
121182St.nateldemoura@f5.com    isolation = TestFeatureIsolation()
131182St.nateldemoura@f5.com
141182St.nateldemoura@f5.com    @classmethod
151182St.nateldemoura@f5.com    def setUpClass(cls, complete_check=True):
161182St.nateldemoura@f5.com        unit = super().setUpClass(complete_check=False)
171182St.nateldemoura@f5.com
181182St.nateldemoura@f5.com        TestFeatureIsolation().check(cls.available, unit.testdir)
191182St.nateldemoura@f5.com
201182St.nateldemoura@f5.com        return unit if not complete_check else unit.complete()
211182St.nateldemoura@f5.com
22*1307St.nateldemoura@f5.com    def unpriv_creds(self):
23*1307St.nateldemoura@f5.com        nobody_uid = pwd.getpwnam('nobody').pw_uid
24*1307St.nateldemoura@f5.com
25*1307St.nateldemoura@f5.com        try:
26*1307St.nateldemoura@f5.com            nogroup_gid = grp.getgrnam('nogroup').gr_gid
27*1307St.nateldemoura@f5.com            nogroup = 'nogroup'
28*1307St.nateldemoura@f5.com        except:
29*1307St.nateldemoura@f5.com            nogroup_gid = grp.getgrnam('nobody').gr_gid
30*1307St.nateldemoura@f5.com            nogroup = 'nobody'
31*1307St.nateldemoura@f5.com
32*1307St.nateldemoura@f5.com        return (nobody_uid, nogroup_gid, nogroup)
33*1307St.nateldemoura@f5.com
341182St.nateldemoura@f5.com    def isolation_key(self, key):
351182St.nateldemoura@f5.com        return key in self.available['features']['isolation'].keys()
361182St.nateldemoura@f5.com
371182St.nateldemoura@f5.com    def test_isolation_values(self):
381182St.nateldemoura@f5.com        self.load('ns_inspect')
391182St.nateldemoura@f5.com
401296St.nateldemoura@f5.com        obj = self.getjson()['body']
411182St.nateldemoura@f5.com
421182St.nateldemoura@f5.com        for ns, ns_value in self.available['features']['isolation'].items():
431182St.nateldemoura@f5.com            if ns.upper() in obj['NS']:
441182St.nateldemoura@f5.com                self.assertEqual(
451182St.nateldemoura@f5.com                    obj['NS'][ns.upper()], ns_value, '%s match' % ns
461182St.nateldemoura@f5.com                )
471182St.nateldemoura@f5.com
48*1307St.nateldemoura@f5.com    def test_isolation_unpriv_user(self):
491182St.nateldemoura@f5.com        if not self.isolation_key('unprivileged_userns_clone'):
501182St.nateldemoura@f5.com            print('unprivileged clone is not available')
511182St.nateldemoura@f5.com            raise unittest.SkipTest()
521182St.nateldemoura@f5.com
53*1307St.nateldemoura@f5.com        if self.is_su:
54*1307St.nateldemoura@f5.com            print('privileged tests, skip this')
55*1307St.nateldemoura@f5.com            raise unittest.SkipTest()
56*1307St.nateldemoura@f5.com
57*1307St.nateldemoura@f5.com        self.load('ns_inspect')
58*1307St.nateldemoura@f5.com        obj = self.getjson()['body']
59*1307St.nateldemoura@f5.com
60*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], self.uid, 'uid match')
61*1307St.nateldemoura@f5.com        self.assertEqual(obj['GID'], self.gid, 'gid match')
62*1307St.nateldemoura@f5.com
63*1307St.nateldemoura@f5.com        self.load('ns_inspect', isolation={'namespaces': {'credential': True}})
64*1307St.nateldemoura@f5.com
65*1307St.nateldemoura@f5.com        obj = self.getjson()['body']
66*1307St.nateldemoura@f5.com
67*1307St.nateldemoura@f5.com        nobody_uid, nogroup_gid, nogroup = self.unpriv_creds()
68*1307St.nateldemoura@f5.com
69*1307St.nateldemoura@f5.com        # unprivileged unit map itself to nobody in the container by default
70*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], nobody_uid, 'uid of nobody')
71*1307St.nateldemoura@f5.com        self.assertEqual(obj['GID'], nogroup_gid, 'gid of %s' % nogroup)
72*1307St.nateldemoura@f5.com
73*1307St.nateldemoura@f5.com        self.load(
74*1307St.nateldemoura@f5.com            'ns_inspect',
75*1307St.nateldemoura@f5.com            user='root',
76*1307St.nateldemoura@f5.com            isolation={'namespaces': {'credential': True}},
77*1307St.nateldemoura@f5.com        )
78*1307St.nateldemoura@f5.com
79*1307St.nateldemoura@f5.com        obj = self.getjson()['body']
80*1307St.nateldemoura@f5.com
81*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], 0, 'uid match user=root')
82*1307St.nateldemoura@f5.com        self.assertEqual(obj['GID'], 0, 'gid match user=root')
83*1307St.nateldemoura@f5.com
84*1307St.nateldemoura@f5.com        self.load(
85*1307St.nateldemoura@f5.com            'ns_inspect',
86*1307St.nateldemoura@f5.com            user='root',
87*1307St.nateldemoura@f5.com            group=nogroup,
88*1307St.nateldemoura@f5.com            isolation={'namespaces': {'credential': True}},
89*1307St.nateldemoura@f5.com        )
90*1307St.nateldemoura@f5.com
91*1307St.nateldemoura@f5.com        obj = self.getjson()['body']
92*1307St.nateldemoura@f5.com
93*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], 0, 'uid match user=root group=nogroup')
94*1307St.nateldemoura@f5.com        self.assertEqual(
95*1307St.nateldemoura@f5.com            obj['GID'], nogroup_gid, 'gid match user=root group=nogroup'
96*1307St.nateldemoura@f5.com        )
97*1307St.nateldemoura@f5.com
98*1307St.nateldemoura@f5.com        self.load(
99*1307St.nateldemoura@f5.com            'ns_inspect',
100*1307St.nateldemoura@f5.com            user='root',
101*1307St.nateldemoura@f5.com            group='root',
102*1307St.nateldemoura@f5.com            isolation={
103*1307St.nateldemoura@f5.com                'namespaces': {'credential': True},
104*1307St.nateldemoura@f5.com                'uidmap': [{'container': 0, 'host': self.uid, 'size': 1}],
105*1307St.nateldemoura@f5.com                'gidmap': [{'container': 0, 'host': self.gid, 'size': 1}],
106*1307St.nateldemoura@f5.com            },
107*1307St.nateldemoura@f5.com        )
108*1307St.nateldemoura@f5.com
109*1307St.nateldemoura@f5.com        obj = self.getjson()['body']
110*1307St.nateldemoura@f5.com
111*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], 0, 'uid match uidmap')
112*1307St.nateldemoura@f5.com        self.assertEqual(obj['GID'], 0, 'gid match gidmap')
113*1307St.nateldemoura@f5.com
114*1307St.nateldemoura@f5.com    def test_isolation_priv_user(self):
115*1307St.nateldemoura@f5.com        if not self.is_su:
116*1307St.nateldemoura@f5.com            print('unprivileged tests, skip this')
117*1307St.nateldemoura@f5.com            raise unittest.SkipTest()
118*1307St.nateldemoura@f5.com
1191182St.nateldemoura@f5.com        self.load('ns_inspect')
1201293St.nateldemoura@f5.com
121*1307St.nateldemoura@f5.com        nobody_uid, nogroup_gid, nogroup = self.unpriv_creds()
122*1307St.nateldemoura@f5.com
123*1307St.nateldemoura@f5.com        obj = self.getjson()['body']
1241293St.nateldemoura@f5.com
125*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], nobody_uid, 'uid match')
126*1307St.nateldemoura@f5.com        self.assertEqual(obj['GID'], nogroup_gid, 'gid match')
127*1307St.nateldemoura@f5.com
128*1307St.nateldemoura@f5.com        self.load('ns_inspect', isolation={'namespaces': {'credential': True}})
1291293St.nateldemoura@f5.com
1301296St.nateldemoura@f5.com        obj = self.getjson()['body']
1311182St.nateldemoura@f5.com
132*1307St.nateldemoura@f5.com        # privileged unit map app creds in the container by default
133*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], nobody_uid, 'uid nobody')
134*1307St.nateldemoura@f5.com        self.assertEqual(obj['GID'], nogroup_gid, 'gid nobody')
1351293St.nateldemoura@f5.com
136*1307St.nateldemoura@f5.com        self.load(
137*1307St.nateldemoura@f5.com            'ns_inspect',
138*1307St.nateldemoura@f5.com            user='root',
139*1307St.nateldemoura@f5.com            isolation={'namespaces': {'credential': True}},
140*1307St.nateldemoura@f5.com        )
1411182St.nateldemoura@f5.com
1421296St.nateldemoura@f5.com        obj = self.getjson()['body']
1431182St.nateldemoura@f5.com
144*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], 0, 'uid nobody user=root')
145*1307St.nateldemoura@f5.com        self.assertEqual(obj['GID'], 0, 'gid nobody user=root')
1461182St.nateldemoura@f5.com
147*1307St.nateldemoura@f5.com        self.load(
148*1307St.nateldemoura@f5.com            'ns_inspect',
149*1307St.nateldemoura@f5.com            user='root',
150*1307St.nateldemoura@f5.com            group=nogroup,
151*1307St.nateldemoura@f5.com            isolation={'namespaces': {'credential': True}},
1521182St.nateldemoura@f5.com        )
1531182St.nateldemoura@f5.com
1541296St.nateldemoura@f5.com        obj = self.getjson()['body']
1551182St.nateldemoura@f5.com
156*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], 0, 'uid match user=root group=nogroup')
157*1307St.nateldemoura@f5.com        self.assertEqual(
158*1307St.nateldemoura@f5.com            obj['GID'], nogroup_gid, 'gid match user=root group=nogroup'
159*1307St.nateldemoura@f5.com        )
160*1307St.nateldemoura@f5.com
161*1307St.nateldemoura@f5.com        self.load(
162*1307St.nateldemoura@f5.com            'ns_inspect',
163*1307St.nateldemoura@f5.com            user='root',
164*1307St.nateldemoura@f5.com            group='root',
165*1307St.nateldemoura@f5.com            isolation={
166*1307St.nateldemoura@f5.com                'namespaces': {'credential': True},
167*1307St.nateldemoura@f5.com                'uidmap': [{'container': 0, 'host': 0, 'size': 1}],
168*1307St.nateldemoura@f5.com                'gidmap': [{'container': 0, 'host': 0, 'size': 1}],
169*1307St.nateldemoura@f5.com            },
170*1307St.nateldemoura@f5.com        )
171*1307St.nateldemoura@f5.com
172*1307St.nateldemoura@f5.com        obj = self.getjson()['body']
173*1307St.nateldemoura@f5.com
174*1307St.nateldemoura@f5.com        self.assertEqual(obj['UID'], 0, 'uid match uidmap user=root')
175*1307St.nateldemoura@f5.com        self.assertEqual(obj['GID'], 0, 'gid match gidmap user=root')
176*1307St.nateldemoura@f5.com
177*1307St.nateldemoura@f5.com        # map 65535 uids
178*1307St.nateldemoura@f5.com        self.load(
179*1307St.nateldemoura@f5.com            'ns_inspect',
180*1307St.nateldemoura@f5.com            user='nobody',
181*1307St.nateldemoura@f5.com            isolation={
182*1307St.nateldemoura@f5.com                'namespaces': {'credential': True},
183*1307St.nateldemoura@f5.com                'uidmap': [
184*1307St.nateldemoura@f5.com                    {'container': 0, 'host': 0, 'size': nobody_uid + 1}
185*1307St.nateldemoura@f5.com                ],
186*1307St.nateldemoura@f5.com            },
187*1307St.nateldemoura@f5.com        )
188*1307St.nateldemoura@f5.com
189*1307St.nateldemoura@f5.com        obj = self.getjson()['body']
190*1307St.nateldemoura@f5.com
191*1307St.nateldemoura@f5.com        self.assertEqual(
192*1307St.nateldemoura@f5.com            obj['UID'], nobody_uid, 'uid match uidmap user=nobody'
193*1307St.nateldemoura@f5.com        )
194*1307St.nateldemoura@f5.com        self.assertEqual(
195*1307St.nateldemoura@f5.com            obj['GID'], nogroup_gid, 'gid match uidmap user=nobody'
196*1307St.nateldemoura@f5.com        )
1971182St.nateldemoura@f5.com
1981182St.nateldemoura@f5.com    def test_isolation_mnt(self):
1991182St.nateldemoura@f5.com        if not self.isolation_key('mnt'):
2001182St.nateldemoura@f5.com            print('mnt namespace is not supported')
2011182St.nateldemoura@f5.com            raise unittest.SkipTest()
2021182St.nateldemoura@f5.com
2031182St.nateldemoura@f5.com        if not self.isolation_key('unprivileged_userns_clone'):
2041182St.nateldemoura@f5.com            print('unprivileged clone is not available')
2051182St.nateldemoura@f5.com            raise unittest.SkipTest()
2061182St.nateldemoura@f5.com
207*1307St.nateldemoura@f5.com        self.load(
208*1307St.nateldemoura@f5.com            'ns_inspect',
209*1307St.nateldemoura@f5.com            isolation={'namespaces': {'mount': True, 'credential': True}},
2101182St.nateldemoura@f5.com        )
2111182St.nateldemoura@f5.com
2121296St.nateldemoura@f5.com        obj = self.getjson()['body']
2131182St.nateldemoura@f5.com
2141182St.nateldemoura@f5.com        # all but user and mnt
2151182St.nateldemoura@f5.com        allns = list(self.available['features']['isolation'].keys())
2161182St.nateldemoura@f5.com        allns.remove('user')
2171182St.nateldemoura@f5.com        allns.remove('mnt')
2181182St.nateldemoura@f5.com
2191182St.nateldemoura@f5.com        for ns in allns:
2201182St.nateldemoura@f5.com            if ns.upper() in obj['NS']:
2211182St.nateldemoura@f5.com                self.assertEqual(
2221182St.nateldemoura@f5.com                    obj['NS'][ns.upper()],
2231182St.nateldemoura@f5.com                    self.available['features']['isolation'][ns],
2241182St.nateldemoura@f5.com                    '%s match' % ns,
2251182St.nateldemoura@f5.com                )
2261182St.nateldemoura@f5.com
2271182St.nateldemoura@f5.com        self.assertNotEqual(
2281182St.nateldemoura@f5.com            obj['NS']['MNT'], self.isolation.getns('mnt'), 'mnt set'
2291182St.nateldemoura@f5.com        )
2301182St.nateldemoura@f5.com        self.assertNotEqual(
2311182St.nateldemoura@f5.com            obj['NS']['USER'], self.isolation.getns('user'), 'user set'
2321182St.nateldemoura@f5.com        )
2331182St.nateldemoura@f5.com
2341182St.nateldemoura@f5.com    def test_isolation_pid(self):
2351182St.nateldemoura@f5.com        if not self.isolation_key('pid'):
2361182St.nateldemoura@f5.com            print('pid namespace is not supported')
2371182St.nateldemoura@f5.com            raise unittest.SkipTest()
2381182St.nateldemoura@f5.com
239*1307St.nateldemoura@f5.com        if not (self.is_su or self.isolation_key('unprivileged_userns_clone')):
240*1307St.nateldemoura@f5.com            print('requires root or unprivileged_userns_clone')
2411182St.nateldemoura@f5.com            raise unittest.SkipTest()
2421182St.nateldemoura@f5.com
243*1307St.nateldemoura@f5.com        self.load(
244*1307St.nateldemoura@f5.com            'ns_inspect',
245*1307St.nateldemoura@f5.com            isolation={'namespaces': {'pid': True, 'credential': True}},
246*1307St.nateldemoura@f5.com        )
2471182St.nateldemoura@f5.com
2481296St.nateldemoura@f5.com        obj = self.getjson()['body']
2491182St.nateldemoura@f5.com
2501182St.nateldemoura@f5.com        self.assertEqual(obj['PID'], 1, 'pid of container is 1')
2511182St.nateldemoura@f5.com
2521236St.nateldemoura@f5.com    def test_isolation_namespace_false(self):
2531236St.nateldemoura@f5.com        self.load('ns_inspect')
2541236St.nateldemoura@f5.com        allns = list(self.available['features']['isolation'].keys())
2551236St.nateldemoura@f5.com
2561236St.nateldemoura@f5.com        remove_list = ['unprivileged_userns_clone', 'ipc', 'cgroup']
2571236St.nateldemoura@f5.com        allns = [ns for ns in allns if ns not in remove_list]
2581236St.nateldemoura@f5.com
2591236St.nateldemoura@f5.com        namespaces = {}
2601236St.nateldemoura@f5.com        for ns in allns:
2611236St.nateldemoura@f5.com            if ns == 'user':
2621236St.nateldemoura@f5.com                namespaces['credential'] = False
2631236St.nateldemoura@f5.com            elif ns == 'mnt':
2641236St.nateldemoura@f5.com                namespaces['mount'] = False
2651236St.nateldemoura@f5.com            elif ns == 'net':
2661236St.nateldemoura@f5.com                namespaces['network'] = False
2671236St.nateldemoura@f5.com            elif ns == 'uts':
2681236St.nateldemoura@f5.com                namespaces['uname'] = False
2691236St.nateldemoura@f5.com            else:
2701236St.nateldemoura@f5.com                namespaces[ns] = False
2711236St.nateldemoura@f5.com
272*1307St.nateldemoura@f5.com        self.load('ns_inspect', isolation={'namespaces': namespaces})
2731236St.nateldemoura@f5.com
2741296St.nateldemoura@f5.com        obj = self.getjson()['body']
2751236St.nateldemoura@f5.com
2761236St.nateldemoura@f5.com        for ns in allns:
2771236St.nateldemoura@f5.com            if ns.upper() in obj['NS']:
2781236St.nateldemoura@f5.com                self.assertEqual(
2791236St.nateldemoura@f5.com                    obj['NS'][ns.upper()],
2801236St.nateldemoura@f5.com                    self.available['features']['isolation'][ns],
2811236St.nateldemoura@f5.com                    '%s match' % ns,
2821236St.nateldemoura@f5.com                )
2831236St.nateldemoura@f5.com
2841182St.nateldemoura@f5.com
2851182St.nateldemoura@f5.comif __name__ == '__main__':
2861182St.nateldemoura@f5.com    TestGoIsolation.main()
287