Merge ~cjwatson/launchpad:archive-gpg-generate-using-signing-service into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 96b7e00f45b9db262a286028a460a7ff39fcb8b8
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:archive-gpg-generate-using-signing-service
Merge into: launchpad:master
Diff against target: 530 lines (+196/-53)
11 files modified
lib/lp/archivepublisher/archivegpgsigningkey.py (+55/-23)
lib/lp/archivepublisher/tests/test_archivegpgsigningkey.py (+105/-3)
lib/lp/services/gpg/handler.py (+3/-7)
lib/lp/services/gpg/interfaces.py (+13/-2)
lib/lp/services/signing/tests/helpers.py (+2/-2)
lib/lp/soyuz/configure.zcml (+0/-1)
lib/lp/soyuz/interfaces/archive.py (+2/-0)
lib/lp/soyuz/model/archive.py (+7/-6)
lib/lp/soyuz/scripts/ppakeygenerator.py (+3/-3)
lib/lp/soyuz/scripts/tests/test_ppakeygenerator.py (+5/-5)
lib/lp/soyuz/tests/test_archive.py (+1/-1)
Reviewer Review Type Date Requested Status
Ioana Lasc (community) Approve
Review via email: mp+390668@code.launchpad.net

Commit message

Generate archive signing keys using the signing service

Description of the change

This is guarded by the feature rule 'archivepublisher.gpg.signing_service.enabled'.

