RedHat Package Manager Tips

Build Setup | Public Keys | Source Packages | Rebuilding Packages | Signing Packages | Resigning Packages | Perl Modules | Python Libraries | Related

Documentation on using RedHat Package Manager (RPM) to build custom software packages. See also Maximum RPM and the Fedora Project Developer's Guide. Packages can be made available to clients via local Yellowdog Updater, Modified (YUM) servers.

Systems used to build and sign packages must not host packages. Instead, copy signed packages from build hosts to distribution servers, and require that clients verify signatures before installing. This way, an attacker who compromises a distribution host will not be able to run arbitrary software on client systems.

Also consider OpenPKG.

Build Setup

Each account used to build packages will need a ~/.rpmmacros configuration file and a build directory structure. The %_topdir statement in ~/.rpmmacros file must match the directory used. The example here uses ~/src/redhat as the parent of the build directory; use the following mkdir commands to create the required directories.

$ mkdir -p ~/src/redhat
$ cd ~/src/redhat
$ mkdir BUILD RPMS SOURCES SPECS SRPMS tmp

Use this Makefile to help setup the subdirectories, obtain sources from a YUM server, sign packages, and upload packages to the YUM server.

Useful settings for the ~/.rpmmacros configuration file include:

Public Keys

Systems used to build packages will need Pretty Good Privacy (PGP) keys imported to verify signed software. Unfortunately, not all developers sign their software, which makes it trivial for an attacker to include malicious code. If software or packages are signed with PGP, import the public keys.

$ gpg --import PGP-KEY-FILE
$ sudo rpm --import PGP-KEY-FILE

To see what keys have been registered with RPM, search for gpg-pubkey-* packages.

$ rpm -qa | grep ^gpg-pubkey
?

If software has a detatched *.sig file, verify the distribution with gpg. RPM files can be verified using rpm -K.

$ ls nmap-3.75.tar.bz2*
nmap-3.75.tar.bz2 nmap-3.75.tar.bz2.sig
$ gpg --verify nmap-3.75.tar.bz2.sig
gpg: Signature made Wed Oct 20 18:01:45 2004 PDT using RSA key ID 53587D95
gpg: Good signature from "Fyodor <fyodor@insecure.org>"
$ rpm -K nmap-3.75-1.src.rpm
nmap-3.75-1.src.rpm: (sha1) dsa sha1 md5 gpg OK

Source Packages

Source RPM files (*.src.rpm) can either be rebuilt using the rpmbuild --rebuild command, or unpacked with the rpm command.

Newly built packages must be signed before being made available for download.

Rebuilding Packages

When writing new or fixing old specification files for packages that do not take long to build, have a script check whether the specification file has changed, and if so, automatically attempt a rebuild on the package. This saves having to rerun the rpmbuild command manually after each set of changes to the specification file, and during initial development of a new *.spec file, quick feedback about problems.

Coding until tests pass is known as test driven development. In terms of building software packages, the tests are whether the package can be built, whether the built package installs properly, and ideally that the tests the software ships with pass, such as those available during make test for many perl modules. Writing and automating these tests should enhance future development and debugging, as expected software behavior and layout is codified into the specification file and other test code.

For packages modified to suit some local site need, ideally indicate this somewhere in the %{name}, %{version}, or %{release} tags to distinguish local packages from standard ones.

More information on specification files can be found in Maximum RPM. See also the test.spec file, which includes example %pre and %post script handlers.

A common source of problems is Kerberos header errors when building against OpenSSL, which leads to errors involving the kssl.h file. One workaround is to set the /usr/kerberos/include directory to be in the include path.

%build
export CPATH=/usr/kerberos/include

Signing Packages

Sign packages on a dedicated build host, then transfer the signed packages to a separate distribution system. This way, a compromise of the distribution system does not give an attacker direct access to the private signing key, disallowing the chance to brute force or keystroke log the password to the private key. Packages must be signed, as otherwise an attacker will be able to run arbitrary software should a distribution server be broken into.

Resigning Packages

If a package signer leaves a site, their public keys should be removed from all systems, and any packages signed by them resigned with a new key. To list the signature on existing packages, use one of the following rpm commands. Older packages may have a SIGPGP value instead of SIGGPG. Unsigned packages will have neither value.

$ rpm -qip clamav-0.86.1-1.src.rpm | grep Signature
Signature : DSA/SHA1, Mon Jun 27 12:20:58 2005, Key ID 5c681717a7309fb6

$ rpm -qp --qf '%{SIGGPG}\n' clamav-0.86.1-1.src.rpm
883f03050042c0519a5c681717a7309fb611029501009d13f5147875e400ad 769e648a5e4c7af97455a900009901ec1b5a68133721be02c0035e7f80d50c227562

Search for packages with the public key to replace, then feed them to rpm --addsign to resign them.

Perl Modules

More information on installing Perl modules via RPM.

Python Libraries

To build python libraries, use the bdist_rpm argument to setup.py.

$ python setup.py bdist_rpm

Related

Experiments in RPM delta compression.