diff options
Diffstat (limited to 'meta/lib/oe/gpg_sign.py')
| -rw-r--r-- | meta/lib/oe/gpg_sign.py | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/meta/lib/oe/gpg_sign.py b/meta/lib/oe/gpg_sign.py new file mode 100644 index 0000000000..55abad8ffc --- /dev/null +++ b/meta/lib/oe/gpg_sign.py | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | """Helper module for GPG signing""" | ||
| 2 | import os | ||
| 3 | |||
| 4 | import bb | ||
| 5 | import oe.utils | ||
| 6 | |||
| 7 | class LocalSigner(object): | ||
| 8 | """Class for handling local (on the build host) signing""" | ||
| 9 | def __init__(self, d, keyid, passphrase_file): | ||
| 10 | self.keyid = keyid | ||
| 11 | self.passphrase_file = passphrase_file | ||
| 12 | self.gpg_bin = d.getVar('GPG_BIN', True) or \ | ||
| 13 | bb.utils.which(os.getenv('PATH'), 'gpg') | ||
| 14 | self.gpg_path = d.getVar('GPG_PATH', True) | ||
| 15 | self.rpm_bin = bb.utils.which(os.getenv('PATH'), "rpm") | ||
| 16 | |||
| 17 | def export_pubkey(self, output_file): | ||
| 18 | """Export GPG public key to a file""" | ||
| 19 | cmd = '%s --batch --yes --export --armor -o %s ' % \ | ||
| 20 | (self.gpg_bin, output_file) | ||
| 21 | if self.gpg_path: | ||
| 22 | cmd += "--homedir %s " % self.gpg_path | ||
| 23 | cmd += self.keyid | ||
| 24 | status, output = oe.utils.getstatusoutput(cmd) | ||
| 25 | if status: | ||
| 26 | raise bb.build.FuncFailed('Failed to export gpg public key (%s): %s' % | ||
| 27 | (self.keyid, output)) | ||
| 28 | |||
| 29 | def sign_rpms(self, files): | ||
| 30 | """Sign RPM files""" | ||
| 31 | import pexpect | ||
| 32 | |||
| 33 | cmd = self.rpm_bin + " --addsign --define '_gpg_name %s' " % self.keyid | ||
| 34 | if self.gpg_bin: | ||
| 35 | cmd += "--define '%%__gpg %s' " % self.gpg_bin | ||
| 36 | if self.gpg_path: | ||
| 37 | cmd += "--define '_gpg_path %s' " % self.gpg_path | ||
| 38 | cmd += ' '.join(files) | ||
| 39 | |||
| 40 | # Need to use pexpect for feeding the passphrase | ||
| 41 | proc = pexpect.spawn(cmd) | ||
| 42 | try: | ||
| 43 | proc.expect_exact('Enter pass phrase:', timeout=15) | ||
| 44 | with open(self.passphrase_file) as fobj: | ||
| 45 | proc.sendline(fobj.readline().rstrip('\n')) | ||
| 46 | proc.expect(pexpect.EOF, timeout=900) | ||
| 47 | proc.close() | ||
| 48 | except pexpect.TIMEOUT as err: | ||
| 49 | bb.error('rpmsign timeout: %s' % err) | ||
| 50 | proc.terminate() | ||
| 51 | if os.WEXITSTATUS(proc.status) or not os.WIFEXITED(proc.status): | ||
| 52 | bb.error('rpmsign failed: %s' % proc.before.strip()) | ||
| 53 | raise bb.build.FuncFailed("Failed to sign RPM packages") | ||
| 54 | |||
| 55 | def detach_sign(self, input_file): | ||
| 56 | """Create a detached signature of a file""" | ||
| 57 | cmd = "%s --detach-sign --armor --batch --no-tty --yes " \ | ||
| 58 | "--passphrase-file '%s' -u '%s' " % \ | ||
| 59 | (self.gpg_bin, self.passphrase_file, self.keyid) | ||
| 60 | if self.gpg_path: | ||
| 61 | gpg_cmd += "--homedir %s " % self.gpg_path | ||
| 62 | cmd += input_file | ||
| 63 | status, output = oe.utils.getstatusoutput(cmd) | ||
| 64 | if status: | ||
| 65 | raise bb.build.FuncFailed("Failed to create signature for '%s': %s" % | ||
| 66 | (input_file, output)) | ||
| 67 | |||
| 68 | |||
| 69 | def get_signer(d, backend, keyid, passphrase_file): | ||
| 70 | """Get signer object for the specified backend""" | ||
| 71 | # Use local signing by default | ||
| 72 | if backend == 'local': | ||
| 73 | return LocalSigner(d, keyid, passphrase_file) | ||
| 74 | else: | ||
| 75 | bb.fatal("Unsupported signing backend '%s'" % backend) | ||
| 76 | |||