To post a comment you must log in.
Revision history for this message
Ioana Lasc (ilasc) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/archivepublisher/archivegpgsigningkey.py b/lib/lp/archivepublisher/archivegpgsigningkey.py
2index a342332..20a4d79 100644
3--- a/lib/lp/archivepublisher/archivegpgsigningkey.py
4+++ b/lib/lp/archivepublisher/archivegpgsigningkey.py
5@@ -37,17 +37,24 @@ from lp.archivepublisher.run_parts import (
6 from lp.registry.interfaces.gpg import IGPGKeySet
7 from lp.services.config import config
8 from lp.services.features import getFeatureFlag
9-from lp.services.gpg.interfaces import IGPGHandler
10+from lp.services.gpg.interfaces import (
11+ IGPGHandler,
12+ IPymeKey,
13+ )
14 from lp.services.osutils import remove_if_exists
15 from lp.services.propertycache import (
16 cachedproperty,
17 get_property_cache,
18 )
19 from lp.services.signing.enums import (
20+ OpenPGPKeyAlgorithm,
21 SigningKeyType,
22 SigningMode,
23 )
24-from lp.services.signing.interfaces.signingkey import ISigningKeySet
25+from lp.services.signing.interfaces.signingkey import (
26+ ISigningKey,
27+ ISigningKeySet,
28+ )
29
30
31 @implementer(ISignableArchive)
32@@ -72,7 +79,7 @@ class SignableArchive:
33 def can_sign(self):
34 """See `ISignableArchive`."""
35 return (
36- self.archive.signing_key is not None or
37+ self.archive.signing_key_fingerprint is not None or
38 self._run_parts_dir is not None)
39
40 @cachedproperty
41@@ -237,9 +244,9 @@ class ArchiveGPGSigningKey(SignableArchive):
42 with open(export_path, 'wb') as export_file:
43 export_file.write(key.export())
44
45- def generateSigningKey(self, log=None):
46+ def generateSigningKey(self, log=None, async_keyserver=False):
47 """See `IArchiveGPGSigningKey`."""
48- assert self.archive.signing_key is None, (
49+ assert self.archive.signing_key_fingerprint is None, (
50 "Cannot override signing_keys.")
51
52 # Always generate signing keys for the default PPA, even if it
53@@ -257,13 +264,26 @@ class ArchiveGPGSigningKey(SignableArchive):
54
55 key_displayname = (
56 "Launchpad PPA for %s" % self.archive.owner.displayname)
57- secret_key = getUtility(IGPGHandler).generateKey(
58- key_displayname, logger=log)
59- self._setupSigningKey(secret_key)
60+ if getFeatureFlag(PUBLISHER_GPG_USES_SIGNING_SERVICE):
61+ try:
62+ signing_key = getUtility(ISigningKeySet).generate(
63+ SigningKeyType.OPENPGP, key_displayname,
64+ openpgp_key_algorithm=OpenPGPKeyAlgorithm.RSA, length=4096)
65+ except Exception as e:
66+ if log is not None:
67+ log.exception(
68+ "Error generating signing key for %s: %s %s" %
69+ (self.archive.reference, e.__class__.__name__, e))
70+ raise
71+ else:
72+ signing_key = getUtility(IGPGHandler).generateKey(
73+ key_displayname, logger=log)
74+ return self._setupSigningKey(
75+ signing_key, async_keyserver=async_keyserver)
76
77 def setSigningKey(self, key_path, async_keyserver=False):
78 """See `IArchiveGPGSigningKey`."""
79- assert self.archive.signing_key is None, (
80+ assert self.archive.signing_key_fingerprint is None, (
81 "Cannot override signing_keys.")
82 assert os.path.exists(key_path), (
83 "%s does not exist" % key_path)
84@@ -274,34 +294,46 @@ class ArchiveGPGSigningKey(SignableArchive):
85 return self._setupSigningKey(
86 secret_key, async_keyserver=async_keyserver)
87
88- def _uploadPublicSigningKey(self, secret_key):
89+ def _uploadPublicSigningKey(self, signing_key):
90 """Upload the public half of a signing key to the keyserver."""
91 # The handler's security proxying doesn't protect anything useful
92 # here, and when we're running in a thread we don't have an
93 # interaction.
94 gpghandler = removeSecurityProxy(getUtility(IGPGHandler))
95- pub_key = gpghandler.retrieveKey(secret_key.fingerprint)
96- gpghandler.uploadPublicKey(pub_key.fingerprint)
97- return pub_key
98+ if IPymeKey.providedBy(signing_key):
99+ pub_key = gpghandler.retrieveKey(signing_key.fingerprint)
100+ gpghandler.uploadPublicKey(pub_key.fingerprint)
101+ return pub_key
102+ else:
103+ assert ISigningKey.providedBy(signing_key)
104+ gpghandler.submitKey(removeSecurityProxy(signing_key).public_key)
105+ return signing_key
106
107 def _storeSigningKey(self, pub_key):
108 """Store signing key reference in the database."""
109 key_owner = getUtility(ILaunchpadCelebrities).ppa_key_guard
110- key, _ = getUtility(IGPGKeySet).activate(
111- key_owner, pub_key, pub_key.can_encrypt)
112- self.archive.signing_key_owner = key.owner
113+ if IPymeKey.providedBy(pub_key):
114+ key, _ = getUtility(IGPGKeySet).activate(
115+ key_owner, pub_key, pub_key.can_encrypt)
116+ else:
117+ assert ISigningKey.providedBy(pub_key)
118+ key = pub_key
119+ self.archive.signing_key_owner = key_owner
120 self.archive.signing_key_fingerprint = key.fingerprint
121 del get_property_cache(self.archive).signing_key
122
123- def _setupSigningKey(self, secret_key, async_keyserver=False):
124+ def _setupSigningKey(self, signing_key, async_keyserver=False):
125 """Mandatory setup for signing keys.
126
127- * Export the secret key into the protected disk location.
128+ * Export the secret key into the protected disk location (for
129+ locally-generated keys).
130 * Upload public key to the keyserver.
131- * Store the public GPGKey reference in the database and update
132- the context archive.signing_key.
133+ * Store the public GPGKey reference in the database (for
134+ locally-generated keys) and update the context
135+ archive.signing_key.
136 """
137- self.exportSecretKey(secret_key)
138+ if IPymeKey.providedBy(signing_key):
139+ self.exportSecretKey(signing_key)
140 if async_keyserver:
141 # If we have an asynchronous keyserver running in the current
142 # thread using Twisted, then we need some contortions to ensure
143@@ -310,10 +342,10 @@ class ArchiveGPGSigningKey(SignableArchive):
144 # Since that thread won't have a Zope interaction, we need to
145 # unwrap the security proxy for it.
146 d = deferToThread(
147- self._uploadPublicSigningKey, removeSecurityProxy(secret_key))
148+ self._uploadPublicSigningKey, removeSecurityProxy(signing_key))
149 d.addCallback(ProxyFactory)
150 d.addCallback(self._storeSigningKey)
151 return d
152 else:
153- pub_key = self._uploadPublicSigningKey(secret_key)
154+ pub_key = self._uploadPublicSigningKey(signing_key)
155 self._storeSigningKey(pub_key)
156diff --git a/lib/lp/archivepublisher/tests/test_archivegpgsigningkey.py b/lib/lp/archivepublisher/tests/test_archivegpgsigningkey.py
157index 87359e8..67366bd 100644
158--- a/lib/lp/archivepublisher/tests/test_archivegpgsigningkey.py
159+++ b/lib/lp/archivepublisher/tests/test_archivegpgsigningkey.py
160@@ -14,8 +14,15 @@ from testtools.matchers import (
161 FileContains,
162 StartsWith,
163 )
164-from testtools.twistedsupport import AsynchronousDeferredRunTest
165-from twisted.internet import defer
166+from testtools.twistedsupport import (
167+ AsynchronousDeferredRunTest,
168+ AsynchronousDeferredRunTestForBrokenTwisted,
169+ )
170+import treq
171+from twisted.internet import (
172+ defer,
173+ reactor,
174+ )
175 from zope.component import getUtility
176
177 from lp.archivepublisher.config import getPubConfig
178@@ -26,18 +33,27 @@ from lp.archivepublisher.interfaces.archivegpgsigningkey import (
179 )
180 from lp.archivepublisher.interfaces.publisherconfig import IPublisherConfigSet
181 from lp.archivepublisher.tests.test_run_parts import RunPartsMixin
182+from lp.registry.interfaces.gpg import IGPGKeySet
183 from lp.services.compat import mock
184 from lp.services.features.testing import FeatureFixture
185+from lp.services.gpg.interfaces import IGPGHandler
186+from lp.services.gpg.tests.test_gpghandler import FakeGenerateKey
187 from lp.services.log.logger import BufferLogger
188 from lp.services.osutils import write_file
189 from lp.services.signing.enums import (
190 SigningKeyType,
191 SigningMode,
192 )
193+from lp.services.signing.interfaces.signingkey import ISigningKeySet
194 from lp.services.signing.tests.helpers import SigningServiceClientFixture
195+from lp.services.twistedsupport.testing import TReqFixture
196+from lp.services.twistedsupport.treq import check_status
197 from lp.soyuz.enums import ArchivePurpose
198 from lp.testing import TestCaseWithFactory
199-from lp.testing.gpgkeys import gpgkeysdir
200+from lp.testing.gpgkeys import (
201+ gpgkeysdir,
202+ test_pubkey_from_email,
203+ )
204 from lp.testing.keyserver import InProcessKeyServerFixture
205 from lp.testing.layers import ZopelessDatabaseLayer
206
207@@ -271,3 +287,89 @@ class TestSignableArchiveWithRunParts(RunPartsMixin, TestCaseWithFactory):
208 FileContains(
209 "detached signature of %s (%s, %s/%s)\n" %
210 (filename, self.archive_root, self.distro.name, self.suite)))
211+
212+
213+class TestArchiveGPGSigningKey(TestCaseWithFactory):
214+
215+ layer = ZopelessDatabaseLayer
216+ # treq.content doesn't close the connection before yielding control back
217+ # to the test, so we need to spin the reactor at the end to finish
218+ # things off.
219+ run_tests_with = AsynchronousDeferredRunTestForBrokenTwisted.make_factory(
220+ timeout=10000)
221+
222+ @defer.inlineCallbacks
223+ def setUp(self):
224+ super(TestArchiveGPGSigningKey, self).setUp()
225+ self.temp_dir = self.makeTemporaryDirectory()
226+ self.pushConfig("personalpackagearchive", root=self.temp_dir)
227+ self.keyserver = self.useFixture(InProcessKeyServerFixture())
228+ yield self.keyserver.start()
229+
230+ @defer.inlineCallbacks
231+ def test_generateSigningKey_local(self):
232+ # Generating a signing key locally using GPGHandler stores it in the
233+ # database and pushes it to the keyserver.
234+ self.useFixture(FakeGenerateKey("ppa-sample@canonical.com.sec"))
235+ logger = BufferLogger()
236+ # Use a display name that matches the pregenerated sample key.
237+ owner = self.factory.makePerson(
238+ displayname="Celso \xe1\xe9\xed\xf3\xfa Providelo")
239+ archive = self.factory.makeArchive(owner=owner)
240+ yield IArchiveGPGSigningKey(archive).generateSigningKey(
241+ log=logger, async_keyserver=True)
242+ # The key is stored in the database.
243+ self.assertIsNotNone(archive.signing_key_owner)
244+ self.assertIsNotNone(archive.signing_key_fingerprint)
245+ # The key is stored as a GPGKey, not a SigningKey.
246+ self.assertIsNotNone(
247+ getUtility(IGPGKeySet).getByFingerprint(
248+ archive.signing_key_fingerprint))
249+ self.assertIsNone(
250+ getUtility(ISigningKeySet).get(
251+ SigningKeyType.OPENPGP, archive.signing_key_fingerprint))
252+ # The key is uploaded to the keyserver.
253+ client = self.useFixture(TReqFixture(reactor)).client
254+ response = yield client.get(
255+ getUtility(IGPGHandler).getURLForKeyInServer(
256+ archive.signing_key_fingerprint, "get"))
257+ yield check_status(response)
258+ content = yield treq.content(response)
259+ self.assertIn(b"-----BEGIN PGP PUBLIC KEY BLOCK-----\n", content)
260+
261+ @defer.inlineCallbacks
262+ def test_generateSigningKey_signing_service(self):
263+ # Generating a signing key on the signing service stores it in the
264+ # database and pushes it to the keyserver.
265+ self.useFixture(
266+ FeatureFixture({PUBLISHER_GPG_USES_SIGNING_SERVICE: "on"}))
267+ signing_service_client = self.useFixture(
268+ SigningServiceClientFixture(self.factory))
269+ signing_service_client.generate.side_effect = None
270+ test_key = test_pubkey_from_email("ftpmaster@canonical.com")
271+ signing_service_client.generate.return_value = {
272+ "fingerprint": "33C0A61893A5DC5EB325B29E415A12CAC2F30234",
273+ "public-key": test_key,
274+ }
275+ logger = BufferLogger()
276+ archive = self.factory.makeArchive()
277+ yield IArchiveGPGSigningKey(archive).generateSigningKey(
278+ log=logger, async_keyserver=True)
279+ # The key is stored in the database.
280+ self.assertIsNotNone(archive.signing_key_owner)
281+ self.assertIsNotNone(archive.signing_key_fingerprint)
282+ # The key is stored as a SigningKey, not a GPGKey.
283+ self.assertIsNone(
284+ getUtility(IGPGKeySet).getByFingerprint(
285+ archive.signing_key_fingerprint))
286+ signing_key = getUtility(ISigningKeySet).get(
287+ SigningKeyType.OPENPGP, archive.signing_key_fingerprint)
288+ self.assertEqual(test_key, signing_key.public_key)
289+ # The key is uploaded to the keyserver.
290+ client = self.useFixture(TReqFixture(reactor)).client
291+ response = yield client.get(
292+ getUtility(IGPGHandler).getURLForKeyInServer(
293+ archive.signing_key_fingerprint, "get"))
294+ yield check_status(response)
295+ content = yield treq.content(response)
296+ self.assertIn(test_key, content)
297diff --git a/lib/lp/services/gpg/handler.py b/lib/lp/services/gpg/handler.py
298index b2bcbad..e3eba45 100644
299--- a/lib/lp/services/gpg/handler.py
300+++ b/lib/lp/services/gpg/handler.py
301@@ -489,12 +489,8 @@ class GPGHandler:
302 raise GPGKeyExpired(key)
303 return key
304
305- def _submitKey(self, content):
306- """Submit an ASCII-armored public key export to the keyserver.
307-
308- It issues a POST at /pks/add on the keyserver specified in the
309- configuration.
310- """
311+ def submitKey(self, content):
312+ """See `IGPGHandler`."""
313 keyserver_http_url = '%s:%s' % (
314 config.gpghandler.host, config.gpghandler.port)
315
316@@ -527,7 +523,7 @@ class GPGHandler:
317 return
318
319 pub_key = self.retrieveKey(fingerprint)
320- self._submitKey(pub_key.export())
321+ self.submitKey(pub_key.export())
322
323 def getURLForKeyInServer(self, fingerprint, action='index', public=False):
324 """See IGPGHandler"""
325diff --git a/lib/lp/services/gpg/interfaces.py b/lib/lp/services/gpg/interfaces.py
326index 78b44c8..d6f0f73 100644
327--- a/lib/lp/services/gpg/interfaces.py
328+++ b/lib/lp/services/gpg/interfaces.py
329@@ -357,6 +357,17 @@ class IGPGHandler(Interface):
330 :return: a `PymeKey`object containing the key information.
331 """
332
333+ def submitKey(content):
334+ """Submit an ASCII-armored public key export to the keyserver.
335+
336+ It issues a POST at /pks/add on the keyserver specified in the
337+ configuration.
338+
339+ :param content: The exported public key, as a byte string.
340+ :raise GPGUploadFailure: if the keyserver could not be reached.
341+ :raise AssertionError: if the POST request failed.
342+ """
343+
344 def uploadPublicKey(fingerprint):
345 """Upload the specified public key to a keyserver.
346
347@@ -365,8 +376,8 @@ class IGPGHandler(Interface):
348
349 :param fingerprint: The key fingerprint, which must be an hexadecimal
350 string.
351- :raise GPGUploadFailure: if the keyserver could not be reaches.
352- :raise AssertionError: if the POST request doesn't succeed.
353+ :raise GPGUploadFailure: if the keyserver could not be reached.
354+ :raise AssertionError: if the POST request failed.
355 """
356
357 def localKeys(filter=None, secret=False):
358diff --git a/lib/lp/services/signing/tests/helpers.py b/lib/lp/services/signing/tests/helpers.py
359index f819745..6831edb 100644
360--- a/lib/lp/services/signing/tests/helpers.py
361+++ b/lib/lp/services/signing/tests/helpers.py
362@@ -49,7 +49,7 @@ class SigningServiceClientFixture(fixtures.Fixture):
363 openpgp_key_algorithm=None, length=None):
364 key = bytes(PrivateKey.generate().public_key)
365 data = {
366- "fingerprint": self.factory.getUniqueHexString(40),
367+ "fingerprint": self.factory.getUniqueHexString(40).upper(),
368 "public-key": key,
369 }
370 self.generate_returns.append((key_type, data))
371@@ -69,7 +69,7 @@ class SigningServiceClientFixture(fixtures.Fixture):
372
373 def _inject(self, key_type, private_key, public_key, description,
374 created_at):
375- data = {'fingerprint': self.factory.getUniqueHexString(40)}
376+ data = {'fingerprint': self.factory.getUniqueHexString(40).upper()}
377 self.inject_returns.append(data)
378 return data
379
380diff --git a/lib/lp/soyuz/configure.zcml b/lib/lp/soyuz/configure.zcml
381index 2e97958..643a85b 100644
382--- a/lib/lp/soyuz/configure.zcml
383+++ b/lib/lp/soyuz/configure.zcml
384@@ -373,7 +373,6 @@
385 set_schema="lp.soyuz.interfaces.archive.IArchiveRestricted"/>
386 <require
387 permission="launchpad.InternalScriptsOnly"
388- attributes="signing_key_owner"
389 set_attributes="dirty_suites distribution signing_key_owner
390 signing_key_fingerprint"/>
391 </class>
392diff --git a/lib/lp/soyuz/interfaces/archive.py b/lib/lp/soyuz/interfaces/archive.py
393index 407f953..b6cc663 100644
394--- a/lib/lp/soyuz/interfaces/archive.py
395+++ b/lib/lp/soyuz/interfaces/archive.py
396@@ -461,6 +461,8 @@ class IArchiveSubscriberView(Interface):
397 "explicit publish flag and any other constraints."))
398 series_with_sources = Attribute(
399 "DistroSeries to which this archive has published sources")
400+ signing_key_owner = Reference(
401+ title=_("Archive signing key owner"), required=False, schema=IPerson)
402 signing_key_fingerprint = exported(
403 Text(
404 title=_("Archive signing key fingerprint"), required=False,
405diff --git a/lib/lp/soyuz/model/archive.py b/lib/lp/soyuz/model/archive.py
406index a37b737..0d58e56 100644
407--- a/lib/lp/soyuz/model/archive.py
408+++ b/lib/lp/soyuz/model/archive.py
409@@ -466,7 +466,7 @@ class Archive(SQLBase):
410 return (
411 not config.personalpackagearchive.require_signing_keys or
412 not self.is_ppa or
413- self.signing_key is not None)
414+ self.signing_key_fingerprint is not None)
415
416 @property
417 def reference(self):
418@@ -2717,10 +2717,12 @@ class ArchiveSet:
419 (owner.name, distribution.name, name))
420
421 # Signing-key for the default PPA is reused when it's already present.
422- signing_key = None
423+ signing_key_owner = None
424+ signing_key_fingerprint = None
425 if purpose == ArchivePurpose.PPA:
426 if owner.archive is not None:
427- signing_key = owner.archive.signing_key
428+ signing_key_owner = owner.archive.signing_key_owner
429+ signing_key_fingerprint = owner.archive.signing_key_fingerprint
430 else:
431 # owner.archive is a cached property and we've just cached it.
432 del get_property_cache(owner).archive
433@@ -2729,9 +2731,8 @@ class ArchiveSet:
434 owner=owner, distribution=distribution, name=name,
435 displayname=displayname, description=description,
436 purpose=purpose, publish=publish,
437- signing_key_owner=signing_key.owner if signing_key else None,
438- signing_key_fingerprint=(
439- signing_key.fingerprint if signing_key else None),
440+ signing_key_owner=signing_key_owner,
441+ signing_key_fingerprint=signing_key_fingerprint,
442 require_virtualized=require_virtualized)
443
444 # Upon creation archives are enabled by default.
445diff --git a/lib/lp/soyuz/scripts/ppakeygenerator.py b/lib/lp/soyuz/scripts/ppakeygenerator.py
446index 190b4a0..88e1d84 100644
447--- a/lib/lp/soyuz/scripts/ppakeygenerator.py
448+++ b/lib/lp/soyuz/scripts/ppakeygenerator.py
449@@ -34,7 +34,7 @@ class PPAKeyGenerator(LaunchpadCronScript):
450 (archive.reference, archive.displayname))
451 archive_signing_key = IArchiveGPGSigningKey(archive)
452 archive_signing_key.generateSigningKey(log=self.logger)
453- self.logger.info("Key %s" % archive.signing_key.fingerprint)
454+ self.logger.info("Key %s" % archive.signing_key_fingerprint)
455
456 def main(self):
457 """Generate signing keys for the selected PPAs."""
458@@ -45,11 +45,11 @@ class PPAKeyGenerator(LaunchpadCronScript):
459 raise LaunchpadScriptFailure(
460 "No archive named '%s' could be found."
461 % self.options.archive)
462- if archive.signing_key is not None:
463+ if archive.signing_key_fingerprint is not None:
464 raise LaunchpadScriptFailure(
465 "%s (%s) already has a signing_key (%s)"
466 % (archive.reference, archive.displayname,
467- archive.signing_key.fingerprint))
468+ archive.signing_key_fingerprint))
469 archives = [archive]
470 else:
471 archive_set = getUtility(IArchiveSet)
472diff --git a/lib/lp/soyuz/scripts/tests/test_ppakeygenerator.py b/lib/lp/soyuz/scripts/tests/test_ppakeygenerator.py
473index 56e8710..a5d3caf 100644
474--- a/lib/lp/soyuz/scripts/tests/test_ppakeygenerator.py
475+++ b/lib/lp/soyuz/scripts/tests/test_ppakeygenerator.py
476@@ -83,7 +83,7 @@ class TestPPAKeyGenerator(TestCase):
477 LaunchpadScriptFailure,
478 ("~cprov/ubuntu/ppa (PPA for Celso Providelo) already has a "
479 "signing_key (%s)" %
480- cprov.archive.signing_key.fingerprint),
481+ cprov.archive.signing_key_fingerprint),
482 key_generator.main)
483
484 def testGenerateKeyForASinglePPA(self):
485@@ -95,14 +95,14 @@ class TestPPAKeyGenerator(TestCase):
486 cprov = getUtility(IPersonSet).getByName('cprov')
487 self._fixArchiveForKeyGeneration(cprov.archive)
488
489- self.assertTrue(cprov.archive.signing_key is None)
490+ self.assertIsNone(cprov.archive.signing_key_fingerprint)
491
492 txn = FakeTransaction()
493 key_generator = self._getKeyGenerator(
494 archive_reference='~cprov/ubuntutest/ppa', txn=txn)
495 key_generator.main()
496
497- self.assertTrue(cprov.archive.signing_key is not None)
498+ self.assertIsNotNone(cprov.archive.signing_key_fingerprint)
499 self.assertEqual(txn.commit_count, 1)
500
501 def testGenerateKeyForAllPPA(self):
502@@ -115,13 +115,13 @@ class TestPPAKeyGenerator(TestCase):
503
504 for archive in archives:
505 self._fixArchiveForKeyGeneration(archive)
506- self.assertTrue(archive.signing_key is None)
507+ self.assertIsNone(archive.signing_key_fingerprint)
508
509 txn = FakeTransaction()
510 key_generator = self._getKeyGenerator(txn=txn)
511 key_generator.main()
512
513 for archive in archives:
514- self.assertTrue(archive.signing_key is not None)
515+ self.assertIsNotNone(archive.signing_key_fingerprint)
516
517 self.assertEqual(txn.commit_count, len(archives))
518diff --git a/lib/lp/soyuz/tests/test_archive.py b/lib/lp/soyuz/tests/test_archive.py
519index 91acf53..5c3f3b6 100644
520--- a/lib/lp/soyuz/tests/test_archive.py
521+++ b/lib/lp/soyuz/tests/test_archive.py
522@@ -4046,7 +4046,7 @@ class TestSigningKeyPropagation(TestCaseWithFactory):
523
524 def test_ppa_created_with_no_signing_key(self):
525 ppa = self.factory.makeArchive(purpose=ArchivePurpose.PPA)
526- self.assertIsNone(ppa.signing_key)
527+ self.assertIsNone(ppa.signing_key_fingerprint)
528
529 def test_default_signing_key_propagated_to_new_ppa(self):
530 person = self.factory.makePerson()

Subscribers

People subscribed via source and target branches

to status/vote changes: