blob: 6be84bade35f37198826dd447bd7e3f08d5255b8 [file] [log] [blame]
Andrew Geisslerd5838332022-05-27 11:33:10 -05001# Copyright (C) 2022 Armin Kuster <akuster808@gmail.com>
2# Copyright (C) 2022 Anton Antonov <Anton.Antonov@arm.com>
3#
4import re
5from tempfile import mkstemp
6
7from oeqa.runtime.case import OERuntimeTestCase
8from oeqa.core.decorator.depends import OETestDepends
9from oeqa.runtime.decorator.package import OEHasPackage
10from oeqa.core.decorator.data import skipIfNotFeature
11
12class ParsecTest(OERuntimeTestCase):
13 @classmethod
14 def setUpClass(cls):
15 cls.toml_file = '/etc/parsec/config.toml'
Patrick Williams92b42cb2022-09-03 06:53:57 -050016 cls.tc.target.run('cp -p %s %s-original' % (cls.toml_file, cls.toml_file))
Andrew Geissler615f2f12022-07-15 14:00:58 -050017
Andrew Geisslerd5838332022-05-27 11:33:10 -050018 def setUp(self):
19 super(ParsecTest, self).setUp()
20 if 'systemd' in self.tc.td['DISTRO_FEATURES']:
21 self.parsec_status='systemctl status -l parsec'
22 self.parsec_reload='systemctl restart parsec'
23 else:
24 self.parsec_status='pgrep -l parsec'
25 self.parsec_reload='/etc/init.d/parsec reload'
26
27 def copy_subconfig(self, cfg, provider):
28 """ Copy a provider configuration to target and append it to Parsec config """
29
30 tmp_fd, tmp_path = mkstemp()
31 with os.fdopen(tmp_fd, 'w') as f:
32 f.write('\n'.join(cfg))
33
34 (status, output) = self.target.copyTo(tmp_path, "%s-%s" % (self.toml_file, provider))
35 self.assertEqual(status, 0, msg='File could not be copied.\n%s' % output)
36 status, output = self.target.run('cat %s-%s >>%s' % (self.toml_file, provider, self.toml_file))
37 os.remove(tmp_path)
38
Patrick Williams92b42cb2022-09-03 06:53:57 -050039 def restore_parsec_config(self):
40 """ Restore original Parsec config """
41 self.target.run('cp -p %s-original %s' % (self.toml_file, self.toml_file))
42 self.target.run(self.parsec_reload)
43
Andrew Geisslerd5838332022-05-27 11:33:10 -050044 def check_parsec_providers(self, provider=None, prov_id=None):
45 """ Get Parsec providers list and check for one if defined """
46
47 status, output = self.target.run(self.parsec_status)
48 self.assertEqual(status, 0, msg='Parsec service is not running.\n%s' % output)
49
50 status, output = self.target.run('parsec-tool list-providers')
51 self.assertEqual(status, 0, msg='Cannot get a list of Parsec providers.\n%s' % output)
52 if provider and prov_id:
53 self.assertIn("ID: 0x0%d (%s provider)" % (prov_id, provider),
54 output, msg='%s provider is not configured.' % provider)
55
56 def run_cli_tests(self, prov_id=None):
57 """ Run Parsec CLI end-to-end tests against one or all providers """
58
59 status, output = self.target.run('parsec-cli-tests.sh %s' % ("-%d" % prov_id if prov_id else ""))
60 self.assertEqual(status, 0, msg='Parsec CLI tests failed.\n %s' % output)
61
Patrick Williams92b42cb2022-09-03 06:53:57 -050062 def check_packageconfig(self, prov):
63 """ Check that the require provider is included in Parsec """
64 if prov not in self.tc.td['PACKAGECONFIG:pn-parsec-service']:
65 self.skipTest('%s provider is not included in Parsec. Parsec PACKAGECONFIG: "%s"' % \
66 (prov, self.tc.td['PACKAGECONFIG:pn-parsec-service']))
67
68 def check_packages(self, prov, packages):
69 """ Check for the required packages for Parsec providers software backends """
70 if isinstance(packages, str):
71 need_pkgs = set([packages,])
72 else:
73 need_pkgs = set(packages)
74
75 if not self.tc.image_packages.issuperset(need_pkgs):
76 self.skipTest('%s provider is not configured and packages "%s" are not included into the image' % \
77 (prov, need_pkgs))
78
Andrew Geisslerd5838332022-05-27 11:33:10 -050079 @OEHasPackage(['parsec-service'])
80 @OETestDepends(['ssh.SSHTest.test_ssh'])
81 def test_all_providers(self):
82 """ Test Parsec service with all pre-defined providers """
83
84 self.check_parsec_providers()
85 self.run_cli_tests()
86
87 def configure_tpm_provider(self):
88 """ Create Parsec TPM provider configuration """
89
90 cfg = [
91 '',
92 '[[provider]]',
93 'name = "tpm-provider"',
94 'provider_type = "Tpm"',
95 'key_info_manager = "sqlite-manager"',
96 'tcti = "swtpm:port=2321"',
97 'owner_hierarchy_auth = ""',
98 ]
99 self.copy_subconfig(cfg, "TPM")
100
101 cmds = [
102 'mkdir /tmp/myvtpm',
103 'swtpm socket -d --tpmstate dir=/tmp/myvtpm --tpm2 --ctrl type=tcp,port=2322 --server type=tcp,port=2321 --flags not-need-init',
104 'tpm2_startup -c -T "swtpm:port=2321"',
Patrick Williams92b42cb2022-09-03 06:53:57 -0500105 'chown -R parsec /tmp/myvtpm',
Andrew Geisslerd5838332022-05-27 11:33:10 -0500106 self.parsec_reload,
Patrick Williams92b42cb2022-09-03 06:53:57 -0500107 'sleep 5',
Andrew Geisslerd5838332022-05-27 11:33:10 -0500108 ]
109
110 for cmd in cmds:
111 status, output = self.target.run(cmd)
112 self.assertEqual(status, 0, msg='\n'.join([cmd, output]))
113
114 @OEHasPackage(['parsec-service'])
Andrew Geisslerd5838332022-05-27 11:33:10 -0500115 @skipIfNotFeature('tpm2','Test parsec_tpm_provider requires tpm2 to be in DISTRO_FEATURES')
Patrick Williams92b42cb2022-09-03 06:53:57 -0500116 @OETestDepends(['ssh.SSHTest.test_ssh'])
Andrew Geisslerd5838332022-05-27 11:33:10 -0500117 def test_tpm_provider(self):
118 """ Configure and test Parsec TPM provider with swtpm as a backend """
119
Patrick Williams92b42cb2022-09-03 06:53:57 -0500120 self.check_packageconfig("TPM")
121
122 reconfigure = False
Andrew Geisslerd5838332022-05-27 11:33:10 -0500123 prov_id = 3
Patrick Williams92b42cb2022-09-03 06:53:57 -0500124 try:
125 # Chech if the provider is already configured
126 self.check_parsec_providers("TPM", prov_id)
127 except:
128 # Try to test the provider with a software backend
129 self.check_packages("TPM", ['swtpm', 'tpm2-tools'])
130 reconfigure = True
131 self.configure_tpm_provider()
132 self.check_parsec_providers("TPM", prov_id)
133
Andrew Geisslerd5838332022-05-27 11:33:10 -0500134 self.run_cli_tests(prov_id)
Patrick Williams92b42cb2022-09-03 06:53:57 -0500135 self.restore_parsec_config()
136
137 if reconfigure:
138 self.target.run('swtpm_ioctl -s --tcp :2322')
Andrew Geisslerd5838332022-05-27 11:33:10 -0500139
140 def configure_pkcs11_provider(self):
141 """ Create Parsec PKCS11 provider configuration """
142
143 status, output = self.target.run('softhsm2-util --init-token --free --label "Parsec Service" --pin 123456 --so-pin 123456')
144 self.assertEqual(status, 0, msg='Failed to init PKCS11 token.\n%s' % output)
145
146 slot = re.search('The token has been initialized and is reassigned to slot (\d*)', output)
147 if slot is None:
148 self.fail('Failed to get PKCS11 slot serial number.\n%s' % output)
149 self.assertNotEqual(slot.group(1), None, msg='Failed to get PKCS11 slot serial number.\n%s' % output)
150
151 cfg = [
152 '',
153 '[[provider]]',
154 'name = "pkcs11-provider"',
155 'provider_type = "Pkcs11"',
156 'key_info_manager = "sqlite-manager"',
157 'library_path = "/usr/lib/softhsm/libsofthsm2.so"',
158 'slot_number = %s' % slot.group(1),
159 'user_pin = "123456"',
160 'allow_export = true',
161 ]
162 self.copy_subconfig(cfg, "PKCS11")
163
164 status, output = self.target.run('for d in /var/lib/softhsm/tokens/*; do chown -R parsec $d; done')
165 status, output = self.target.run(self.parsec_reload)
166 self.assertEqual(status, 0, msg='Failed to reload Parsec.\n%s' % output)
167
168 @OEHasPackage(['parsec-service'])
Patrick Williams92b42cb2022-09-03 06:53:57 -0500169 @OETestDepends(['ssh.SSHTest.test_ssh'])
Andrew Geisslerd5838332022-05-27 11:33:10 -0500170 def test_pkcs11_provider(self):
171 """ Configure and test Parsec PKCS11 provider with softhsm as a backend """
172
Patrick Williams92b42cb2022-09-03 06:53:57 -0500173 self.check_packageconfig("PKCS11")
Andrew Geisslerd5838332022-05-27 11:33:10 -0500174 prov_id = 2
Patrick Williams92b42cb2022-09-03 06:53:57 -0500175 try:
176 # Chech if the provider is already configured
177 self.check_parsec_providers("PKCS #11", prov_id)
178 except:
179 # Try to test the provider with a software backend
180 self.check_packages("PKCS11", 'softhsm')
181 self.configure_pkcs11_provider()
182 self.check_parsec_providers("PKCS #11", prov_id)
183
Andrew Geisslerd5838332022-05-27 11:33:10 -0500184 self.run_cli_tests(prov_id)
Patrick Williams92b42cb2022-09-03 06:53:57 -0500185 self.restore_parsec_config()
186
187 def configure_TS_provider(self):
188 """ Create Trusted Services provider configuration """
189
190 cfg = [
191 '',
192 '[[provider]]',
193 'name = "trusted-service-provider"',
194 'provider_type = "TrustedService"',
195 'key_info_manager = "sqlite-manager"',
196 ]
197 self.copy_subconfig(cfg, "TS")
198
199 status, output = self.target.run(self.parsec_reload)
200 self.assertEqual(status, 0, msg='Failed to reload Parsec.\n%s' % output)
201
202 @OEHasPackage(['parsec-service'])
203 @OETestDepends(['ssh.SSHTest.test_ssh'])
204 def test_TS_provider(self):
205 """ Configure and test Parsec PKCS11 provider with softhsm as a backend """
206
207 self.check_packageconfig("TS")
208 prov_id = 4
209 try:
210 # Chech if the provider is already configured
211 self.check_parsec_providers("Trusted Service", prov_id)
212 except:
213 self.configure_TS_provider()
214 self.check_parsec_providers("Trusted Service", prov_id)
215
216 self.run_cli_tests(prov_id)
217 self.restore_parsec_config()