Hello,

Thank you for your Koji callback.

I perform some modifications:
+ to handle DEFAULT section (if section for Tag name is not defined)
+ to support empty GPG pass-phrase
+ to work on localized OS
+ to log GPG messages if rpm --resign fails

Note: your GPG directory (gpg_path in .conf file) must be readable and writeable by apache (the user which runs Koji hub)

Regards,
Pierre

# 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

# Configuration file in /etc like for other plugins
CONFIG_FILE = '/etc/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
    import ConfigParser
    config = ConfigParser.ConfigParser()
    config.read(CONFIG_FILE)
    try:
        rpm = config.get(tag_name, 'rpm')
    except ConfigParser.NoSectionError:
        rpm = config.get(ConfigParser.DEFAULTSECT, 'rpm')
    try:
        gpgbin = config.get(tag_name, 'gpgbin')
    except ConfigParser.NoSectionError:
        gpgbin = config.get(ConfigParser.DEFAULTSECT, 'gpgbin')
    try:
        gpg_path = config.get(tag_name, 'gpg_path')
    except ConfigParser.NoSectionError:
        gpg_path = config.get(ConfigParser.DEFAULTSECT, 'gpg_path')
    try:
        gpg_name = config.get(tag_name, 'gpg_name')
    except ConfigParser.NoSectionError:
        gpg_name = config.get(ConfigParser.DEFAULTSECT, 'gpg_name')
    try:
        gpg_pass = config.get(tag_name, 'gpg_pass')
    except ConfigParser.NoSectionError:
        gpg_pass = config.get(ConfigParser.DEFAULTSECT, '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
    import os
    os.environ['LC_ALL'] = 'C'
    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)
    # Add rpm output to a temporary file
    fout = os.tmpfile()
    pex.logfile = fout
    pex.expect('(E|e)nter (P|p)ass (P|p)hrase:', timeout=1000)
    if not gpg_pass:
        pex.sendline('\r')
    else:
        pex.sendline(gpg_pass)
    i = pex.expect(['good', 'failed', 'skipping', pexpect.TIMEOUT])
    pex.expect(pexpect.EOF)
    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:
        # Rewind in rpm output
        fout.seek(0)
        # Add GPG errors to log
        for line in fout.readlines():
            if 'gpg:' in line:
                logging.getLogger('koji.plugin.sign').error(line.rstrip('\n'))
        fout.close()
        raise Exception, 'Package sign failed!'
    else:
        fout.close()

register_callback('preImport', sign)





Regards,
Pierre