Launchpad entry: https://blueprints.edge.launchpad.net/soyuz/+spec/signed-archives
Created: [2008-07-17] by JulianEdwards
Depends on: n/a
Summary: PPA repositories will be signed in the same way that the Ubuntu one is. Signing keys will be generated and stored in Launchpad, and can optionally be signed by the archive's owner.
Goal/Deliverables: We'll deliver a UI that will allow a user to manage private keys for an archive, and published archives will be signed with the key registered for that archive.
We will know we have finished when PPA Release files get signed after each modification.
2.1.12 rollout will automatically create GPG signing keys for every non-empty PPA and subsequent repository modification (upload or rebuild) will result in a signed Release file for the affected suite.
Despite serving archive contents via a secure protocol (HTTPS) we are not able to certify that the content being transported is what the user believes it is (the certified origin).
APT already uses OpenPGP signatures before installing anything from a specific archive.
Soyuz should be able to sign archive Release files, per-owner request, when they want to distribute certified packages.
Why per-PPA keys?
Consider the following scenario if we were to use a site-wide ppa.launchpad.net key:
- Bob produces a shiny new lolcats-backgrounds package and uploads it to his Launchpad PPA
- Alice loves lolcats, and adds his PPA to her sources.list.
- This pulls in the ppa.launchpad.net key as an authorized key
- Evil Eve uploads a newer, trojan-ed, lolcats-backgrounds to her Launchpad PPA
- Evil Eve MITMs Alice (e.g. via Kamnisky DNS poisoning) and redirects Alice's traffic from ppa.launchpad.net to harhar.evileve.com which contains a mirror of her PPA
- Alice's apt thinks it's downloading from ppa.launchpad.net/~bob-ppa
- The repository being served by Evil Eve has been signed by LP and is thus trusted by Alice's apt
-> profit for Evil Eve, loss for Alice and Bob
- Arthur has a Launchpad PPA and wants to allow his users to verify if they are really installing packages provided by him.
- Ford uses Arthur's PPA and would be less concerned on each update if he could verify if the packages being installed are the ones provided by Arthur.
Users are happy to have a private key kept on their behalf;
It will be mandatory to have signing-keys set for PPAs.
There is no need to model the existence of a corresponding private part of a GPG key in LP, it will be implicit in the fact that a GpgKey record is set as signing-key for any archive.
Revoking launchpad-generated keys will be considered a crisis/corner-case and will be handled on demand since it will be only necessary if the PPA machine gets compromised.
Users will manifest their trust in lp-generated keys by signing its corresponding public part already published in the global keyring. That will be done externally, using the current gpg infrastructure, i.e. doesn't require any LP support.
The signing GPG key pair will be generated sometime after the PPA activation. Since they are mandatory nothing will change in this form, apart of a clear indication of what will be done.
Of course there will be a minor change in the PPA index page pointing users to the public part of the key used to sign it and also instructions about how users/clients should use it.
We will assume LP environment is secure enough (specially germanium, the PPA machine) and generate the keys directly on disk (associated with more secure and reliable backups). The private key will be retrieved from disk on-the-fly, based on the fingerprint of the public part when a signature is required. Later we can migrate them to a distributed location using the appropriate security artifacts (KEK).
A key generation will be triggered by the fact that there are Archive WHERE purpose=PPA AND enabled=true AND sigining_key is NULL, ppa-generate-key.py will perform the following actions for each missing-signing-key:
- Generate a key pair, export the private key into a file in the private-key-path;
- The signing key UID will be "Launchpad %(ppa.title)s" as in "Launchpad PPA for Celso Providelo"
- Export and upload the public part to the keyserver;
Record the pub part existence in the GpgKey table;
- Record the just created Archive.sigining_key existence.
publish-distro will cope fine with archives with unset signing-keys and skip the release file signature until it gets generated.
- Schema - 1 hour, plus discussions
- GPGHandler changes to generate, sign and upload keys - 4 days.
gpgkey-guard and signing release files - 2 days
- UI - 1 day
- GPGHandler changes:
IGPGHandler.generateKey(comment='Signing key for <archive.title>', can_encrypt=False)
- IGPGHandler.signContent(content, fingerprint, detached=False)
- key pair generation for all PPAs missing signing-keys;
- key pair generation for a specific PPA;
- Signing archives with generated signing-keys;
- +archive/+index: pointer to the signing key and instructions about how to use it;
- ~ppa-key-guard/+editpgpkeys: lists all signing-keys created (requires administrative rights);
Archive: simply adding a 'nullable' signing_key FK to GpgKey.
The first time ppa-generate-keys.py runs in production it will generate keys for all existing PPA, and subsequent runs will catch up with new PPA activations.
Will Archive.signing_key have to be nullable forever, not only for the migration period ?
CelsoProvidelo: There are other Archives that don't have to be signed (REBUILDS for instance). After the migration time we can add a NOT NULL constraint WHERE purpose = PPA if it contribute for safety.
Should Archive.signing_key not be UNIQUE in order to allow sharing the same key across archives (not necessarily PPAs) ?
CelsoProvidelo: It may be necessary, if we decide to host signing-keys for PRIMARY & PARTNER archives as well. Unless we are absolutely sure that each signed archive should have its exclusive key.