openSUSE:Build Service Signer

Jump to: navigation, search

Description

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.

Instructions

Required Packages

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.

mkdir -v /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:

ln -s /root/.gnupg /

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

Edit /usr/lib/obs/server/BSConfig.pm.

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

Run SuSEconfig --module permissions after having created this file.

Activate the Signer

Run:

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.

Check the pesign-obs-integration source code or package for details.

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.

Troubleshooting

--project

$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

Leaving $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.