Merge lp:~apw/launchpad/uefi-auto-key into lp:launchpad

Proposed by Andy Whitcroft
Status: Merged
Approved by: Colin Watson
Approved revision: no longer in the source branch.
Merged at revision: 18015
Proposed branch: lp:~apw/launchpad/uefi-auto-key
Merge into: lp:launchpad
Diff against target: 443 lines (+221/-50)
4 files modified
lib/lp/archivepublisher/config.py (+3/-0)
lib/lp/archivepublisher/tests/test_config.py (+5/-0)
lib/lp/archivepublisher/tests/test_uefi.py (+141/-27)
lib/lp/archivepublisher/uefi.py (+72/-23)
To merge this branch: bzr merge lp:~apw/launchpad/uefi-auto-key
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Andy Whitcroft (community) Abstain
Review via email: mp+293087@code.launchpad.net

Commit message

Move the existing raw-uefi custom upload to validating the uefi signing keys on first use. For PPAs generate the keys on first use if they are missing.

Description of the change

Update the uefi custom upload to optionally manage key generation. Also in preparation for signing generification move key validation/generation to first use.

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
review: Needs Fixing
Revision history for this message
Andy Whitcroft (apw) wrote :

I have pushed up a number of updates on top of the previous code. I believe this should reflect your review comments. In particular I have revamps the testing to split command generation checks from flow testing. Oh and the lint roller has been applied.

review: Needs Resubmitting
Revision history for this message
Andy Whitcroft (apw) :
review: Abstain
Revision history for this message
Colin Watson (cjwatson) wrote :

Definitely getting there, but still some things to fix, mostly in the tests.

review: Needs Fixing
Revision history for this message
Andy Whitcroft (apw) wrote :

Ok. I pushed up another attempt. I hope this one covers your remaining review comments. As expected the majority of the diff is in the tests. Looking at the diff against mainline there is actually very little delta for the operational code (also as expected).

Revision history for this message
Colin Watson (cjwatson) wrote :

Looks good now!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/archivepublisher/config.py'
--- lib/lp/archivepublisher/config.py 2016-02-05 16:51:12 +0000
+++ lib/lp/archivepublisher/config.py 2016-05-03 11:13:13 +0000
@@ -79,12 +79,15 @@
7979
80 if archive.is_main:80 if archive.is_main:
81 pubconf.uefiroot = pubconf.archiveroot + '-uefi'81 pubconf.uefiroot = pubconf.archiveroot + '-uefi'
82 pubconf.uefiautokey = False
82 elif archive.is_ppa:83 elif archive.is_ppa:
83 pubconf.uefiroot = os.path.join(84 pubconf.uefiroot = os.path.join(
84 ppa_config.signing_keys_root, "uefi",85 ppa_config.signing_keys_root, "uefi",
85 archive.owner.name, archive.name)86 archive.owner.name, archive.name)
87 pubconf.uefiautokey = True
86 else:88 else:
87 pubconf.uefiroot = None89 pubconf.uefiroot = None
90 pubconf.uefiautokey = False
8891
89 pubconf.poolroot = os.path.join(pubconf.archiveroot, 'pool')92 pubconf.poolroot = os.path.join(pubconf.archiveroot, 'pool')
90 pubconf.distsroot = os.path.join(pubconf.archiveroot, 'dists')93 pubconf.distsroot = os.path.join(pubconf.archiveroot, 'dists')
9194
=== modified file 'lib/lp/archivepublisher/tests/test_config.py'
--- lib/lp/archivepublisher/tests/test_config.py 2016-01-13 17:09:34 +0000
+++ lib/lp/archivepublisher/tests/test_config.py 2016-05-03 11:13:13 +0000
@@ -47,6 +47,7 @@
47 self.assertEqual(47 self.assertEqual(
48 self.root + "/ubuntutest-temp", primary_config.temproot)48 self.root + "/ubuntutest-temp", primary_config.temproot)
49 self.assertEqual(archiveroot + "-uefi", primary_config.uefiroot)49 self.assertEqual(archiveroot + "-uefi", primary_config.uefiroot)
50 self.assertFalse(primary_config.uefiautokey)
50 self.assertIs(None, primary_config.metaroot)51 self.assertIs(None, primary_config.metaroot)
51 self.assertEqual(archiveroot + "-staging", primary_config.stagingroot)52 self.assertEqual(archiveroot + "-staging", primary_config.stagingroot)
5253
@@ -70,6 +71,7 @@
70 self.assertEqual(71 self.assertEqual(
71 self.root + "/ubuntutest-temp", partner_config.temproot)72 self.root + "/ubuntutest-temp", partner_config.temproot)
72 self.assertEqual(archiveroot + "-uefi", partner_config.uefiroot)73 self.assertEqual(archiveroot + "-uefi", partner_config.uefiroot)
74 self.assertFalse(partner_config.uefiautokey)
73 self.assertIs(None, partner_config.metaroot)75 self.assertIs(None, partner_config.metaroot)
74 self.assertEqual(archiveroot + "-staging", partner_config.stagingroot)76 self.assertEqual(archiveroot + "-staging", partner_config.stagingroot)
7577
@@ -92,6 +94,7 @@
92 self.assertEqual(archiveroot + "-misc", copy_config.miscroot)94 self.assertEqual(archiveroot + "-misc", copy_config.miscroot)
93 self.assertEqual(archiveroot + "-temp", copy_config.temproot)95 self.assertEqual(archiveroot + "-temp", copy_config.temproot)
94 self.assertIsNone(copy_config.uefiroot)96 self.assertIsNone(copy_config.uefiroot)
97 self.assertFalse(copy_config.uefiautokey)
95 self.assertIs(None, copy_config.metaroot)98 self.assertIs(None, copy_config.metaroot)
96 self.assertIs(None, copy_config.stagingroot)99 self.assertIs(None, copy_config.stagingroot)
97100
@@ -131,6 +134,7 @@
131 uefiroot = "/var/tmp/ppa-signing-keys.test/uefi/%s/%s" % (134 uefiroot = "/var/tmp/ppa-signing-keys.test/uefi/%s/%s" % (
132 self.ppa.owner.name, self.ppa.name)135 self.ppa.owner.name, self.ppa.name)
133 self.assertEqual(uefiroot, self.ppa_config.uefiroot)136 self.assertEqual(uefiroot, self.ppa_config.uefiroot)
137 self.assertTrue(self.ppa_config.uefiautokey)
134 self.assertIs(None, self.ppa_config.metaroot)138 self.assertIs(None, self.ppa_config.metaroot)
135 self.assertIs(None, self.ppa_config.stagingroot)139 self.assertIs(None, self.ppa_config.stagingroot)
136140
@@ -165,6 +169,7 @@
165 uefiroot = "/var/tmp/ppa-signing-keys.test/uefi/%s/%s" % (169 uefiroot = "/var/tmp/ppa-signing-keys.test/uefi/%s/%s" % (
166 p3a.owner.name, p3a.name)170 p3a.owner.name, p3a.name)
167 self.assertEqual(uefiroot, p3a_config.uefiroot)171 self.assertEqual(uefiroot, p3a_config.uefiroot)
172 self.assertTrue(self.ppa_config.uefiautokey)
168 self.assertIs(None, p3a_config.metaroot)173 self.assertIs(None, p3a_config.metaroot)
169 self.assertIs(None, p3a_config.stagingroot)174 self.assertIs(None, p3a_config.stagingroot)
170175
171176
=== modified file 'lib/lp/archivepublisher/tests/test_uefi.py'
--- lib/lp/archivepublisher/tests/test_uefi.py 2016-02-05 16:51:12 +0000
+++ lib/lp/archivepublisher/tests/test_uefi.py 2016-05-03 11:13:13 +0000
@@ -7,6 +7,8 @@
77
8import os8import os
99
10from fixtures import MonkeyPatch
11
10from lp.archivepublisher.customupload import (12from lp.archivepublisher.customupload import (
11 CustomUploadAlreadyExists,13 CustomUploadAlreadyExists,
12 CustomUploadBadUmask,14 CustomUploadBadUmask,
@@ -18,11 +20,35 @@
18from lp.testing.fakemethod import FakeMethod20from lp.testing.fakemethod import FakeMethod
1921
2022
23class FakeMethodGenUefiKeys(FakeMethod):
24 """Fake execution of generation of Uefi keys pairs."""
25 def __init__(self, upload=None, *args, **kwargs):
26 super(FakeMethodGenUefiKeys, self).__init__(*args, **kwargs)
27 self.upload = upload
28
29 def __call__(self, *args, **kwargs):
30 super(FakeMethodGenUefiKeys, self).__call__(*args, **kwargs)
31
32 write_file(self.upload.key, "")
33 write_file(self.upload.cert, "")
34
35
21class FakeConfig:36class FakeConfig:
22 """A fake publisher configuration."""37 """A fake publisher configuration for the main archive."""
23 def __init__(self, archiveroot, uefiroot):38 def __init__(self, distroroot, uefiroot):
24 self.archiveroot = archiveroot39 self.distroroot = distroroot
25 self.uefiroot = uefiroot40 self.uefiroot = uefiroot
41 self.archiveroot = os.path.join(self.distroroot, 'ubuntu')
42 self.uefiautokey = False
43
44
45class FakeConfigPPA:
46 """A fake publisher configuration for a PPA."""
47 def __init__(self, distroroot, uefiroot, owner, ppa):
48 self.distroroot = distroroot
49 self.uefiroot = uefiroot
50 self.archiveroot = os.path.join(self.distroroot, owner, ppa, 'ubuntu')
51 self.uefiautokey = True
2652
2753
28class TestUefi(TestCase):54class TestUefi(TestCase):
@@ -37,11 +63,17 @@
37 old_umask = os.umask(0o022)63 old_umask = os.umask(0o022)
38 self.addCleanup(os.umask, old_umask)64 self.addCleanup(os.umask, old_umask)
3965
40 def setUpKeyAndCert(self):66 def setUpPPA(self):
67 self.pubconf = FakeConfigPPA(self.temp_dir, self.uefi_dir,
68 'ubuntu-archive', 'testing')
69 self.testcase_cn = '/CN=PPA ubuntu-archive testing/'
70
71 def setUpKeyAndCert(self, create=True):
41 self.key = os.path.join(self.uefi_dir, "uefi.key")72 self.key = os.path.join(self.uefi_dir, "uefi.key")
42 self.cert = os.path.join(self.uefi_dir, "uefi.crt")73 self.cert = os.path.join(self.uefi_dir, "uefi.crt")
43 write_file(self.key, "")74 if create:
44 write_file(self.cert, "")75 write_file(self.key, "")
76 write_file(self.cert, "")
4577
46 def openArchive(self, loader_type, version, arch):78 def openArchive(self, loader_type, version, arch):
47 self.path = os.path.join(79 self.path = os.path.join(
@@ -52,41 +84,48 @@
52 def process(self):84 def process(self):
53 self.archive.close()85 self.archive.close()
54 self.buffer.close()86 self.buffer.close()
87 fake_call = FakeMethod()
55 upload = UefiUpload()88 upload = UefiUpload()
56 upload.sign = FakeMethod()89 upload.signUefi = FakeMethod()
57 upload.process(self.pubconf, self.path, self.suite)90 with self.useFixture(MonkeyPatch("subprocess.call", fake_call)):
91 upload.process(self.pubconf, self.path, self.suite)
92 # Under no circumstances is it safe to execute actual commands.
93 self.assertEqual(0, fake_call.call_count)
94
58 return upload95 return upload
5996
60 def getUefiPath(self, loader_type, arch):97 def getUefiPath(self, loader_type, arch):
61 return os.path.join(98 return os.path.join(
62 self.temp_dir, "dists", self.suite, "main", "uefi",99 self.pubconf.archiveroot, "dists", self.suite, "main", "uefi",
63 "%s-%s" % (loader_type, arch))100 "%s-%s" % (loader_type, arch))
64101
65 def test_unconfigured(self):102 def test_unconfigured(self):
66 # If there is no key/cert configuration, processing succeeds but103 # If there is no key/cert configuration, processing succeeds but
67 # nothing is signed.104 # nothing is signed. Signing is attempted.
68 self.pubconf = FakeConfig(self.temp_dir, None)105 self.pubconf = FakeConfig(self.temp_dir, None)
69 self.openArchive("test", "1.0", "amd64")106 self.openArchive("test", "1.0", "amd64")
70 self.archive.add_file("1.0/empty.efi", "")107 self.archive.add_file("1.0/empty.efi", "")
71 upload = self.process()108 upload = self.process()
72 self.assertEqual(0, upload.sign.call_count)109 self.assertEqual(1, upload.signUefi.call_count)
73110
74 def test_missing_key_and_cert(self):111 def test_missing_key_and_cert(self):
75 # If the configured key/cert are missing, processing succeeds but112 # If the configured key/cert are missing, processing succeeds but
76 # nothing is signed.113 # nothing is signed. Signing is attempted.
77 self.openArchive("test", "1.0", "amd64")114 self.openArchive("test", "1.0", "amd64")
78 self.archive.add_file("1.0/empty.efi", "")115 self.archive.add_file("1.0/empty.efi", "")
79 upload = self.process()116 upload = self.process()
80 self.assertEqual(0, upload.sign.call_count)117 self.assertEqual(1, upload.signUefi.call_count)
81118
82 def test_no_efi_files(self):119 def test_no_efi_files(self):
83 # Tarballs containing no *.efi files are extracted without complaint.120 # Tarballs containing no *.efi files are extracted without complaint.
121 # Nothing is signed.
84 self.setUpKeyAndCert()122 self.setUpKeyAndCert()
85 self.openArchive("empty", "1.0", "amd64")123 self.openArchive("empty", "1.0", "amd64")
86 self.archive.add_file("1.0/hello", "world")124 self.archive.add_file("1.0/hello", "world")
87 self.process()125 upload = self.process()
88 self.assertTrue(os.path.exists(os.path.join(126 self.assertTrue(os.path.exists(os.path.join(
89 self.getUefiPath("empty", "amd64"), "1.0", "hello")))127 self.getUefiPath("empty", "amd64"), "1.0", "hello")))
128 self.assertEqual(0, upload.signUefi.call_count)
90129
91 def test_already_exists(self):130 def test_already_exists(self):
92 # If the target directory already exists, processing fails.131 # If the target directory already exists, processing fails.
@@ -104,15 +143,60 @@
104 os.umask(0o002) # cleanup already handled by setUp143 os.umask(0o002) # cleanup already handled by setUp
105 self.assertRaises(CustomUploadBadUmask, self.process)144 self.assertRaises(CustomUploadBadUmask, self.process)
106145
107 def test_correct_signing_command(self):146 def test_correct_uefi_signing_command_executed(self):
108 # getSigningCommand returns the correct command.147 # Check that calling signUefi() will generate the expected command
148 # when appropriate keys are present.
109 self.setUpKeyAndCert()149 self.setUpKeyAndCert()
110 upload = UefiUpload()150 fake_call = FakeMethod()
111 upload.setTargetDirectory(151 with self.useFixture(MonkeyPatch("subprocess.call", fake_call)):
112 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")152 upload = UefiUpload()
113 expected_command = [153 upload.generateUefiKeys = FakeMethod()
114 "sbsign", "--key", self.key, "--cert", self.cert, "t.efi"]154 upload.setTargetDirectory(
115 self.assertEqual(expected_command, upload.getSigningCommand("t.efi"))155 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
156 upload.signUefi('t.efi')
157 self.assertEqual(1, fake_call.call_count)
158 # Assert command form.
159 args = fake_call.calls[0][0][0]
160 expected_cmd = [
161 'sbsign', '--key', self.key, '--cert', self.cert, 't.efi',
162 ]
163 self.assertEqual(expected_cmd, args)
164 self.assertEqual(0, upload.generateUefiKeys.call_count)
165
166 def test_correct_uefi_signing_command_executed_no_keys(self):
167 # Check that calling signUefi() will generate no commands when
168 # no keys are present.
169 self.setUpKeyAndCert(create=False)
170 fake_call = FakeMethod()
171 with self.useFixture(MonkeyPatch("subprocess.call", fake_call)):
172 upload = UefiUpload()
173 upload.generateUefiKeys = FakeMethod()
174 upload.setTargetDirectory(
175 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
176 upload.signUefi('t.efi')
177 self.assertEqual(0, fake_call.call_count)
178 self.assertEqual(0, upload.generateUefiKeys.call_count)
179
180 def test_correct_uefi_keygen_command_executed(self):
181 # Check that calling generateUefiKeys() will generate the
182 # expected command.
183 self.setUpPPA()
184 self.setUpKeyAndCert(create=False)
185 fake_call = FakeMethod()
186 with self.useFixture(MonkeyPatch("subprocess.call", fake_call)):
187 upload = UefiUpload()
188 upload.setTargetDirectory(
189 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
190 upload.generateUefiKeys()
191 self.assertEqual(1, fake_call.call_count)
192 # Assert the actual command matches.
193 args = fake_call.calls[0][0][0]
194 expected_cmd = [
195 'openssl', 'req', '-new', '-x509', '-newkey', 'rsa:2048',
196 '-subj', self.testcase_cn, '-keyout', self.key, '-out', self.cert,
197 '-days', '3650', '-nodes', '-sha256',
198 ]
199 self.assertEqual(expected_cmd, args)
116200
117 def test_signs_image(self):201 def test_signs_image(self):
118 # Each image in the tarball is signed.202 # Each image in the tarball is signed.
@@ -120,10 +204,7 @@
120 self.openArchive("test", "1.0", "amd64")204 self.openArchive("test", "1.0", "amd64")
121 self.archive.add_file("1.0/empty.efi", "")205 self.archive.add_file("1.0/empty.efi", "")
122 upload = self.process()206 upload = self.process()
123 self.assertEqual(1, upload.sign.call_count)207 self.assertEqual(1, upload.signUefi.call_count)
124 self.assertEqual(1, len(upload.sign.calls[0][0]))
125 self.assertEqual(
126 "empty.efi", os.path.basename(upload.sign.calls[0][0][0]))
127208
128 def test_installed(self):209 def test_installed(self):
129 # Files in the tarball are installed correctly.210 # Files in the tarball are installed correctly.
@@ -133,3 +214,36 @@
133 self.process()214 self.process()
134 self.assertTrue(os.path.exists(os.path.join(215 self.assertTrue(os.path.exists(os.path.join(
135 self.getUefiPath("test", "amd64"), "1.0", "empty.efi")))216 self.getUefiPath("test", "amd64"), "1.0", "empty.efi")))
217
218 def test_create_uefi_keys_autokey_off(self):
219 # Keys are not created.
220 self.setUpKeyAndCert(create=False)
221 self.assertFalse(os.path.exists(self.key))
222 self.assertFalse(os.path.exists(self.cert))
223 fake_call = FakeMethod()
224 with self.useFixture(MonkeyPatch("subprocess.call", fake_call)):
225 upload = UefiUpload()
226 upload.generateUefiKeys = FakeMethodGenUefiKeys(upload=upload)
227 upload.setTargetDirectory(
228 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
229 upload.signUefi('t.efi')
230 self.assertEqual(0, upload.generateUefiKeys.call_count)
231 self.assertFalse(os.path.exists(self.key))
232 self.assertFalse(os.path.exists(self.cert))
233
234 def test_create_uefi_keys_autokey_on(self):
235 # Keys are created on demand.
236 self.setUpPPA()
237 self.setUpKeyAndCert(create=False)
238 self.assertFalse(os.path.exists(self.key))
239 self.assertFalse(os.path.exists(self.cert))
240 fake_call = FakeMethod()
241 with self.useFixture(MonkeyPatch("subprocess.call", fake_call)):
242 upload = UefiUpload()
243 upload.generateUefiKeys = FakeMethodGenUefiKeys(upload=upload)
244 upload.setTargetDirectory(
245 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
246 upload.signUefi('t.efi')
247 self.assertEqual(1, upload.generateUefiKeys.call_count)
248 self.assertTrue(os.path.exists(self.key))
249 self.assertTrue(os.path.exists(self.cert))
136250
=== modified file 'lib/lp/archivepublisher/uefi.py'
--- lib/lp/archivepublisher/uefi.py 2013-07-25 16:45:20 +0000
+++ lib/lp/archivepublisher/uefi.py 2016-05-03 11:13:13 +0000
@@ -68,24 +68,17 @@
68 self.logger.warning("No UEFI root configured for this archive")68 self.logger.warning("No UEFI root configured for this archive")
69 self.key = None69 self.key = None
70 self.cert = None70 self.cert = None
71 self.autokey = False
71 else:72 else:
72 self.key = os.path.join(pubconf.uefiroot, "uefi.key")73 self.key = os.path.join(pubconf.uefiroot, "uefi.key")
73 self.cert = os.path.join(pubconf.uefiroot, "uefi.crt")74 self.cert = os.path.join(pubconf.uefiroot, "uefi.crt")
74 if not os.access(self.key, os.R_OK):75 self.autokey = pubconf.uefiautokey
75 if self.logger is not None:
76 self.logger.warning(
77 "UEFI private key %s not readable" % self.key)
78 self.key = None
79 if not os.access(self.cert, os.R_OK):
80 if self.logger is not None:
81 self.logger.warning(
82 "UEFI certificate %s not readable" % self.cert)
83 self.cert = None
8476
85 self.setComponents(tarfile_path)77 self.setComponents(tarfile_path)
86 self.targetdir = os.path.join(78 self.targetdir = os.path.join(
87 pubconf.archiveroot, "dists", distroseries, "main", "uefi",79 pubconf.archiveroot, "dists", distroseries, "main", "uefi",
88 "%s-%s" % (self.loader_type, self.arch))80 "%s-%s" % (self.loader_type, self.arch))
81 self.archiveroot = pubconf.archiveroot
8982
90 @classmethod83 @classmethod
91 def getSeriesKey(cls, tarfile_path):84 def getSeriesKey(cls, tarfile_path):
@@ -102,17 +95,74 @@
102 if filename.endswith(".efi"):95 if filename.endswith(".efi"):
103 yield os.path.join(dirpath, filename)96 yield os.path.join(dirpath, filename)
10497
105 def getSigningCommand(self, image):98 def generateUefiKeys(self):
106 """Return the command used to sign an image."""99 """Generate new UEFI Keys for this archive."""
107 return ["sbsign", "--key", self.key, "--cert", self.cert, image]100 directory = os.path.dirname(self.key)
108101 if not os.path.exists(directory):
109 def sign(self, image):102 os.makedirs(directory)
110 """Sign an image."""103
111 if subprocess.call(self.getSigningCommand(image)) != 0:104 # XXX: pull out the PPA owner and name to seed key CN
105 archive_name = os.path.dirname(self.archiveroot)
106 owner_name = os.path.basename(os.path.dirname(archive_name))
107 archive_name = os.path.basename(archive_name)
108 common_name = '/CN=PPA ' + owner_name + ' ' + archive_name + '/'
109
110 old_mask = os.umask(0o077)
111 try:
112 new_key_cmd = [
113 'openssl', 'req', '-new', '-x509', '-newkey', 'rsa:2048',
114 '-subj', common_name, '-keyout', self.key, '-out', self.cert,
115 '-days', '3650', '-nodes', '-sha256',
116 ]
117 if subprocess.call(new_key_cmd) != 0:
118 # Just log this rather than failing, since custom upload errors
119 # tend to make the publisher rather upset.
120 if self.logger is not None:
121 self.logger.warning(
122 "Failed to generate UEFI signing keys for %s" %
123 common_name)
124 finally:
125 os.umask(old_mask)
126
127 if os.path.exists(self.cert):
128 os.chmod(self.cert, 0o644)
129
130 def getUefiKeys(self):
131 """Validate and return the uefi key and cert for encryption."""
132
133 if self.key and self.cert:
134 # If neither of the key files exists then attempt to
135 # generate them.
136 if (self.autokey and not os.path.exists(self.key)
137 and not os.path.exists(self.cert)):
138 self.generateUefiKeys()
139
140 # If we have keys, but cannot read them they are dead to us.
141 if not os.access(self.key, os.R_OK):
142 if self.logger is not None:
143 self.logger.warning(
144 "UEFI private key %s not readable" % self.key)
145 self.key = None
146 if not os.access(self.cert, os.R_OK):
147 if self.logger is not None:
148 self.logger.warning(
149 "UEFI certificate %s not readable" % self.cert)
150 self.cert = None
151
152 return (self.key, self.cert)
153
154 def signUefi(self, image):
155 """Attempt to sign an image."""
156 (key, cert) = self.getUefiKeys()
157 if not key or not cert:
158 return
159 cmdl = ["sbsign", "--key", key, "--cert", cert, image]
160 if subprocess.call(cmdl) != 0:
112 # Just log this rather than failing, since custom upload errors161 # Just log this rather than failing, since custom upload errors
113 # tend to make the publisher rather upset.162 # tend to make the publisher rather upset.
114 if self.logger is not None:163 if self.logger is not None:
115 self.logger.warning("Failed to sign %s" % image)164 self.logger.warning("UEFI Signing Failed '%s'" %
165 " ".join(cmdl))
116166
117 def extract(self):167 def extract(self):
118 """Copy the custom upload to a temporary directory, and sign it.168 """Copy the custom upload to a temporary directory, and sign it.
@@ -120,11 +170,10 @@
120 No actual extraction is required.170 No actual extraction is required.
121 """171 """
122 super(UefiUpload, self).extract()172 super(UefiUpload, self).extract()
123 if self.key is not None and self.cert is not None:173 efi_filenames = list(self.findEfiFilenames())
124 efi_filenames = list(self.findEfiFilenames())174 for efi_filename in efi_filenames:
125 for efi_filename in efi_filenames:175 remove_if_exists("%s.signed" % efi_filename)
126 remove_if_exists("%s.signed" % efi_filename)176 self.signUefi(efi_filename)
127 self.sign(efi_filename)
128177
129 def shouldInstall(self, filename):178 def shouldInstall(self, filename):
130 return filename.startswith("%s/" % self.version)179 return filename.startswith("%s/" % self.version)