Merge lp:~apw/launchpad/generify-uefi-signing into lp:launchpad

Proposed by Andy Whitcroft on 2016-05-04
Status: Merged
Merged at revision: 18029
Proposed branch: lp:~apw/launchpad/generify-uefi-signing
Merge into: lp:launchpad
Diff against target: 853 lines (+244/-105)
15 files modified
lib/lp/archivepublisher/config.py (+12/-7)
lib/lp/archivepublisher/signing.py (+44/-25)
lib/lp/archivepublisher/tests/test_config.py (+42/-12)
lib/lp/archivepublisher/tests/test_ftparchive.py (+6/-2)
lib/lp/archivepublisher/tests/test_signing.py (+71/-26)
lib/lp/archiveuploader/nascentuploadfile.py (+8/-6)
lib/lp/archiveuploader/tests/test_nascentuploadfile.py (+7/-1)
lib/lp/archiveuploader/tests/test_uploadpolicy.py (+22/-1)
lib/lp/soyuz/browser/queue.py (+2/-2)
lib/lp/soyuz/configure.zcml (+1/-0)
lib/lp/soyuz/enums.py (+3/-3)
lib/lp/soyuz/interfaces/queue.py (+5/-2)
lib/lp/soyuz/model/queue.py (+8/-6)
lib/lp/soyuz/scripts/custom_uploads_copier.py (+6/-5)
lib/lp/soyuz/scripts/tests/test_custom_uploads_copier.py (+7/-7)
To merge this branch: bzr merge lp:~apw/launchpad/generify-uefi-signing
Reviewer Review Type Date Requested Status
Colin Watson 2016-05-04 Approve on 2016-05-11
Review via email: mp+293802@code.launchpad.net

Commit message

Generify the UEFI signing custom upload. Switch it to be a signing upload initially only supporting UEFI signing as before. Include backwards compatibility such that raw-uefi and raw-signing are both supported.

Description of the change

Generify the UEFI signing custom upload. Switch it to be a signing upload initially only supporting UEFI signing as before. Include backwards compatibility such that raw-uefi and raw-signing are both supported. Publication is into dists in the "signed" directory. Where existing configuration exists under "uefi" we will continue to use that. We also expose dists "signed" as dists "uefi" for compatibility with existing *-signed packages.

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

Ok, I have pushed up a further set of changes. These include making the signing dists directory primary and adding tests for it actually being linked correctly. I have also addresed the naming issues you pointed out.

Colin Watson (cjwatson) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/archivepublisher/config.py'
2--- lib/lp/archivepublisher/config.py 2016-04-27 10:39:03 +0000
3+++ lib/lp/archivepublisher/config.py 2016-05-11 15:32:04 +0000
4@@ -78,16 +78,21 @@
5 pubconf.miscroot = None
6
7 if archive.is_main:
8- pubconf.uefiroot = pubconf.archiveroot + '-uefi'
9- pubconf.uefiautokey = False
10+ pubconf.signingroot = pubconf.archiveroot + '-uefi'
11+ if not os.path.exists(pubconf.signingroot):
12+ pubconf.signingroot = pubconf.archiveroot + '-signing'
13+ pubconf.signingautokey = False
14 elif archive.is_ppa:
15- pubconf.uefiroot = os.path.join(
16- ppa_config.signing_keys_root, "uefi",
17+ signing_keys_root = os.path.join(ppa_config.signing_keys_root, "uefi")
18+ if not os.path.exists(signing_keys_root):
19+ signing_keys_root = os.path.join(
20+ ppa_config.signing_keys_root, "signing")
21+ pubconf.signingroot = os.path.join(signing_keys_root,
22 archive.owner.name, archive.name)
23- pubconf.uefiautokey = True
24+ pubconf.signingautokey = True
25 else:
26- pubconf.uefiroot = None
27- pubconf.uefiautokey = False
28+ pubconf.signingroot = None
29+ pubconf.signingautokey = False
30
31 pubconf.poolroot = os.path.join(pubconf.archiveroot, 'pool')
32 pubconf.distsroot = os.path.join(pubconf.archiveroot, 'dists')
33
34=== renamed file 'lib/lp/archivepublisher/uefi.py' => 'lib/lp/archivepublisher/signing.py'
35--- lib/lp/archivepublisher/uefi.py 2016-05-03 09:30:51 +0000
36+++ lib/lp/archivepublisher/signing.py 2016-05-11 15:32:04 +0000
37@@ -1,7 +1,7 @@
38-# Copyright 2012-2013 Canonical Ltd. This software is licensed under the
39+# Copyright 2012-2016 Canonical Ltd. This software is licensed under the
40 # GNU Affero General Public License version 3 (see the file LICENSE).
41
42-"""The processing of UEFI boot loader images.
43+"""The processing of Signing tarballs.
44
45 UEFI Secure Boot requires boot loader images to be signed, and we want to
46 have signed images in the archive so that they can be used for upgrades.
47@@ -12,8 +12,8 @@
48 __metaclass__ = type
49
50 __all__ = [
51- "process_uefi",
52- "UefiUpload",
53+ "process_signing",
54+ "SigningUpload",
55 ]
56
57 import os
58@@ -23,32 +23,32 @@
59 from lp.services.osutils import remove_if_exists
60
61
62-class UefiUpload(CustomUpload):
63- """UEFI boot loader custom upload.
64+class SigningUpload(CustomUpload):
65+ """Signing custom upload.
66
67 The filename must be of the form:
68
69- <TYPE>_<VERSION>_<ARCH>.tar.gz
70+ <PACKAGE>_<VERSION>_<ARCH>.tar.gz
71
72 where:
73
74- * TYPE: loader type (e.g. 'efilinux');
75+ * PACKAGE: source package of the contents;
76 * VERSION: encoded version;
77 * ARCH: targeted architecture tag (e.g. 'amd64').
78
79 The contents are extracted in the archive in the following path:
80
81- <ARCHIVE>/dists/<SUITE>/main/uefi/<TYPE>-<ARCH>/<VERSION>
82+ <ARCHIVE>/dists/<SUITE>/main/signed/<PACKAGE>-<ARCH>/<VERSION>
83
84 A 'current' symbolic link points to the most recent version. The
85 tarfile must contain at least one file matching the wildcard *.efi, and
86 any such files are signed using the archive's UEFI signing key.
87
88- Signing keys may be installed in the "uefiroot" directory specified in
89+ Signing keys may be installed in the "signingroot" directory specified in
90 publisher configuration. In this directory, the private key is
91 "uefi.key" and the certificate is "uefi.crt".
92 """
93- custom_type = "UEFI"
94+ custom_type = "signing"
95
96 @staticmethod
97 def parsePath(tarfile_path):
98@@ -59,32 +59,51 @@
99 return bits[0], bits[1], bits[2].split(".")[0]
100
101 def setComponents(self, tarfile_path):
102- self.loader_type, self.version, self.arch = self.parsePath(
103+ self.package, self.version, self.arch = self.parsePath(
104 tarfile_path)
105
106 def setTargetDirectory(self, pubconf, tarfile_path, distroseries):
107- if pubconf.uefiroot is None:
108+ if pubconf.signingroot is None:
109 if self.logger is not None:
110- self.logger.warning("No UEFI root configured for this archive")
111+ self.logger.warning(
112+ "No signing root configured for this archive")
113 self.key = None
114 self.cert = None
115 self.autokey = False
116 else:
117- self.key = os.path.join(pubconf.uefiroot, "uefi.key")
118- self.cert = os.path.join(pubconf.uefiroot, "uefi.crt")
119- self.autokey = pubconf.uefiautokey
120+ self.key = os.path.join(pubconf.signingroot, "uefi.key")
121+ self.cert = os.path.join(pubconf.signingroot, "uefi.crt")
122+ self.autokey = pubconf.signingautokey
123
124 self.setComponents(tarfile_path)
125+
126+ # Ensure we expose the results via uefi and signed in dists.
127+ # If we already have a uefi directory move it to signed else
128+ # make a new signed. For compatibility ensure we have uefi
129+ # symlink to signed.
130+ # NOTE: we rely on "signed" and "uefi" being in the same directory.
131+ dists_signed = os.path.join(
132+ pubconf.archiveroot, "dists", distroseries, "main", "signed")
133+ dists_uefi = os.path.join(
134+ pubconf.archiveroot, "dists", distroseries, "main", "uefi")
135+ if not os.path.exists(dists_signed):
136+ if os.path.isdir(dists_uefi):
137+ os.rename(dists_uefi, dists_signed)
138+ else:
139+ os.makedirs(dists_signed, 0o755)
140+ if not os.path.exists(dists_uefi):
141+ os.symlink("signed", dists_uefi)
142+
143+ # Extract into the "signed" path regardless of linking.
144 self.targetdir = os.path.join(
145- pubconf.archiveroot, "dists", distroseries, "main", "uefi",
146- "%s-%s" % (self.loader_type, self.arch))
147+ dists_signed, "%s-%s" % (self.package, self.arch))
148 self.archiveroot = pubconf.archiveroot
149
150 @classmethod
151 def getSeriesKey(cls, tarfile_path):
152 try:
153- loader_type, _, arch = cls.parsePath(tarfile_path)
154- return loader_type, arch
155+ package, _, arch = cls.parsePath(tarfile_path)
156+ return package, arch
157 except ValueError:
158 return None
159
160@@ -169,7 +188,7 @@
161
162 No actual extraction is required.
163 """
164- super(UefiUpload, self).extract()
165+ super(SigningUpload, self).extract()
166 efi_filenames = list(self.findEfiFilenames())
167 for efi_filename in efi_filenames:
168 remove_if_exists("%s.signed" % efi_filename)
169@@ -179,12 +198,12 @@
170 return filename.startswith("%s/" % self.version)
171
172
173-def process_uefi(pubconf, tarfile_path, distroseries, logger=None):
174- """Process a raw-uefi tarfile.
175+def process_signing(pubconf, tarfile_path, distroseries, logger=None):
176+ """Process a raw-uefi/raw-signing tarfile.
177
178 Unpacking it into the given archive for the given distroseries.
179 Raises CustomUploadError (or some subclass thereof) if anything goes
180 wrong.
181 """
182- upload = UefiUpload(logger=logger)
183+ upload = SigningUpload(logger=logger)
184 upload.process(pubconf, tarfile_path, distroseries)
185
186=== modified file 'lib/lp/archivepublisher/tests/test_config.py'
187--- lib/lp/archivepublisher/tests/test_config.py 2016-05-03 11:11:39 +0000
188+++ lib/lp/archivepublisher/tests/test_config.py 2016-05-11 15:32:04 +0000
189@@ -8,6 +8,8 @@
190
191 __metaclass__ = type
192
193+import os
194+
195 from zope.component import getUtility
196
197 from lp.archivepublisher.config import getPubConfig
198@@ -46,11 +48,19 @@
199 self.assertEqual(archiveroot + "-misc", primary_config.miscroot)
200 self.assertEqual(
201 self.root + "/ubuntutest-temp", primary_config.temproot)
202- self.assertEqual(archiveroot + "-uefi", primary_config.uefiroot)
203- self.assertFalse(primary_config.uefiautokey)
204+ self.assertEqual(archiveroot + "-signing", primary_config.signingroot)
205+ self.assertFalse(primary_config.signingautokey)
206 self.assertIs(None, primary_config.metaroot)
207 self.assertEqual(archiveroot + "-staging", primary_config.stagingroot)
208
209+ def test_primary_config_compat(self):
210+ # Primary archive configuration is correct.
211+ archiveroot = self.root + "/ubuntutest"
212+ self.addCleanup(os.rmdir, archiveroot + "-uefi")
213+ os.makedirs(archiveroot + "-uefi")
214+ primary_config = getPubConfig(self.ubuntutest.main_archive)
215+ self.assertEqual(archiveroot + "-uefi", primary_config.signingroot)
216+
217 def test_partner_config(self):
218 # Partner archive configuration is correct.
219 # The publisher config for PARTNER contains only 'partner' in its
220@@ -70,8 +80,8 @@
221 self.assertIsNone(partner_config.miscroot)
222 self.assertEqual(
223 self.root + "/ubuntutest-temp", partner_config.temproot)
224- self.assertEqual(archiveroot + "-uefi", partner_config.uefiroot)
225- self.assertFalse(partner_config.uefiautokey)
226+ self.assertEqual(archiveroot + "-signing", partner_config.signingroot)
227+ self.assertFalse(partner_config.signingautokey)
228 self.assertIs(None, partner_config.metaroot)
229 self.assertEqual(archiveroot + "-staging", partner_config.stagingroot)
230
231@@ -93,8 +103,8 @@
232 self.assertEqual(archiveroot + "-cache", copy_config.cacheroot)
233 self.assertEqual(archiveroot + "-misc", copy_config.miscroot)
234 self.assertEqual(archiveroot + "-temp", copy_config.temproot)
235- self.assertIsNone(copy_config.uefiroot)
236- self.assertFalse(copy_config.uefiautokey)
237+ self.assertIsNone(copy_config.signingroot)
238+ self.assertFalse(copy_config.signingautokey)
239 self.assertIs(None, copy_config.metaroot)
240 self.assertIs(None, copy_config.stagingroot)
241
242@@ -131,10 +141,10 @@
243 self.assertIsNone(self.ppa_config.miscroot)
244 self.assertEqual(
245 "/var/tmp/archive/ubuntutest-temp", self.ppa_config.temproot)
246- uefiroot = "/var/tmp/ppa-signing-keys.test/uefi/%s/%s" % (
247+ signingroot = "/var/tmp/ppa-signing-keys.test/signing/%s/%s" % (
248 self.ppa.owner.name, self.ppa.name)
249- self.assertEqual(uefiroot, self.ppa_config.uefiroot)
250- self.assertTrue(self.ppa_config.uefiautokey)
251+ self.assertEqual(signingroot, self.ppa_config.signingroot)
252+ self.assertTrue(self.ppa_config.signingautokey)
253 self.assertIs(None, self.ppa_config.metaroot)
254 self.assertIs(None, self.ppa_config.stagingroot)
255
256@@ -166,10 +176,10 @@
257 "/var/tmp/archive/ubuntutest-temp", p3a_config.temproot)
258 # It's OK for the signing keys to be in the same location as for
259 # public PPAs, as the owner/name namespace is shared.
260- uefiroot = "/var/tmp/ppa-signing-keys.test/uefi/%s/%s" % (
261+ signingroot = "/var/tmp/ppa-signing-keys.test/signing/%s/%s" % (
262 p3a.owner.name, p3a.name)
263- self.assertEqual(uefiroot, p3a_config.uefiroot)
264- self.assertTrue(self.ppa_config.uefiautokey)
265+ self.assertEqual(signingroot, p3a_config.signingroot)
266+ self.assertTrue(self.ppa_config.signingautokey)
267 self.assertIs(None, p3a_config.metaroot)
268 self.assertIs(None, p3a_config.stagingroot)
269
270@@ -186,3 +196,23 @@
271 ubuntu_ppa.owner.name, ubuntu_ppa.name),
272 getPubConfig(ubuntu_ppa).metaroot)
273 self.assertIs(None, getPubConfig(test_ppa).metaroot)
274+
275+
276+class TestGetPubConfigPPACompatUefi(TestCaseWithFactory):
277+
278+ layer = ZopelessDatabaseLayer
279+
280+ def setUp(self):
281+ super(TestGetPubConfigPPACompatUefi, self).setUp()
282+ self.ubuntutest = getUtility(IDistributionSet)['ubuntutest']
283+ self.ppa = self.factory.makeArchive(
284+ distribution=self.ubuntutest, purpose=ArchivePurpose.PPA)
285+ signingroot = "/var/tmp/ppa-signing-keys.test/uefi"
286+ self.addCleanup(os.rmdir, signingroot)
287+ os.makedirs(signingroot)
288+ self.ppa_config = getPubConfig(self.ppa)
289+
290+ def test_ppa_uefi_config(self):
291+ signingroot = "/var/tmp/ppa-signing-keys.test/uefi/%s/%s" % (
292+ self.ppa.owner.name, self.ppa.name)
293+ self.assertEqual(signingroot, self.ppa_config.signingroot)
294
295=== modified file 'lib/lp/archivepublisher/tests/test_ftparchive.py'
296--- lib/lp/archivepublisher/tests/test_ftparchive.py 2016-04-05 02:07:48 +0000
297+++ lib/lp/archivepublisher/tests/test_ftparchive.py 2016-05-11 15:32:04 +0000
298@@ -552,9 +552,10 @@
299 self._addRepositoryFile("main", "tiny", "tiny_0.1.tar.gz")
300 self._addRepositoryFile("main", "tiny", "tiny_0.1_i386.deb")
301 comp_dir = os.path.join(self._distsdir, "hoary-test", "main")
302- os.makedirs(os.path.join(comp_dir, "uefi"))
303- with open(os.path.join(comp_dir, "uefi", "stuff"), "w"):
304+ os.makedirs(os.path.join(comp_dir, "signed"))
305+ with open(os.path.join(comp_dir, "signed", "stuff"), "w"):
306 pass
307+ os.symlink("signed", os.path.join(comp_dir, "uefi"))
308 os.makedirs(os.path.join(comp_dir, "i18n"))
309 for name in ("Translation-de", "Translation-de.gz", "Translation-en",
310 "Translation-en.Z"):
311@@ -602,6 +603,9 @@
312 self.assertContentEqual(
313 ["Sources.gz", "Sources.xz"],
314 os.listdir(os.path.join(comp_dir, "source")))
315+ self.assertEqual(
316+ ["stuff"],
317+ os.listdir(os.path.join(comp_dir, "signed")))
318 self.assertEqual(["stuff"], os.listdir(os.path.join(comp_dir, "uefi")))
319 self.assertContentEqual(
320 ["Translation-de", "Translation-de.gz", "Translation-en.gz",
321
322=== renamed file 'lib/lp/archivepublisher/tests/test_uefi.py' => 'lib/lp/archivepublisher/tests/test_signing.py'
323--- lib/lp/archivepublisher/tests/test_uefi.py 2016-05-03 13:35:16 +0000
324+++ lib/lp/archivepublisher/tests/test_signing.py 2016-05-11 15:32:04 +0000
325@@ -13,7 +13,7 @@
326 CustomUploadAlreadyExists,
327 CustomUploadBadUmask,
328 )
329-from lp.archivepublisher.uefi import UefiUpload
330+from lp.archivepublisher.signing import SigningUpload
331 from lp.services.osutils import write_file
332 from lp.services.tarfile_helpers import LaunchpadWriteTarFile
333 from lp.testing import TestCase
334@@ -35,42 +35,42 @@
335
336 class FakeConfig:
337 """A fake publisher configuration for the main archive."""
338- def __init__(self, distroroot, uefiroot):
339+ def __init__(self, distroroot, signingroot):
340 self.distroroot = distroroot
341- self.uefiroot = uefiroot
342+ self.signingroot = signingroot
343 self.archiveroot = os.path.join(self.distroroot, 'ubuntu')
344- self.uefiautokey = False
345+ self.signingautokey = False
346
347
348 class FakeConfigPPA:
349 """A fake publisher configuration for a PPA."""
350- def __init__(self, distroroot, uefiroot, owner, ppa):
351+ def __init__(self, distroroot, signingroot, owner, ppa):
352 self.distroroot = distroroot
353- self.uefiroot = uefiroot
354+ self.signingroot = signingroot
355 self.archiveroot = os.path.join(self.distroroot, owner, ppa, 'ubuntu')
356- self.uefiautokey = True
357-
358-
359-class TestUefi(TestCase):
360+ self.signingautokey = True
361+
362+
363+class TestSigning(TestCase):
364
365 def setUp(self):
366- super(TestUefi, self).setUp()
367+ super(TestSigning, self).setUp()
368 self.temp_dir = self.makeTemporaryDirectory()
369- self.uefi_dir = self.makeTemporaryDirectory()
370- self.pubconf = FakeConfig(self.temp_dir, self.uefi_dir)
371+ self.signing_dir = self.makeTemporaryDirectory()
372+ self.pubconf = FakeConfig(self.temp_dir, self.signing_dir)
373 self.suite = "distroseries"
374 # CustomUpload.installFiles requires a umask of 0o022.
375 old_umask = os.umask(0o022)
376 self.addCleanup(os.umask, old_umask)
377
378 def setUpPPA(self):
379- self.pubconf = FakeConfigPPA(self.temp_dir, self.uefi_dir,
380+ self.pubconf = FakeConfigPPA(self.temp_dir, self.signing_dir,
381 'ubuntu-archive', 'testing')
382 self.testcase_cn = '/CN=PPA ubuntu-archive testing/'
383
384 def setUpKeyAndCert(self, create=True):
385- self.key = os.path.join(self.uefi_dir, "uefi.key")
386- self.cert = os.path.join(self.uefi_dir, "uefi.crt")
387+ self.key = os.path.join(self.signing_dir, "uefi.key")
388+ self.cert = os.path.join(self.signing_dir, "uefi.crt")
389 if create:
390 write_file(self.key, "")
391 write_file(self.cert, "")
392@@ -85,7 +85,7 @@
393 self.archive.close()
394 self.buffer.close()
395 fake_call = FakeMethod()
396- upload = UefiUpload()
397+ upload = SigningUpload()
398 upload.signUefi = FakeMethod()
399 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
400 upload.process(self.pubconf, self.path, self.suite)
401@@ -94,9 +94,16 @@
402
403 return upload
404
405+ def getDistsPath(self):
406+ return os.path.join(self.pubconf.archiveroot, "dists",
407+ self.suite, "main")
408+
409+ def getSignedPath(self, loader_type, arch):
410+ return os.path.join(self.getDistsPath(), "signed",
411+ "%s-%s" % (loader_type, arch))
412+
413 def getUefiPath(self, loader_type, arch):
414- return os.path.join(
415- self.pubconf.archiveroot, "dists", self.suite, "main", "uefi",
416+ return os.path.join(self.getDistsPath(), "uefi",
417 "%s-%s" % (loader_type, arch))
418
419 def test_unconfigured(self):
420@@ -124,7 +131,7 @@
421 self.archive.add_file("1.0/hello", "world")
422 upload = self.process()
423 self.assertTrue(os.path.exists(os.path.join(
424- self.getUefiPath("empty", "amd64"), "1.0", "hello")))
425+ self.getSignedPath("empty", "amd64"), "1.0", "hello")))
426 self.assertEqual(0, upload.signUefi.call_count)
427
428 def test_already_exists(self):
429@@ -132,7 +139,7 @@
430 self.setUpKeyAndCert()
431 self.openArchive("test", "1.0", "amd64")
432 self.archive.add_file("1.0/empty.efi", "")
433- os.makedirs(os.path.join(self.getUefiPath("test", "amd64"), "1.0"))
434+ os.makedirs(os.path.join(self.getSignedPath("test", "amd64"), "1.0"))
435 self.assertRaises(CustomUploadAlreadyExists, self.process)
436
437 def test_bad_umask(self):
438@@ -149,7 +156,7 @@
439 self.setUpKeyAndCert()
440 fake_call = FakeMethod()
441 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
442- upload = UefiUpload()
443+ upload = SigningUpload()
444 upload.generateUefiKeys = FakeMethod()
445 upload.setTargetDirectory(
446 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
447@@ -169,7 +176,7 @@
448 self.setUpKeyAndCert(create=False)
449 fake_call = FakeMethod()
450 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
451- upload = UefiUpload()
452+ upload = SigningUpload()
453 upload.generateUefiKeys = FakeMethod()
454 upload.setTargetDirectory(
455 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
456@@ -184,7 +191,7 @@
457 self.setUpKeyAndCert(create=False)
458 fake_call = FakeMethod()
459 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
460- upload = UefiUpload()
461+ upload = SigningUpload()
462 upload.setTargetDirectory(
463 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
464 upload.generateUefiKeys()
465@@ -212,6 +219,44 @@
466 self.openArchive("test", "1.0", "amd64")
467 self.archive.add_file("1.0/empty.efi", "")
468 self.process()
469+ self.assertTrue(os.path.isdir(os.path.join(
470+ self.getDistsPath(), "signed")))
471+ self.assertTrue(os.path.islink(os.path.join(
472+ self.getDistsPath(), "uefi")))
473+ self.assertTrue(os.path.exists(os.path.join(
474+ self.getSignedPath("test", "amd64"), "1.0", "empty.efi")))
475+ self.assertTrue(os.path.exists(os.path.join(
476+ self.getUefiPath("test", "amd64"), "1.0", "empty.efi")))
477+
478+ def test_installed_existing_uefi(self):
479+ # Files in the tarball are installed correctly.
480+ os.makedirs(os.path.join(self.getDistsPath(), "uefi"))
481+ self.setUpKeyAndCert()
482+ self.openArchive("test", "1.0", "amd64")
483+ self.archive.add_file("1.0/empty.efi", "")
484+ self.process()
485+ self.assertTrue(os.path.isdir(os.path.join(
486+ self.getDistsPath(), "signed")))
487+ self.assertTrue(os.path.islink(os.path.join(
488+ self.getDistsPath(), "uefi")))
489+ self.assertTrue(os.path.exists(os.path.join(
490+ self.getSignedPath("test", "amd64"), "1.0", "empty.efi")))
491+ self.assertTrue(os.path.exists(os.path.join(
492+ self.getUefiPath("test", "amd64"), "1.0", "empty.efi")))
493+
494+ def test_installed_existing_signing(self):
495+ # Files in the tarball are installed correctly.
496+ os.makedirs(os.path.join(self.getDistsPath(), "signing"))
497+ self.setUpKeyAndCert()
498+ self.openArchive("test", "1.0", "amd64")
499+ self.archive.add_file("1.0/empty.efi", "")
500+ self.process()
501+ self.assertTrue(os.path.isdir(os.path.join(
502+ self.getDistsPath(), "signed")))
503+ self.assertTrue(os.path.islink(os.path.join(
504+ self.getDistsPath(), "uefi")))
505+ self.assertTrue(os.path.exists(os.path.join(
506+ self.getSignedPath("test", "amd64"), "1.0", "empty.efi")))
507 self.assertTrue(os.path.exists(os.path.join(
508 self.getUefiPath("test", "amd64"), "1.0", "empty.efi")))
509
510@@ -222,7 +267,7 @@
511 self.assertFalse(os.path.exists(self.cert))
512 fake_call = FakeMethod()
513 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
514- upload = UefiUpload()
515+ upload = SigningUpload()
516 upload.generateUefiKeys = FakeMethodGenUefiKeys(upload=upload)
517 upload.setTargetDirectory(
518 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
519@@ -239,7 +284,7 @@
520 self.assertFalse(os.path.exists(self.cert))
521 fake_call = FakeMethod()
522 self.useFixture(MonkeyPatch("subprocess.call", fake_call))
523- upload = UefiUpload()
524+ upload = SigningUpload()
525 upload.generateUefiKeys = FakeMethodGenUefiKeys(upload=upload)
526 upload.setTargetDirectory(
527 self.pubconf, "test_1.0_amd64.tar.gz", "distroseries")
528
529=== modified file 'lib/lp/archiveuploader/nascentuploadfile.py'
530--- lib/lp/archiveuploader/nascentuploadfile.py 2015-01-28 17:54:34 +0000
531+++ lib/lp/archiveuploader/nascentuploadfile.py 2016-05-11 15:32:04 +0000
532@@ -1,4 +1,4 @@
533-# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
534+# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
535 # GNU Affero General Public License version 3 (see the file LICENSE).
536
537 """Specific models for uploaded files"""
538@@ -33,7 +33,7 @@
539 from lp.archivepublisher.debian_installer import DebianInstallerUpload
540 from lp.archivepublisher.dist_upgrader import DistUpgraderUpload
541 from lp.archivepublisher.rosetta_translations import RosettaTranslationsUpload
542-from lp.archivepublisher.uefi import UefiUpload
543+from lp.archivepublisher.signing import SigningUpload
544 from lp.archiveuploader.utils import (
545 determine_source_file_type,
546 prefix_multi_line_string,
547@@ -258,7 +258,8 @@
548 PackageUploadCustomFormat.STATIC_TRANSLATIONS,
549 'raw-meta-data':
550 PackageUploadCustomFormat.META_DATA,
551- 'raw-uefi': PackageUploadCustomFormat.UEFI,
552+ 'raw-signing': PackageUploadCustomFormat.SIGNING,
553+ 'raw-uefi': PackageUploadCustomFormat.SIGNING, # Compatibility
554 }
555
556 custom_handlers = {
557@@ -267,7 +268,7 @@
558 PackageUploadCustomFormat.DDTP_TARBALL: DdtpTarballUpload,
559 PackageUploadCustomFormat.ROSETTA_TRANSLATIONS:
560 RosettaTranslationsUpload,
561- PackageUploadCustomFormat.UEFI: UefiUpload,
562+ PackageUploadCustomFormat.SIGNING: SigningUpload,
563 }
564
565 @property
566@@ -306,8 +307,9 @@
567
568 def autoApprove(self):
569 """Return whether this custom upload can be automatically approved."""
570- # UEFI uploads are signed, and must therefore be approved by a human.
571- if self.custom_type == PackageUploadCustomFormat.UEFI:
572+ # Signing uploads will be signed, and must therefore be approved
573+ # by a human.
574+ if self.custom_type == PackageUploadCustomFormat.SIGNING:
575 return False
576 return True
577
578
579=== modified file 'lib/lp/archiveuploader/tests/test_nascentuploadfile.py'
580--- lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2015-03-04 13:06:02 +0000
581+++ lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2016-05-11 15:32:04 +0000
582@@ -1,4 +1,4 @@
583-# Copyright 2010-2015 Canonical Ltd. This software is licensed under the
584+# Copyright 2010-2016 Canonical Ltd. This software is licensed under the
585 # GNU Affero General Public License version 3 (see the file LICENSE).
586
587 """Test NascentUploadFile functionality."""
588@@ -167,6 +167,12 @@
589 "bla.txt", "data", "main/raw-uefi", "extra")
590 self.assertFalse(uploadfile.autoApprove())
591
592+ def test_signing_not_auto_approved(self):
593+ # UEFI uploads are auto-approved.
594+ uploadfile = self.createCustomUploadFile(
595+ "bla.txt", "data", "main/raw-signing", "extra")
596+ self.assertFalse(uploadfile.autoApprove())
597+
598
599 class PackageUploadFileTestCase(NascentUploadFileTestCase):
600 """Base class for all tests of classes deriving from PackageUploadFile."""
601
602=== modified file 'lib/lp/archiveuploader/tests/test_uploadpolicy.py'
603--- lib/lp/archiveuploader/tests/test_uploadpolicy.py 2013-08-01 14:09:45 +0000
604+++ lib/lp/archiveuploader/tests/test_uploadpolicy.py 2016-05-11 15:32:04 +0000
605@@ -1,6 +1,6 @@
606 #!/usr/bin/python
607 #
608-# Copyright 2010-2013 Canonical Ltd. This software is licensed under the
609+# Copyright 2010-2016 Canonical Ltd. This software is licensed under the
610 # GNU Affero General Public License version 3 (see the file LICENSE).
611
612 from zope.component import getUtility
613@@ -304,6 +304,17 @@
614 upload.changes = FakeChangesFile(custom_files=[uploadfile])
615 self.assertFalse(buildd_policy.autoApprove(upload))
616
617+ def test_buildd_does_not_approve_signing(self):
618+ # Uploads to the primary archive containing files for signing are
619+ # not approved.
620+ buildd_policy = findPolicyByName("buildd")
621+ uploadfile = CustomUploadFile(
622+ "uefi.tar.gz", None, 0, "main/raw-signing", "extra", buildd_policy,
623+ None)
624+ upload = make_fake_upload(binaryful=True)
625+ upload.changes = FakeChangesFile(custom_files=[uploadfile])
626+ self.assertFalse(buildd_policy.autoApprove(upload))
627+
628 def test_buildd_approves_uefi_ppa(self):
629 # Uploads to PPAs containing UEFI custom files are auto-approved.
630 buildd_policy = findPolicyByName("buildd")
631@@ -313,3 +324,13 @@
632 upload = make_fake_upload(binaryful=True, is_ppa=True)
633 upload.changes = FakeChangesFile(custom_files=[uploadfile])
634 self.assertTrue(buildd_policy.autoApprove(upload))
635+
636+ def test_buildd_approves_signing_ppa(self):
637+ # Uploads to PPAs containing UEFI custom files are auto-approved.
638+ buildd_policy = findPolicyByName("buildd")
639+ uploadfile = CustomUploadFile(
640+ "uefi.tar.gz", None, 0, "main/raw-signing", "extra", buildd_policy,
641+ None)
642+ upload = make_fake_upload(binaryful=True, is_ppa=True)
643+ upload.changes = FakeChangesFile(custom_files=[uploadfile])
644+ self.assertTrue(buildd_policy.autoApprove(upload))
645
646=== modified file 'lib/lp/soyuz/browser/queue.py'
647--- lib/lp/soyuz/browser/queue.py 2015-07-09 20:06:17 +0000
648+++ lib/lp/soyuz/browser/queue.py 2016-05-11 15:32:04 +0000
649@@ -1,4 +1,4 @@
650-# Copyright 2009-2013 Canonical Ltd. This software is licensed under the
651+# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
652 # GNU Affero General Public License version 3 (see the file LICENSE).
653
654 """Browser views for package queue."""
655@@ -574,7 +574,7 @@
656 (self.contains_installer, ("Installer", 'ubuntu-icon')),
657 (self.contains_upgrader, ("Upgrader", 'ubuntu-icon')),
658 (self.contains_ddtp, (ddtp, 'ubuntu-icon')),
659- (self.contains_uefi, ("Signed UEFI boot loader", 'ubuntu-icon')),
660+ (self.contains_signing, ("Objects for Signing", 'ubuntu-icon')),
661 ]
662 return [
663 self.composeIcon(*details)
664
665=== modified file 'lib/lp/soyuz/configure.zcml'
666--- lib/lp/soyuz/configure.zcml 2016-03-22 12:51:03 +0000
667+++ lib/lp/soyuz/configure.zcml 2016-05-11 15:32:04 +0000
668@@ -168,6 +168,7 @@
669 contains_installer
670 contains_upgrader
671 contains_ddtp
672+ contains_signing
673 contains_uefi
674 displayname
675 displayarchs
676
677=== modified file 'lib/lp/soyuz/enums.py'
678--- lib/lp/soyuz/enums.py 2016-02-05 20:28:29 +0000
679+++ lib/lp/soyuz/enums.py 2016-05-11 15:32:04 +0000
680@@ -481,10 +481,10 @@
681 the Software Center.
682 """)
683
684- UEFI = DBItem(6, """
685- uefi
686+ SIGNING = DBItem(6, """
687+ signing
688
689- A UEFI boot loader image to be signed.
690+ A tarball containing images to be signed.
691 """)
692
693
694
695=== modified file 'lib/lp/soyuz/interfaces/queue.py'
696--- lib/lp/soyuz/interfaces/queue.py 2015-09-03 15:14:07 +0000
697+++ lib/lp/soyuz/interfaces/queue.py 2016-05-11 15:32:04 +0000
698@@ -1,4 +1,4 @@
699-# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
700+# Copyright 2009-2016 Canonical Ltd. This software is licensed under the
701 # GNU Affero General Public License version 3 (see the file LICENSE).
702
703 """Queue interfaces."""
704@@ -264,8 +264,11 @@
705 "whether or not this upload contains upgrader images")
706 contains_ddtp = Attribute(
707 "whether or not this upload contains DDTP images")
708+ contains_signing = Attribute(
709+ "whether or not this upload contains signing images")
710 contains_uefi = Attribute(
711- "whether or not this upload contains a signed UEFI boot loader image")
712+ "whether or not this upload contains a signed UEFI boot loader image"
713+ " (deprecated)")
714 isPPA = Attribute(
715 "Return True if this PackageUpload is a PPA upload.")
716
717
718=== modified file 'lib/lp/soyuz/model/queue.py'
719--- lib/lp/soyuz/model/queue.py 2016-03-14 23:42:45 +0000
720+++ lib/lp/soyuz/model/queue.py 2016-05-11 15:32:04 +0000
721@@ -665,9 +665,11 @@
722 return PackageUploadCustomFormat.DDTP_TARBALL in self._customFormats
723
724 @cachedproperty
725- def contains_uefi(self):
726+ def contains_signing(self):
727 """See `IPackageUpload`."""
728- return PackageUploadCustomFormat.UEFI in self._customFormats
729+ return PackageUploadCustomFormat.SIGNING in self._customFormats
730+
731+ contains_uefi = contains_signing
732
733 @property
734 def package_name(self):
735@@ -1462,13 +1464,13 @@
736 self.libraryfilealias.open()
737 copy_and_close(self.libraryfilealias, file_obj)
738
739- def publishUefi(self, logger=None):
740+ def publishSigning(self, logger=None):
741 """See `IPackageUploadCustom`."""
742 # XXX cprov 2005-03-03: We need to use the Zope Component Lookup
743 # to instantiate the object in question and avoid circular imports
744- from lp.archivepublisher.uefi import process_uefi
745+ from lp.archivepublisher.signing import process_signing
746
747- self._publishCustom(process_uefi, logger=logger)
748+ self._publishCustom(process_signing, logger=logger)
749
750 publisher_dispatch = {
751 PackageUploadCustomFormat.DEBIAN_INSTALLER: publishDebianInstaller,
752@@ -1479,7 +1481,7 @@
753 PackageUploadCustomFormat.STATIC_TRANSLATIONS:
754 publishStaticTranslations,
755 PackageUploadCustomFormat.META_DATA: publishMetaData,
756- PackageUploadCustomFormat.UEFI: publishUefi,
757+ PackageUploadCustomFormat.SIGNING: publishSigning,
758 }
759
760 # publisher_dispatch must have an entry for each value of
761
762=== modified file 'lib/lp/soyuz/scripts/custom_uploads_copier.py'
763--- lib/lp/soyuz/scripts/custom_uploads_copier.py 2013-10-10 18:47:16 +0000
764+++ lib/lp/soyuz/scripts/custom_uploads_copier.py 2016-05-11 15:32:04 +0000
765@@ -1,4 +1,4 @@
766-# Copyright 2011-2013 Canonical Ltd. This software is licensed under the
767+# Copyright 2011-2016 Canonical Ltd. This software is licensed under the
768 # GNU Affero General Public License version 3 (see the file LICENSE).
769
770 """Copy latest custom uploads into a distribution release series.
771@@ -18,7 +18,7 @@
772 from lp.archivepublisher.debian_installer import DebianInstallerUpload
773 from lp.archivepublisher.dist_upgrader import DistUpgraderUpload
774 from lp.archivepublisher.rosetta_translations import RosettaTranslationsUpload
775-from lp.archivepublisher.uefi import UefiUpload
776+from lp.archivepublisher.signing import SigningUpload
777 from lp.registry.interfaces.pocket import PackagePublishingPocket
778 from lp.services.database.bulk import load_referencing
779 from lp.soyuz.enums import PackageUploadCustomFormat
780@@ -40,7 +40,7 @@
781 PackageUploadCustomFormat.DDTP_TARBALL: DdtpTarballUpload,
782 PackageUploadCustomFormat.ROSETTA_TRANSLATIONS:
783 RosettaTranslationsUpload,
784- PackageUploadCustomFormat.UEFI: UefiUpload,
785+ PackageUploadCustomFormat.SIGNING: SigningUpload,
786 }
787
788 def __init__(self, target_series,
789@@ -61,8 +61,9 @@
790 if (custom.packageupload.archive.is_ppa or
791 custom.packageupload.archive == source_archive):
792 return True
793- # UEFI uploads are signed, and must therefore be approved by a human.
794- if custom.customformat == PackageUploadCustomFormat.UEFI:
795+ # Signing uploads will be signed, and must therefore be approved
796+ # by a human.
797+ if custom.customformat == PackageUploadCustomFormat.SIGNING:
798 return False
799 return True
800
801
802=== modified file 'lib/lp/soyuz/scripts/tests/test_custom_uploads_copier.py'
803--- lib/lp/soyuz/scripts/tests/test_custom_uploads_copier.py 2013-10-10 18:47:16 +0000
804+++ lib/lp/soyuz/scripts/tests/test_custom_uploads_copier.py 2016-05-11 15:32:04 +0000
805@@ -1,4 +1,4 @@
806-# Copyright 2011-2013 Canonical Ltd. This software is licensed under the
807+# Copyright 2011-2016 Canonical Ltd. This software is licensed under the
808 # GNU Affero General Public License version 3 (see the file LICENSE).
809
810 """Test copying of custom package uploads for a new `DistroSeries`."""
811@@ -408,36 +408,36 @@
812 copied_pu = copier.copyUpload(original_upload).packageupload
813 self.assertEqual(PackageUploadStatus.ACCEPTED, copied_pu.status)
814
815- def test_copyUpload_unapproves_uefi_from_different_archive(self):
816+ def test_copyUpload_unapproves_signing_from_different_archive(self):
817 # Copies of UEFI custom uploads to a primary archive are set to
818 # UNAPPROVED, since they will normally end up being signed.
819 target_series = self.factory.makeDistroSeries()
820 archive = self.factory.makeArchive(
821 distribution=target_series.distribution)
822 original_upload = self.makeUpload(
823- archive=archive, custom_type=PackageUploadCustomFormat.UEFI)
824+ archive=archive, custom_type=PackageUploadCustomFormat.SIGNING)
825 copier = CustomUploadsCopier(
826 target_series, target_archive=target_series.main_archive)
827 copied_pu = copier.copyUpload(original_upload).packageupload
828 self.assertEqual(PackageUploadStatus.UNAPPROVED, copied_pu.status)
829
830- def test_copyUpload_approves_uefi_from_same_archive(self):
831+ def test_copyUpload_approves_signing_from_same_archive(self):
832 # Copies of UEFI custom uploads within the same archive are
833 # automatically accepted, since they have already been signed.
834 original_upload = self.makeUpload(
835- custom_type=PackageUploadCustomFormat.UEFI)
836+ custom_type=PackageUploadCustomFormat.SIGNING)
837 target_series = self.factory.makeDistroSeries()
838 copier = CustomUploadsCopier(target_series)
839 copied_pu = copier.copyUpload(original_upload).packageupload
840 self.assertEqual(PackageUploadStatus.ACCEPTED, copied_pu.status)
841
842- def test_copyUpload_approves_uefi_to_ppa(self):
843+ def test_copyUpload_approves_signing_to_ppa(self):
844 # Copies of UEFI custom uploads to a PPA are automatically accepted,
845 # since PPAs have much more limited upload permissions than the main
846 # archive, and in any case PPAs do not have an upload approval
847 # workflow.
848 original_upload = self.makeUpload(
849- custom_type=PackageUploadCustomFormat.UEFI)
850+ custom_type=PackageUploadCustomFormat.SIGNING)
851 target_series = self.factory.makeDistroSeries()
852 target_archive = self.factory.makeArchive(
853 distribution=target_series.distribution)