koji sign plugin

Paul B Schroeder paulbsch at vbridges.com
Fri Dec 17 07:19:49 UTC 2010


As a follow up to the recent thread on singing RPMs in koji...and the many times this question pops
up on the list.  I've written some code that uses the koji plugin framework for signing packages.
I'm betting this may be useful to many folks that don't want/need sigul.  It might also be useful
to get this into the koji-hub-plugins package?

At any rate, here is the code and an example config file..  sign.py goes into your PluginPath.
The config file needs to be readable by the apache user and should probably be chmoded 600.  Also,
make sure you add sign to the Plugins option in hub.conf.  Oh, you'll want to install pexpect too.


sign.py:
# Koji callback for GPG signing RPMs before import
#
# Author:
#     Paul B Schroeder <paulbsch "at" vbridges "dot" com>

from koji.plugin import register_callback
import logging

config_file = '/usr/lib/koji-hub-plugins/sign.conf'

def sign(cbtype, *args, **kws):
    if kws['type'] != 'build':
       return

    # Get the tag name from the buildroot map
    import sys
    sys.path.insert(0, '/usr/share/koji-hub')
    from kojihub import get_buildroot
    br_id = kws['brmap'].values()[0]
    br = get_buildroot(br_id)
    tag_name = br['tag_name']

    # Get GPG info using the config for the tag name
    from ConfigParser import ConfigParser
    config = ConfigParser()
    config.read(config_file)
    rpm = config.get(tag_name, 'rpm')
    gpgbin = config.get(tag_name, 'gpgbin')
    gpg_path = config.get(tag_name, 'gpg_path')
    gpg_name = config.get(tag_name, 'gpg_name')
    gpg_pass = config.get(tag_name, 'gpg_pass')

    # Get the package paths set up
    from koji import pathinfo
    uploadpath = pathinfo.work()
    rpms = ''
    for relpath in [kws['srpm']] + kws['rpms']:
       rpms += '%s/%s ' % (uploadpath, relpath)

    # Get the packages signed
    import pexpect
    logging.getLogger('koji.plugin.sign').info('Attempting to sign packages'
       ' (%s) with key "%s"' % (rpms, gpg_name))
    rpm_cmd = "%s --resign --define '_signature gpg'" % rpm
    rpm_cmd += " --define '_gpgbin %s'" % gpgbin
    rpm_cmd += " --define '_gpg_path %s'" % gpg_path
    rpm_cmd += " --define '_gpg_name %s' %s" % (gpg_name, rpms)
    pex = pexpect.spawn(rpm_cmd, timeout=1000)
    pex.expect('(E|e)nter (P|p)ass (P|p)hrase:', timeout=1000)
    pex.sendline(gpg_pass)
    i = pex.expect(['good', 'failed', 'skipping', pexpect.TIMEOUT])
    if i == 0:
        logging.getLogger('koji.plugin.sign').info('Package sign successful!')
    elif i == 1:
        logging.getLogger('koji.plugin.sign').error('Pass phrase check failed!')
    elif i == 2:
        logging.getLogger('koji.plugin.sign').error('Package sign skipped!')
    elif i == 3:
        logging.getLogger('koji.plugin.sign').error('Package sign timed out!')
    else:
        logging.getLogger('koji.plugin.sign').error('Unexpected sign result!')
    if i != 0:
        raise Exception, 'Package sign failed!'
    pex.expect(pexpect.EOF)

register_callback('preImport', sign)


sign.conf:
[DEFAULT]
rpm = /bin/rpm
gpgbin = /usr/bin/gpg
gpg_path = /usr/lib/koji-hub-plugins/sign_gnupg
gpg_name = My Company, Inc. <support at mycompany.com>
gpg_pass = my_passphrase

# Defaults can be overridden on a per-tag basis
[dist-foo-build]
gpg_name = My Other Company, Inc. <support at myothercompany.com>
gpg_pass = my_other_passphrase




Cheers...Paul...


-- 
---
Paul B Schroeder
<paulbsch "at" vbridges "dot" com>


More information about the buildsys mailing list