Merge ~pappacena/launchpad:copy-signing-key-overwrite into launchpad:master

Proposed by Thiago F. Pappacena
Status: Merged
Approved by: Thiago F. Pappacena
Approved revision: 96b1c12c4def2771e8a8445c7d6cdd6032dc3364
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~pappacena/launchpad:copy-signing-key-overwrite
Merge into: launchpad:master
Diff against target: 141 lines (+60/-6)
4 files modified
lib/lp/archivepublisher/scripts/copy_signingkeys.py (+16/-4)
lib/lp/archivepublisher/tests/test_copy_signingkeys.py (+36/-0)
lib/lp/services/signing/interfaces/signingkey.py (+4/-1)
lib/lp/services/signing/model/signingkey.py (+4/-1)
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+400277@code.launchpad.net

Commit message

Adding --overwrite option to copy-signingkeys script

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
review: Approve
96b1c12... by Thiago F. Pappacena

Omitting short version of override option

Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Pushed requested change.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/lp/archivepublisher/scripts/copy_signingkeys.py b/lib/lp/archivepublisher/scripts/copy_signingkeys.py
index e4a46bd..322b7d9 100644
--- a/lib/lp/archivepublisher/scripts/copy_signingkeys.py
+++ b/lib/lp/archivepublisher/scripts/copy_signingkeys.py
@@ -42,6 +42,10 @@ class CopySigningKeysScript(LaunchpadScript):
42 "-n", "--dry-run", action="store_true", default=False,42 "-n", "--dry-run", action="store_true", default=False,
43 help="Report what would be done, but don't actually copy keys.")43 help="Report what would be done, but don't actually copy keys.")
4444
45 self.parser.add_option(
46 "--overwrite", action="store_true", default=False,
47 help="Overwrite existing keys when executing the copy.")
48
45 def getArchive(self, reference):49 def getArchive(self, reference):
46 archive = getUtility(IArchiveSet).getByReference(reference)50 archive = getUtility(IArchiveSet).getByReference(reference)
47 if archive is None:51 if archive is None:
@@ -78,7 +82,8 @@ class CopySigningKeysScript(LaunchpadScript):
78 self.key_types = self.getKeyTypes(self.options.key_type)82 self.key_types = self.getKeyTypes(self.options.key_type)
79 self.series = self.getSeries(self.options.series)83 self.series = self.getSeries(self.options.series)
8084
81 def copy(self, from_archive, to_archive, key_type, series=None):85 def copy(self, from_archive, to_archive, key_type, series=None,
86 overwrite=False):
82 series_name = series.name if series else None87 series_name = series.name if series else None
83 from_archive_signing_key = getUtility(IArchiveSigningKeySet).get(88 from_archive_signing_key = getUtility(IArchiveSigningKeySet).get(
84 key_type, from_archive, series, exact_match=True)89 key_type, from_archive, series, exact_match=True)
@@ -90,10 +95,17 @@ class CopySigningKeysScript(LaunchpadScript):
90 to_archive_signing_key = getUtility(IArchiveSigningKeySet).get(95 to_archive_signing_key = getUtility(IArchiveSigningKeySet).get(
91 key_type, to_archive, series, exact_match=True)96 key_type, to_archive, series, exact_match=True)
92 if to_archive_signing_key is not None:97 if to_archive_signing_key is not None:
98 if not overwrite:
99 # If it already exists and we do not force overwrite,
100 # abort this signing key copy.
101 self.logger.warning(
102 "%s signing key for %s / %s already exists",
103 key_type, to_archive.reference, series_name)
104 return
93 self.logger.warning(105 self.logger.warning(
94 "%s signing key for %s / %s already exists",106 "%s signing key for %s / %s being overwritten",
95 key_type, to_archive.reference, series_name)107 key_type, to_archive.reference, series_name)
96 return108 to_archive_signing_key.destroySelf()
97 self.logger.info(109 self.logger.info(
98 "Copying %s signing key %s from %s / %s to %s / %s",110 "Copying %s signing key %s from %s / %s to %s / %s",
99 key_type, from_archive_signing_key.signing_key.fingerprint,111 key_type, from_archive_signing_key.signing_key.fingerprint,
@@ -107,7 +119,7 @@ class CopySigningKeysScript(LaunchpadScript):
107 for key_type in self.key_types:119 for key_type in self.key_types:
108 self.copy(120 self.copy(
109 self.from_archive, self.to_archive, key_type,121 self.from_archive, self.to_archive, key_type,
110 series=self.series)122 series=self.series, overwrite=self.options.overwrite)
111 if self.options.dry_run:123 if self.options.dry_run:
112 self.logger.info("Dry run requested. Not committing changes.")124 self.logger.info("Dry run requested. Not committing changes.")
113 transaction.abort()125 transaction.abort()
diff --git a/lib/lp/archivepublisher/tests/test_copy_signingkeys.py b/lib/lp/archivepublisher/tests/test_copy_signingkeys.py
index 56862a7..f993c19 100644
--- a/lib/lp/archivepublisher/tests/test_copy_signingkeys.py
+++ b/lib/lp/archivepublisher/tests/test_copy_signingkeys.py
@@ -306,6 +306,42 @@ class TestCopySigningKeysScript(TestCaseWithFactory):
306 MatchesStructure.byEquality(306 MatchesStructure.byEquality(
307 archive=archives[1], earliest_distro_series=None,307 archive=archives[1], earliest_distro_series=None,
308 key_type=SigningKeyType.UEFI, signing_key=signing_keys[1]),308 key_type=SigningKeyType.UEFI, signing_key=signing_keys[1]),
309 ))
310
311 def test_copy_forced_overwrite(self):
312 archives = [self.factory.makeArchive() for _ in range(2)]
313 signing_keys = [
314 self.factory.makeSigningKey(key_type=SigningKeyType.UEFI)
315 for _ in range(2)]
316 for archive, signing_key in zip(archives, signing_keys):
317 self.factory.makeArchiveSigningKey(
318 archive=archive, signing_key=signing_key)
319 script = self.makeScript(
320 test_args=["--key-type", "UEFI", "--overwrite"],
321 archives=archives[:2])
322 script.main()
323
324 expected_log = [
325 "WARNING UEFI signing key for %s / None being overwritten" % (
326 archives[1].reference),
327 "INFO Copying UEFI signing key %s from %s / %s to %s / %s" % (
328 signing_keys[0].fingerprint,
329 archives[0].reference, None,
330 archives[1].reference, None),
331 ]
332 self.assertEqual(
333 expected_log, script.logger.content.as_text().splitlines())
334 self.assertThat(
335 self.findKeys(archives),
336 MatchesSetwise(
337 # First archive keeps its signing keys.
338 MatchesStructure.byEquality(
339 archive=archives[0], earliest_distro_series=None,
340 key_type=SigningKeyType.UEFI, signing_key=signing_keys[0]),
341 # Second archive uses the same signing_key from first archive.
342 MatchesStructure.byEquality(
343 archive=archives[1], earliest_distro_series=None,
344 key_type=SigningKeyType.UEFI, signing_key=signing_keys[0]),
309 ))345 ))
310346
311 def runScript(self, args=None):347 def runScript(self, args=None):
diff --git a/lib/lp/services/signing/interfaces/signingkey.py b/lib/lp/services/signing/interfaces/signingkey.py
index 8548fa8..b714d42 100644
--- a/lib/lp/services/signing/interfaces/signingkey.py
+++ b/lib/lp/services/signing/interfaces/signingkey.py
@@ -1,4 +1,4 @@
1# Copyright 2020 Canonical Ltd. This software is licensed under the1# Copyright 2020-2021 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Interfaces for signing keys stored at the signing service."""4"""Interfaces for signing keys stored at the signing service."""
@@ -126,6 +126,9 @@ class IArchiveSigningKey(Interface):
126 ISigningKey, title=_("Signing key"), required=True, readonly=True,126 ISigningKey, title=_("Signing key"), required=True, readonly=True,
127 description=_("Which signing key should be used by this archive"))127 description=_("Which signing key should be used by this archive"))
128128
129 def destroySelf():
130 """Removes the ArchiveSigningKey from the database."""
131
129132
130class IArchiveSigningKeySet(Interface):133class IArchiveSigningKeySet(Interface):
131 """Management class to deal with ArchiveSigningKey objects134 """Management class to deal with ArchiveSigningKey objects
diff --git a/lib/lp/services/signing/model/signingkey.py b/lib/lp/services/signing/model/signingkey.py
index ee77613..fdbc199 100644
--- a/lib/lp/services/signing/model/signingkey.py
+++ b/lib/lp/services/signing/model/signingkey.py
@@ -1,4 +1,4 @@
1# Copyright 2020 Canonical Ltd. This software is licensed under the1# Copyright 2020-2021 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Database classes to manage signing keys stored at the signing service."""4"""Database classes to manage signing keys stored at the signing service."""
@@ -177,6 +177,9 @@ class ArchiveSigningKey(StormBase):
177 self.key_type = signing_key.key_type177 self.key_type = signing_key.key_type
178 self.earliest_distro_series = earliest_distro_series178 self.earliest_distro_series = earliest_distro_series
179179
180 def destroySelf(self):
181 IStore(self).remove(self)
182
180183
181@implementer(IArchiveSigningKeySet)184@implementer(IArchiveSigningKeySet)
182class ArchiveSigningKeySet:185class ArchiveSigningKeySet: