openSUSE:Build Service Signer
The openSUSE Build Service supports the signing of RPM and DEB packages with a GPG key. This is relatively automated; however, the setting up of the signer can be long and complicated, as well as expose some unwanted information. You'll want to make sure that this is set up on a locked down server.
You will need:
- the obs-signd package from the openSUSE:Tools repository
- a gpg2 package with the files-are-digests.patch applied
The obs-signd package (starting at about version 2.1.12) has a dependency on the virtual requirement gpg2_signd_support, which in turn is complementarily provided an appropriate gpg2 package.
openSUSE (starting from 11.3, and newer) ships gpg2 with gpg2_signd_support. For other distributions, a patch is needed for GPG.
Note that Gnupg 2.2 has new upstream functionality that will make this patch obsolete, but obs-signer needs to be updated to make use of it.
Set up the GPG key
You will need to su-to-root and use gpg to create a master key with multiple encryption and signing types as follows:
$ gpg --gen-key Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? 1 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) 2048 Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 5y Key expires at Tue Aug 4 12:15:28 2015 CEST Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: My Build Service Email address: obsrun@localhost Comment: You selected this USER-ID: "My Build Service <obsrun@localhost>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o You need a Passphrase to protect your secret key. (Passphrase dialog.) gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u gpg: next trustdb check due at 2015-08-04 pub 2048R/F86E2EDC 2010-08-05 [expires: 2015-08-04] Key fingerprint = E020 2A9C 1D89 662C A354 FB37 87DD A101 F86E 2EDC uid My Build Service <obsrun@localhost> sub 2048R/D849EAAB 2010-08-05 [expires: 2015-08-04]
Because it is possible for packages to get signed with DSA, you should also add a DSA subkey:
$ gpg --edit F86E2EDC gpg (GnuPG) 2.0.12; Copyright (C) 2009 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Secret key is available. pub 2048R/F86E2EDC created: 2010-08-05 expires: 2015-08-04 usage: SC trust: ultimate validity: ultimate sub 2048R/D849EAAB created: 2010-08-05 expires: 2015-08-04 usage: E [ultimate] (1). My Build Service <obsrun@localhost> Command> addkey (Passphrase dialog.) Please select what kind of key you want: (3) DSA (sign only) (4) RSA (sign only) (5) Elgamal (encrypt only) (6) RSA (encrypt only) Your selection? 3 DSA keys may be between 1024 and 3072 bits long. What keysize do you want? (2048) 2048 Requested keysize is 2048 bits Please specify how long the key should be valid. 0 = key does not expire <n> = key expires in n days <n>w = key expires in n weeks <n>m = key expires in n months <n>y = key expires in n years Key is valid for? (0) 2015-08-04
Instead of the mnemonic "5y", pick the actual date of the master key so that the subkeys expire at approximately the same time.
Some programs[which?] cannot handle DSA 2048, so if you are actually affected, you may want to limit yourself to a 1024 bit-DSA key instead.
Key expires at Mon Aug 24 11:59:24 2015 CEST Is this correct? (y/N) y Really create? (y/N) y pub 2048R/F86E2EDC created: 2010-08-05 expires: 2015-08-04 usage: SC trust: ultimate validity: ultimate sub 2048R/D849EAAB created: 2010-08-05 expires: 2015-08-04 usage: E sub 2048D/D5C8DB1B created: 2010-08-05 expires: 2015-08-24 usage: S [ultimate] (1). My Build Service <obsrun@localhost>
Repeat the addkey step and pick Elgamal this time. (Make sure you have Elgamal 2048 bits[why?].) Eventually, you will have all the possible schemes available in a single key:
pub 2048R/F86E2EDC created: 2010-08-05 expires: 2015-08-04 usage: SC trust: ultimate validity: ultimate sub 2048R/D849EAAB created: 2010-08-05 expires: 2015-08-04 usage: E sub 2048D/D5C8DB1B created: 2010-08-05 expires: 2015-08-24 usage: S sub 2048g/D4A6E8F1 created: 2010-08-05 expires: 2015-08-24 usage: E [ultimate] (1). My Build Service <obsrun@localhost>
Prep the signer
You need to create a directory, /root/.phrases.
Create a file in there, named after the email of the GPG key, that is, obsrun@localhost in our example. The content of the file should be the passcode of your key, without any trailing newline.
Now, run the following command:
For some reason, sign will look for the key in both /root and /. They must be in both places.
Configure the signer
Export the key first so that OBS can use it...
gpg --armor --export F86E2EDC > /etc/ourkeyfile.asc
Change to the following:
our $gpg_standard_key = "<location of the keyfile>"; # The above should be something like "/etc/keyfile.asc". our $sign = '/usr/bin/sign'; # Extend sign call with project name as argument "--project $NAME" our $sign_project = 0; # Global sign key our $keyfile = '<location of the keyfile>'; # Create a key by default for new projects, if top level have not one our $forceprojectkeys = 1;
The keyfile should be the your created key, exported to .asc format. By uncommenting $sign, the Build Server knows to use the signer.
Now, edit /etc/sign.conf to display this:
user: obsrun@localhost allowuser: obsrun allow: 127.0.0.1 phrases: /root/.phrases
This allows sign to use the key.
If you run a version older than obs-signd-2.1.2 where /etc/permissions.d/sign is missing, create this file and add to it:
/usr/bin/sign root:obsrun 4750
SuSEconfig --module permissions after having created this file.
Activate the Signer
insserv obssignd obssigner rcobssignd start rcobssigner start
And have a lot of fun!
Signing EFI binaries/kernel modules for EFI Secure Boot
OBS can sign and repack RPM or Debian packages that contain EFI binaries or kernel modules for Secure Boot.
Detached signer machine
Any OBS admin with root can access the master gpg private key, and thus decrypt and access every project private signing key. If this is undesirable, a separate machine can be added to the same LAN and can be further restricted and used as a remote signer. It is recommended to follow all best practices for mission critical machines (bare metal, encrypted disk, ssh access only via public key, strict firewall rules, back-to-back network connection with main OBS instance, etc).
The only software to install is the obs-signd package. Follow the above instructions to generate a GPG master key, but then in /etc/sign.conf instead of 127.0.0.1 set the main OBS instance IP address in the "allow" field. At the same time, on the main OBS instance in the same file, use the signer machine instead of 127.0.0.1 in the "server" field. The default TCP port used by signer/signd is 5167.
$sign_project causes the signer to be called with an extra
--project $projectname argument. This is meant for sign implementations other than obs-sign which may do their own key management.<ref>http://lists.opensuse.org/opensuse-buildservice/2010-08/msg00035.html</ref>
No global key
$keyfile in BSConfig.pm empty/commented out will cause packages in a project that has no signkey available to remain stuck in the "signing" state until signing can be performed.
No secret key found and GNUPGHOME
The /etc/init.d/obssignd from obs-signd-2.1.2-1.1 rpm package sets the GNUPGHOME to /obs/gnupg before starting signd daemon. If you followed the above instructions, your GNUPGHOME will be /root/.gnupg.
One solution is to copy the /root/.gnupg to /obs/gnupg , or use symlinks. Another would be to edit /etc/sysconfig/signd to set up the GNUPGHOME (look at /var/adm/fillup-templates/sysconfig.signd).
No OpenSSL certificate at build/sign time
OBS will create and make available an OpenSSl certificate for EFI signing only if there is a per-project key available (or in the parent). In case the global master key is used directly, this will not be possible. Create a project key with osc signkey --create $project.
Project keys creation and storage details
This paragraph attempts to document how signd works under the hood when signing a project.
Upon the first signing request on a new project, if a project or any of its parents do not have a key, the backend will ask signd to create a new keypair and an SSL certificate. They are stored in the DB.
The keypair is also stored on the filesystem, under $projectsdir/$projectid.pkg as _pubkey, a GPG ASCII format public key, and _signkey, a GPG binary format secret key encrypted with the signer's GPG public key (the one created by the instructions on this page) and stored as an ASCII hex string.
On each signature request, the backend will send the files/data to be signed to signd together with the project's public key and encrypted private key. So, only the signer machine and those with access to it are able to access the private key of a project.