launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #31247
[Merge] ~lgp171188/launchpad:serve-rsa4096-when-archive-also-has-rsa1024-key into launchpad:master
Guruprasad has proposed merging ~lgp171188/launchpad:serve-rsa4096-when-archive-also-has-rsa1024-key into launchpad:master.
Commit message:
Add a garbo job to switch the served signing key fingerprint of PPAs
When a PPA has an rsa1024 signing key and rsa4096 signing key, this job
will update `IArchive.signing_key_fingerprint` to point to the latter,
thereby making the default more secure.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~lgp171188/launchpad/+git/launchpad/+merge/470160
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~lgp171188/launchpad:serve-rsa4096-when-archive-also-has-rsa1024-key into launchpad:master.
diff --git a/lib/lp/scripts/garbo.py b/lib/lp/scripts/garbo.py
index d4fa136..63bc5b7 100644
--- a/lib/lp/scripts/garbo.py
+++ b/lib/lp/scripts/garbo.py
@@ -67,6 +67,7 @@ from lp.code.model.revisionstatus import RevisionStatusArtifact
from lp.oci.model.ocirecipebuild import OCIFile
from lp.registry.interfaces.person import IPersonSet
from lp.registry.model.distribution import Distribution
+from lp.registry.model.gpgkey import GPGKey
from lp.registry.model.person import Person
from lp.registry.model.product import Product
from lp.registry.model.sourcepackagename import SourcePackageName
@@ -112,6 +113,7 @@ from lp.services.scripts.base import (
SilentLaunchpadScriptFailure,
)
from lp.services.session.model import SessionData
+from lp.services.signing.interfaces.signingkey import IArchiveSigningKeySet
from lp.services.verification.model.logintoken import LoginToken
from lp.services.webapp.publisher import canonical_url
from lp.services.webhooks.interfaces import IWebhookJobSource
@@ -120,6 +122,7 @@ from lp.snappy.model.snapbuild import SnapFile
from lp.snappy.model.snapbuildjob import SnapBuildJobType
from lp.soyuz.enums import (
ArchivePublishingMethod,
+ ArchivePurpose,
ArchiveRepositoryFormat,
ArchiveSubscriberStatus,
)
@@ -2259,6 +2262,53 @@ class ArchiveFileDatePopulator(TunableLoop):
transaction.commit()
+class UpdatePPASigningKeyFingerprintToRSA4096Key(TunableLoop):
+ """
+ Update the signing key fingerprint of archives with an rsa1024
+ signing key and an rsa4096 signing key to be the fingerprint of
+ the rsa4096 signing key.
+ """
+
+ maximum_chunk_size = 1000
+
+ def __init__(self, log, abort_time=None):
+ super().__init__(log, abort_time)
+ self.store = IPrimaryStore(Archive)
+ self.start_at = 1
+
+ def findAffectedArchives(self):
+ join = (
+ Archive,
+ Join(
+ GPGKey,
+ GPGKey.fingerprint == Archive.signing_key_fingerprint,
+ ),
+ )
+ return (
+ self.store.using(*join)
+ .find(
+ Archive,
+ Archive.purpose == ArchivePurpose.PPA,
+ GPGKey.keysize == 1024,
+ )
+ .order_by(Archive.id)
+ )
+
+ def updateSigningKeyFingerprint(self, archive):
+ archive_signing_key_set = getUtility(IArchiveSigningKeySet)
+ rsa4096_key = archive_signing_key_set.get4096BitRSASigningKey(archive)
+ if rsa4096_key:
+ archive.signing_key_fingerprint = rsa4096_key.fingerprint
+
+ def isDone(self):
+ return self.findAffectedArchives().is_empty()
+
+ def __call__(self, chunk_size):
+ for archive in self.findAffectedArchives()[:chunk_size]:
+ self.updateSigningKeyFingerprint(archive)
+ transaction.commit()
+
+
class BaseDatabaseGarbageCollector(LaunchpadCronScript):
"""Abstract base class to run a collection of TunableLoops."""
@@ -2550,6 +2600,7 @@ class HourlyDatabaseGarbageCollector(BaseDatabaseGarbageCollector):
GitRepositoryPruner,
RevisionCachePruner,
UnusedSessionPruner,
+ UpdatePPASigningKeyFingerprintToRSA4096Key,
]
experimental_tunable_loops = []
diff --git a/lib/lp/scripts/tests/test_garbo.py b/lib/lp/scripts/tests/test_garbo.py
index a5a16e0..85563a0 100644
--- a/lib/lp/scripts/tests/test_garbo.py
+++ b/lib/lp/scripts/tests/test_garbo.py
@@ -82,6 +82,7 @@ from lp.scripts.garbo import (
ProductVCSPopulator,
UnusedPOTMsgSetPruner,
UnusedSessionPruner,
+ UpdatePPASigningKeyFingerprintToRSA4096Key,
load_garbo_job_state,
save_garbo_job_state,
)
@@ -106,6 +107,7 @@ from lp.services.messages.interfaces.message import IMessageSet
from lp.services.messages.model.message import Message
from lp.services.openid.model.openidconsumer import OpenIDConsumerNonce
from lp.services.session.model import SessionData, SessionPkgData
+from lp.services.signing.enums import SigningKeyType
from lp.services.verification.interfaces.authtoken import LoginTokenType
from lp.services.verification.model.logintoken import LoginToken
from lp.services.worlddata.interfaces.language import ILanguageSet
@@ -2584,6 +2586,41 @@ class TestGarbo(FakeAdapterMixin, TestCaseWithFactory):
self.assertEqual(1, rs.count())
self.assertEqual(archive_files[1], rs.one())
+ def test_UpdatePPASigningKeyFingerprintToRSA4096Key(self):
+ switch_dbuser("testadmin")
+ person = self.factory.makePerson()
+ archive = self.factory.makeArchive(owner=person)
+ rsa1024_gpg_key = self.factory.makeGPGKey(owner=person, keysize=1024)
+ archive.signing_key_fingerprint = rsa1024_gpg_key.fingerprint
+ rsa4096_gpg_key = self.factory.makeGPGKey(owner=person, keysize=4096)
+ rsa4096_signing_key = self.factory.makeSigningKey(
+ key_type=SigningKeyType.OPENPGP,
+ fingerprint=rsa4096_gpg_key.fingerprint,
+ )
+ self.factory.makeArchiveSigningKey(archive, None, rsa4096_signing_key)
+
+ archive_2 = self.factory.makeArchive()
+ rsa1024_gpg_key_2 = self.factory.makeGPGKey(owner=person, keysize=1024)
+ archive_2.signing_key_fingerprint = rsa1024_gpg_key_2.fingerprint
+ rsa4096_gpg_key_2 = self.factory.makeGPGKey(owner=person, keysize=4096)
+ rsa4096_signing_key_2 = self.factory.makeSigningKey(
+ key_type=SigningKeyType.OPENPGP,
+ fingerprint=rsa4096_gpg_key_2.fingerprint,
+ )
+ self.factory.makeArchiveSigningKey(
+ archive_2, None, rsa4096_signing_key_2
+ )
+ updater = UpdatePPASigningKeyFingerprintToRSA4096Key(log=None)
+ self.assertEqual(2, updater.findAffectedArchives().count())
+ self.runHourly()
+ self.assertTrue(updater.findAffectedArchives().is_empty())
+ self.assertEqual(
+ rsa4096_gpg_key.fingerprint, archive.signing_key_fingerprint
+ )
+ self.assertEqual(
+ rsa4096_gpg_key_2.fingerprint, archive_2.signing_key_fingerprint
+ )
+
class TestGarboTasks(TestCaseWithFactory):
layer = LaunchpadZopelessLayer
References