launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #20059
[Merge] lp:~wgrant/launchpad/gpgkey-fks into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/gpgkey-fks into lp:launchpad with lp:~wgrant/launchpad/gpgkey-fks-db as a prerequisite.
Commit message:
Set GPGKey FK replacement columns and add garbo jobs to backfill.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/gpgkey-fks/+merge/287710
Set GPGKey FK replacement columns and add garbo jobs to backfill.
Using a Storm validator would be lovely, but construction gets angry when an incomplete object is flushed.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/gpgkey-fks into lp:launchpad.
=== modified file 'database/schema/security.cfg'
--- database/schema/security.cfg 2016-03-02 21:21:26 +0000
+++ database/schema/security.cfg 2016-03-03 18:43:25 +0000
@@ -2277,6 +2277,7 @@
public.accesspolicygrant = SELECT, DELETE
public.account = SELECT, DELETE
public.answercontact = SELECT, DELETE
+public.archive = SELECT, UPDATE
public.branch = SELECT, UPDATE
public.branchjob = SELECT, DELETE
public.binarypackagename = SELECT
@@ -2318,6 +2319,7 @@
public.milestonetag = SELECT
public.openidconsumerassociation = SELECT, DELETE
public.openidconsumernonce = SELECT, DELETE
+public.packageupload = SELECT, UPDATE
public.person = SELECT, DELETE
public.personsettings = SELECT, UPDATE
public.product = SELECT, UPDATE
@@ -2327,9 +2329,10 @@
public.previewdiff = SELECT, DELETE
public.revisionauthor = SELECT, UPDATE
public.revisioncache = SELECT, DELETE
+public.signedcodeofconduct = SELECT, UPDATE
public.snapfile = SELECT, DELETE
public.sourcepackagename = SELECT
-public.sourcepackagerelease = SELECT
+public.sourcepackagerelease = SELECT, UPDATE
public.sourcepackagepublishinghistory = SELECT, UPDATE
public.suggestivepotemplate = INSERT, DELETE
public.teammembership = SELECT, DELETE
=== modified file 'lib/lp/archivepublisher/archivesigningkey.py'
--- lib/lp/archivepublisher/archivesigningkey.py 2015-09-13 18:30:51 +0000
+++ lib/lp/archivepublisher/archivesigningkey.py 2016-03-03 18:43:25 +0000
@@ -70,7 +70,10 @@
if self.archive != default_ppa:
if default_ppa.signing_key is None:
IArchiveSigningKey(default_ppa).generateSigningKey()
- self.archive.signing_key = default_ppa.signing_key
+ key = default_ppa.signing_key
+ self.archive.signing_key = key
+ self.archive.signing_key_owner = key.owner
+ self.archive._signing_key_fingerprint = key.fingerprint
return
key_displayname = (
@@ -105,9 +108,12 @@
algorithm = GPGKeyAlgorithm.items[pub_key.algorithm]
key_owner = getUtility(ILaunchpadCelebrities).ppa_key_guard
- self.archive.signing_key = getUtility(IGPGKeySet).new(
+ key = getUtility(IGPGKeySet).new(
key_owner, pub_key.keyid, pub_key.fingerprint, pub_key.keysize,
algorithm, active=True, can_encrypt=pub_key.can_encrypt)
+ self.archive.signing_key = key
+ self.archive.signing_key_owner = key.owner
+ self.archive._signing_key_fingerprint = key.fingerprint
def signRepository(self, suite):
"""See `IArchiveSigningKey`."""
=== modified file 'lib/lp/registry/model/codeofconduct.py'
--- lib/lp/registry/model/codeofconduct.py 2015-07-10 15:31:28 +0000
+++ lib/lp/registry/model/codeofconduct.py 2016-03-03 18:43:25 +0000
@@ -19,6 +19,7 @@
ForeignKey,
StringCol,
)
+from storm.properties import Unicode
from zope.component import getUtility
from zope.interface import implementer
@@ -181,6 +182,7 @@
signingkey = ForeignKey(foreignKey="GPGKey", dbName="signingkey",
notNull=False, default=None)
+ signing_key_fingerprint = Unicode()
datecreated = UtcDateTimeCol(dbName='datecreated', notNull=True,
default=UTC_NOW)
@@ -305,8 +307,10 @@
'space differences are acceptable).')
# Store the signature
- signed = SignedCodeOfConduct(owner=user, signingkey=gpg,
- signedcode=signedcode, active=True)
+ signed = SignedCodeOfConduct(
+ owner=user, signingkey=gpg,
+ signing_key_fingerprint=gpg.fingerprint if gpg else None,
+ signedcode=signedcode, active=True)
# Send Advertisement Email
subject = 'Your Code of Conduct signature has been acknowledged'
=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py 2016-02-05 20:28:29 +0000
+++ lib/lp/registry/model/distroseries.py 2016-03-03 18:43:25 +0000
@@ -1164,8 +1164,11 @@
architecturehintlist=architecturehintlist, component=component,
creator=creator, urgency=urgency, changelog=changelog,
changelog_entry=changelog_entry, dsc=dsc,
- dscsigningkey=dscsigningkey, section=section, copyright=copyright,
- upload_archive=archive,
+ dscsigningkey=dscsigningkey,
+ signing_key_owner=dscsigningkey.owner if dscsigningkey else None,
+ signing_key_fingerprint=(
+ dscsigningkey.fingerprint if dscsigningkey else None),
+ section=section, copyright=copyright, upload_archive=archive,
dsc_maintainer_rfc822=dsc_maintainer_rfc822,
dsc_standards_version=dsc_standards_version,
dsc_format=dsc_format, dsc_binaries=dsc_binaries,
@@ -1350,7 +1353,11 @@
return PackageUpload(
distroseries=self, status=PackageUploadStatus.NEW,
pocket=pocket, archive=archive, changesfile=changes_file_alias,
- signing_key=signing_key, package_copy_job=package_copy_job)
+ signing_key=signing_key,
+ signing_key_owner=signing_key.owner if signing_key else None,
+ signing_key_fingerprint=(
+ signing_key.fingerprint if signing_key else None),
+ package_copy_job=package_copy_job)
def getPackageUploadQueue(self, state):
"""See `IDistroSeries`."""
=== modified file 'lib/lp/scripts/garbo.py'
--- lib/lp/scripts/garbo.py 2016-02-05 17:18:57 +0000
+++ lib/lp/scripts/garbo.py 2016-03-03 18:43:25 +0000
@@ -69,6 +69,7 @@
RevisionCache,
)
from lp.hardwaredb.model.hwdb import HWSubmission
+from lp.registry.model.codeofconduct import SignedCodeOfConduct
from lp.registry.model.commercialsubscription import CommercialSubscription
from lp.registry.model.person import (
Person,
@@ -124,6 +125,7 @@
from lp.soyuz.model.archive import Archive
from lp.soyuz.model.livefsbuild import LiveFSFile
from lp.soyuz.model.publishing import SourcePackagePublishingHistory
+from lp.soyuz.model.queue import PackageUpload
from lp.soyuz.model.reporting import LatestPersonSourcePackageReleaseCache
from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
from lp.translations.interfaces.potemplate import IPOTemplateSet
@@ -1461,6 +1463,78 @@
transaction.commit()
+class BaseKeyMigrator(TunableLoop):
+
+ maximum_chunk_size = 5000
+
+ def __init__(self, log, abort_time=None):
+ super(BaseKeyMigrator, self).__init__(
+ log, abort_time)
+ state = load_garbo_job_state(self.__class__.__name__) or {}
+ self.start_at = state.get('next_id', 1)
+ self.store = IMasterStore(self.klass)
+
+ def findObjects(self):
+ return self.store.find(
+ self.klass,
+ self.klass.id >= self.start_at).order_by(
+ self.klass.id)
+
+ def isDone(self):
+ return (
+ not getFeatureFlag('gpg.migrator.%s' % self.klass.__name__)
+ or self.findObjects().is_empty())
+
+ def __call__(self, chunk_size):
+ objs = list(self.findObjects()[:chunk_size])
+ for obj in objs:
+ key = getattr(obj, self.fk_attr, None)
+ if self.fingerprint_attr:
+ setattr(
+ obj, self.fingerprint_attr,
+ key.fingerprint if key else None)
+ if self.owner_attr:
+ setattr(
+ obj, self.owner_attr,
+ key.owner if key else None)
+ self.start_at = objs[-1].id + 1
+ save_garbo_job_state(
+ self.__class__.__name__, {'next_id': self.start_at})
+ transaction.commit()
+
+
+class ArchiveKeyMigrator(BaseKeyMigrator):
+
+ klass = Archive
+ fk_attr = 'signing_key'
+ fingerprint_attr = '_signing_key_fingerprint'
+ owner_attr = 'signing_key_owner'
+
+
+class PackageUploadKeyMigrator(BaseKeyMigrator):
+
+ klass = PackageUpload
+ fk_attr = 'signing_key'
+ fingerprint_attr = 'signing_key_fingerprint'
+ owner_attr = 'signing_key_owner'
+
+
+class SignedCodeOfConductKeyMigrator(BaseKeyMigrator):
+
+ klass = SignedCodeOfConduct
+ fk_attr = 'signingkey'
+ fingerprint_attr = 'signing_key_fingerprint'
+ owner_attr = None
+
+
+class SourcePackageReleaseKeyMigrator(BaseKeyMigrator):
+
+ klass = SourcePackageRelease
+ fk_attr = 'dscsigningkey'
+ fingerprint_attr = 'signing_key_fingerprint'
+ owner_attr = 'signing_key_owner'
+
+
class BaseDatabaseGarbageCollector(LaunchpadCronScript):
"""Abstract base class to run a collection of TunableLoops."""
script_name = None # Script name for locking and database user. Override.
@@ -1709,10 +1783,14 @@
"""
script_name = 'garbo-hourly'
tunable_loops = [
+ ArchiveKeyMigrator,
BugHeatUpdater,
BugWatchScheduler,
DuplicateSessionPruner,
+ PackageUploadKeyMigrator,
RevisionCachePruner,
+ SignedCodeOfConductKeyMigrator,
+ SourcePackageReleaseKeyMigrator,
UnusedSessionPruner,
]
experimental_tunable_loops = []
=== modified file 'lib/lp/scripts/tests/test_garbo.py'
--- lib/lp/scripts/tests/test_garbo.py 2016-02-06 02:55:51 +0000
+++ lib/lp/scripts/tests/test_garbo.py 2016-03-03 18:43:25 +0000
@@ -73,6 +73,7 @@
from lp.registry.interfaces.accesspolicy import IAccessPolicySource
from lp.registry.interfaces.person import IPersonSet
from lp.registry.interfaces.teammembership import TeamMembershipStatus
+from lp.registry.model.codeofconduct import SignedCodeOfConduct
from lp.registry.model.commercialsubscription import CommercialSubscription
from lp.registry.model.person import PersonSettings
from lp.registry.model.teammembership import TeamMembership
@@ -128,7 +129,10 @@
TestCase,
TestCaseWithFactory,
)
-from lp.testing.dbuser import switch_dbuser
+from lp.testing.dbuser import (
+ dbuser,
+ switch_dbuser,
+ )
from lp.testing.layers import (
DatabaseLayer,
LaunchpadScriptLayer,
@@ -1390,6 +1394,67 @@
self._test_LiveFSFilePruner(
'application/octet-stream', 0, expected_count=1)
+ def test_ArchiveKeyMigrator(self):
+ with dbuser('testadmin'):
+ key = self.factory.makeGPGKey(self.factory.makePerson())
+ a1 = self.factory.makeArchive()
+ a2 = self.factory.makeArchive()
+ removeSecurityProxy(a2).signing_key = key
+ self.assertIs(None, a1._signing_key_fingerprint)
+ self.assertIs(None, a1.signing_key_owner)
+ self.assertIs(None, a2._signing_key_fingerprint)
+ self.assertIs(None, a2.signing_key_owner)
+ with FeatureFixture({'gpg.migrator.Archive': 'on'}):
+ self.runHourly()
+ self.assertIs(None, a1._signing_key_fingerprint)
+ self.assertIs(None, a1.signing_key_owner)
+ self.assertEqual(key.fingerprint, a2._signing_key_fingerprint)
+ self.assertEqual(key.owner, a2.signing_key_owner)
+
+ def test_PackageUploadKeyMigrator(self):
+ with dbuser('testadmin'):
+ key = self.factory.makeGPGKey(self.factory.makePerson())
+ pu1 = self.factory.makePackageUpload()
+ pu2 = self.factory.makePackageUpload(signing_key=key)
+ npu2 = removeSecurityProxy(pu2)
+ npu2.signing_key_fingerprint = npu2.signing_key_owner = None
+ self.assertIs(None, pu1.signing_key_fingerprint)
+ self.assertIs(None, pu1.signing_key_owner)
+ self.assertIs(None, pu2.signing_key_fingerprint)
+ self.assertIs(None, pu2.signing_key_owner)
+ with FeatureFixture({'gpg.migrator.PackageUpload': 'on'}):
+ self.runHourly()
+ self.assertIs(None, pu1.signing_key_fingerprint)
+ self.assertIs(None, pu1.signing_key_owner)
+ self.assertEqual(key.fingerprint, pu2.signing_key_fingerprint)
+ self.assertEqual(key.owner, pu2.signing_key_owner)
+
+ def test_SignedCodeOfConductKeyMigrator(self):
+ coc = SignedCodeOfConduct.get(1)
+ self.assertIs(None, coc.signing_key_fingerprint)
+ with FeatureFixture({'gpg.migrator.SignedCodeOfConduct': 'on'}):
+ self.runHourly()
+ self.assertEqual(
+ 'ABCDEF0123456789ABCDDCBA0000111112345678',
+ coc.signing_key_fingerprint)
+
+ def test_SourcePackageReleaseKeyMigrator(self):
+ with dbuser('testadmin'):
+ key = self.factory.makeGPGKey(self.factory.makePerson())
+ spr1 = self.factory.makeSourcePackageRelease()
+ spr2 = self.factory.makeSourcePackageRelease()
+ removeSecurityProxy(spr2).dscsigningkey = key
+ self.assertIs(None, spr1.signing_key_fingerprint)
+ self.assertIs(None, spr1.signing_key_owner)
+ self.assertIs(None, spr2.signing_key_fingerprint)
+ self.assertIs(None, spr2.signing_key_owner)
+ with FeatureFixture({'gpg.migrator.SourcePackageRelease': 'on'}):
+ self.runHourly()
+ self.assertIs(None, spr1.signing_key_fingerprint)
+ self.assertIs(None, spr1.signing_key_owner)
+ self.assertEqual(key.fingerprint, spr2.signing_key_fingerprint)
+ self.assertEqual(key.owner, spr2.signing_key_owner)
+
def test_PersonSettingsENFPopulator(self):
switch_dbuser('testadmin')
store = IMasterStore(PersonSettings)
=== modified file 'lib/lp/soyuz/configure.zcml'
--- lib/lp/soyuz/configure.zcml 2016-01-08 14:35:52 +0000
+++ lib/lp/soyuz/configure.zcml 2016-03-03 18:43:25 +0000
@@ -75,6 +75,7 @@
class="lp.soyuz.model.sourcepackagerelease.SourcePackageRelease">
<allow
interface="lp.soyuz.interfaces.sourcepackagerelease.ISourcePackageRelease"/>
+ <allow attributes="signing_key_fingerprint signing_key_owner" />
<!-- changelog needs to be updated when unembargoing -->
<require
permission="launchpad.Edit"
@@ -143,6 +144,8 @@
changesfile
changes_file_url
signing_key
+ signing_key_fingerprint
+ signing_key_owner
archive
sources
sourceFileUrls
@@ -386,7 +389,9 @@
set_schema="lp.soyuz.interfaces.archive.IArchiveRestricted"/>
<require
permission="launchpad.InternalScriptsOnly"
- set_attributes="distribution signing_key"/>
+ attributes="signing_key_owner _signing_key_fingerprint"
+ set_attributes="distribution signing_key signing_key_owner
+ _signing_key_fingerprint"/>
</class>
<adapter
for="lp.soyuz.interfaces.archive.IArchive"
=== modified file 'lib/lp/soyuz/model/archive.py'
--- lib/lp/soyuz/model/archive.py 2015-11-26 15:46:38 +0000
+++ lib/lp/soyuz/model/archive.py 2016-03-03 18:43:25 +0000
@@ -23,21 +23,22 @@
IntCol,
StringCol,
)
+from storm.base import Storm
from storm.expr import (
And,
+ Count,
Desc,
+ Join,
Not,
Or,
Select,
Sum,
)
-from storm.locals import (
- Count,
+from storm.properties import (
Int,
- Join,
- Reference,
- Storm,
+ Unicode,
)
+from storm.references import Reference
from storm.store import Store
from zope.component import (
getAdapter,
@@ -339,6 +340,9 @@
signing_key = ForeignKey(
foreignKey='GPGKey', dbName='signing_key', notNull=False)
+ signing_key_owner_id = Int(name="signing_key_owner")
+ signing_key_owner = Reference(signing_key_owner_id, 'Person.id')
+ _signing_key_fingerprint = Unicode(name="signing_key_fingerprint")
relative_build_score = IntCol(
dbName='relative_build_score', notNull=True, default=0)
@@ -2534,6 +2538,9 @@
owner=owner, distribution=distribution, name=name,
displayname=displayname, description=description,
purpose=purpose, publish=publish, signing_key=signing_key,
+ signing_key_owner=signing_key.owner if signing_key else None,
+ _signing_key_fingerprint=(
+ signing_key.fingerprint if signing_key else None),
require_virtualized=require_virtualized)
# Upon creation archives are enabled by default.
=== modified file 'lib/lp/soyuz/model/queue.py'
--- lib/lp/soyuz/model/queue.py 2016-02-05 16:51:12 +0000
+++ lib/lp/soyuz/model/queue.py 2016-03-03 18:43:25 +0000
@@ -186,6 +186,9 @@
signing_key = ForeignKey(
foreignKey='GPGKey', dbName='signing_key', notNull=False)
+ signing_key_owner_id = Int(name="signing_key_owner")
+ signing_key_owner = Reference(signing_key_owner_id, 'Person.id')
+ signing_key_fingerprint = Unicode()
package_copy_job_id = Int(name='package_copy_job', allow_none=True)
package_copy_job = Reference(package_copy_job_id, 'PackageCopyJob.id')
=== modified file 'lib/lp/soyuz/model/sourcepackagerelease.py'
--- lib/lp/soyuz/model/sourcepackagerelease.py 2016-02-05 15:16:29 +0000
+++ lib/lp/soyuz/model/sourcepackagerelease.py 2016-03-03 18:43:25 +0000
@@ -30,6 +30,7 @@
Desc,
Int,
Reference,
+ Unicode,
)
from storm.store import Store
from zope.component import getUtility
@@ -89,6 +90,9 @@
dbName='maintainer', foreignKey='Person',
storm_validator=validate_public_person, notNull=True)
dscsigningkey = ForeignKey(foreignKey='GPGKey', dbName='dscsigningkey')
+ signing_key_owner_id = Int(name="signing_key_owner")
+ signing_key_owner = Reference(signing_key_owner_id, 'Person.id')
+ signing_key_fingerprint = Unicode()
urgency = EnumCol(dbName='urgency', schema=SourcePackageUrgency,
default=SourcePackageUrgency.LOW, notNull=True)
dateuploaded = UtcDateTimeCol(dbName='dateuploaded', notNull=True,
=== modified file 'lib/lp/soyuz/scripts/gina/handlers.py'
--- lib/lp/soyuz/scripts/gina/handlers.py 2015-05-20 11:31:11 +0000
+++ lib/lp/soyuz/scripts/gina/handlers.py 2016-03-03 18:43:25 +0000
@@ -616,6 +616,8 @@
sourcepackagename=name.id,
maintainer=maintainer.id,
dscsigningkey=key,
+ signing_key_owner=key.owner if key else None,
+ signing_key_fingerprint=key.fingerprint if key else None,
urgency=ChangesFile.urgency_map[src.urgency],
dateuploaded=src.date_uploaded,
dsc=src.dsc,
Follow ups