Integrate parts of meta-intel-iot-security
[AGL/meta-agl.git] / meta-security / lib / oeqa / runtime / securitymanager.py
1 import unittest
2 import re
3 import os
4 import string
5 from oeqa.oetest import oeRuntimeTest, skipModule
6 from oeqa.utils.decorators import *
7
8 def get_files_dir():
9     """Get directory of supporting files"""
10     pkgarch = oeRuntimeTest.tc.d.getVar('MACHINE', True)
11     deploydir = oeRuntimeTest.tc.d.getVar('DEPLOY_DIR', True)
12     return os.path.join(deploydir, "files", "target", pkgarch)
13
14 MAX_LABEL_LEN = 255
15 LABEL = "a" * MAX_LABEL_LEN
16
17 def setUpModule():
18     if not oeRuntimeTest.hasPackage('security-manager'):
19         skipModule(
20             "security-manager module skipped: "
21             "target doesn't have security-manager installed")
22
23 class SecurityManagerBasicTest(oeRuntimeTest):
24     ''' base smack test '''
25     def setUp(self):
26         # TODO: avoid hardcoding path (also in SecurityManager itself)
27         self.security_manager_db = '/usr/dbspace/.security-manager.db'
28         cmd = "sqlite3 %s 'SELECT name from privilege ORDER BY privilege_id'" % self.security_manager_db
29         status, output = self.target.run(cmd)
30         self.assertFalse(status, msg="%s failed: %s" % (cmd, output))
31         self.privileges = output.split()
32         if not self.privileges:
33             # Only privileges that map to a Unix group need to be known to
34             # SecurityManager. Therefore it is possible that the query above
35             # returns nothing. In that case, make up something for the tests.
36             self.privileges.append('FoobarPrivilege')
37         self.appid = 'test-app-id'
38         self.pkgid = 'test-pkg-id'
39         self.user = 'security-manager-user'
40         idcmd = 'id -u %s' % self.user
41         status, output = self.target.run(idcmd)
42         if status:
43             # -D is from busybox. It disables setting a password.
44             createcmd = 'adduser -D %s' % self.user
45             status, output = self.target.run(createcmd)
46             self.assertFalse(status, msg="%s failed: %s" % (createcmd, output))
47             status, output = self.target.run(idcmd)
48         self.assertTrue(output.isdigit(), msg="Unexpected output from %s: %s" % (idcmd, output))
49         self.uid = output
50
51 class SecurityManagerApp(SecurityManagerBasicTest):
52     '''Tests covering app installation. Ordering is important, therefore tests are numbered.'''
53
54     @skipUnlessPassed('test_ssh')
55     def test_security_manager_01_setup(self):
56         '''Check that basic SecurityManager setup is in place.'''
57         # If we get this far, then at least the sqlite db must have been in place.
58         # This does not mean much, but we need to start somewhere.
59         pass
60
61     @skipUnlessPassed('test_security_manager_01_setup')
62     def test_security_manager_02_install(self):
63         '''Test if installing an app sets up privilege rules for it, also in Cynara.'''
64         self.target.copy_to(os.path.join(get_files_dir(), "app-runas"), "/tmp/")
65         cmd = '/tmp/app-runas -a %s -p %s -u %s -r %s -i' % \
66               (self.appid, self.pkgid, self.uid, self.privileges[0])
67         status, output = self.target.run(cmd)
68         self.assertFalse(status, msg="%s failed: %s" % (cmd, output))
69         cmd = '''sqlite3 %s 'SELECT uid,app_name,pkg_name from app_pkg_view WHERE app_name = "%s"' ''' % \
70               (self.security_manager_db, self.appid)
71         status, output = self.target.run(cmd)
72         self.assertFalse(status, msg="%s failed: %s" % (cmd, output))
73         self.assertEqual(output, '|'.join((self.uid, self.appid, self.pkgid)))
74         cmd = 'grep -r %s /var/cynara/db/' % self.appid
75         status, output = self.target.run(cmd)
76         self.assertFalse(status, msg="%s failed: %s" % (cmd, output))
77         # User::App:: prefix still hard-coded here because it is not customizable at the moment.
78         self.assertEqual(output, '/var/cynara/db/_MANIFESTS:User::App::%s;%s;%s;0xFFFF;' % \
79                          (self.appid, self.uid, self.privileges[0]))
80
81     @skipUnlessPassed('test_security_manager_02_install')
82     def test_security_manager_03_run(self):
83         '''Test running as app. Depends on preparations in test_security_manager_install().'''
84         cmd = '''/tmp/app-runas -a %s -u %s -e -- sh -c 'id -u && cat /proc/self/attr/current' ''' % \
85               (self.appid, self.uid)
86         status, output = self.target.run(cmd)
87         self.assertFalse(status, msg="%s failed: %s" % (cmd, output))
88         self.assertEqual(output, '%s\nUser::App::%s' % (self.uid, self.appid))
89
90     @skipUnlessPassed('test_security_manager_02_install')
91     def test_security_manager_03_uninstall(self):
92         '''Test removal of an app.'''
93         cmd = '/tmp/app-runas -a %s -p %s -u %s -d' % \
94               (self.appid, self.pkgid, self.uid)
95         status, output = self.target.run(cmd)
96         self.assertFalse(status, msg="%s failed: %s" % (cmd, output))
97         cmd = '''sqlite3 %s 'SELECT uid,app_name,pkg_name from app_pkg_view WHERE app_name = "%s"' ''' % \
98               (self.security_manager_db, self.appid)
99         status, output = self.target.run(cmd)
100         self.assertFalse(status, msg="%s failed: %s" % (cmd, output))
101         # Entry does not really get removed. Bug filed here:
102         # https://github.com/Samsung/security-manager/issues/2
103         # self.assertEqual(output, '')
104         cmd = 'grep -r %s /var/cynara/db/' % self.appid
105         status, output = self.target.run(cmd)
106         self.assertFalse(status, msg="%s failed: %s" % (cmd, output))
107         # This also does not get removed. Perhaps same root cause.
108         # self.assertEqual(output, '')