diff options
author | Michał Górny <mgorny@gentoo.org> | 2020-09-05 17:36:58 +0200 |
---|---|---|
committer | Michał Górny <mgorny@gentoo.org> | 2020-09-05 17:37:12 +0200 |
commit | 61c3f0a91582ad337bbaeea06472f23816478ce8 (patch) | |
tree | 99fb958798a713c00a3220069937121478f8cd1c | |
parent | d418c9e19970f62143b27b433c44215a249f1a9c (diff) | |
download | gemato-61c3f0a91582ad337bbaeea06472f23816478ce8.tar.gz |
Add gpg-wrap command
Closes: https://github.com/mgorny/gemato/issues/18
Signed-off-by: Michał Górny <mgorny@gentoo.org>
-rw-r--r-- | gemato/cli.py | 42 | ||||
-rw-r--r-- | tests/test_openpgp.py | 38 |
2 files changed, 78 insertions, 2 deletions
diff --git a/gemato/cli.py b/gemato/cli.py index d3692bb..22b19f7 100644 --- a/gemato/cli.py +++ b/gemato/cli.py @@ -10,6 +10,8 @@ import datetime import logging import multiprocessing import os.path +import signal +import subprocess import sys import timeit @@ -561,14 +563,50 @@ class OpenPGPVerifyCommand(VerifyingOpenPGPMixin, GematoCommand): return 0 if ret else 1 +class GnuPGWrapCommand(VerifyingOpenPGPMixin, GematoCommand): + name = 'gpg-wrap' + help = ('Run specified command with GNUPGHOME set to OpenPGP ' + 'verification environment (with keys loaded)') + + def add_options(self, subp): + super().add_options(subp) + + subp.add_argument( + 'argv', nargs='+', + help='Command to execute') + + def parse_args(self, args, argp): + super().parse_args(args, argp) + + if args.openpgp_key is None: + argp.error('gpg-wrap requires --openpgp-key to be specified') + self.argv = args.argv + + def __call__(self): + super().__call__() + assert isinstance(self.openpgp_env, OpenPGPEnvironment) + os.environ['GNUPGHOME'] = self.openpgp_env._home + p = subprocess.Popen(self.argv) + ret = p.wait() + if ret < 0: + logging.error(f'Child process terminated due to signal: ' + f'{signal.strsignal(-ret)}') + return ret + + def main(argv): argp = argparse.ArgumentParser( prog=argv[0], description='Gentoo Manifest Tool') subp = argp.add_subparsers() - commands = [VerifyCommand, UpdateCommand, CreateCommand, - HashCommand, OpenPGPVerifyCommand] + commands = [VerifyCommand, + UpdateCommand, + CreateCommand, + HashCommand, + OpenPGPVerifyCommand, + GnuPGWrapCommand, + ] for cmdclass in commands: cmd = cmdclass() cmdp = subp.add_parser(cmd.name, help=cmd.help) diff --git a/tests/test_openpgp.py b/tests/test_openpgp.py index dbb71e5..69f0aad 100644 --- a/tests/test_openpgp.py +++ b/tests/test_openpgp.py @@ -6,6 +6,8 @@ import datetime import io import os +import shlex +import signal import tempfile import pytest @@ -841,3 +843,39 @@ def test_refresh_wkd_fallback_to_hkp(openpgp_env_with_refresh, ]) def test_get_wkd_url(email, expected): assert OpenPGPEnvironment.get_wkd_url(email) == expected + + +@pytest.mark.parametrize( + 'command,expected,match', + [('true', 0, None), + ('false', 1, None), + ('gpg --verify {tmp_path}/Manifest', 0, None), + ('gpg --verify {tmp_path}/Manifest.subkey', 2, None), + ('sh -c "kill $$"', -signal.SIGTERM, + f'Child process terminated due to signal: ' + f'{signal.strsignal(signal.SIGTERM)}'), + ('sh -c "kill -USR1 $$"', -signal.SIGUSR1, + f'Child process terminated due to signal: ' + f'{signal.strsignal(signal.SIGUSR1)}'), + ]) +def test_cli_gpg_wrap(tmp_path, caplog, command, expected, match): + with open(tmp_path / '.key.bin', 'wb') as f: + f.write(VALID_PUBLIC_KEY) + with open(tmp_path / 'Manifest', 'w') as f: + f.write(SIGNED_MANIFEST) + with open(tmp_path / 'Manifest.subkey', 'w') as f: + f.write(SUBKEY_SIGNED_MANIFEST) + + command = [x.replace('{tmp_path}', str(tmp_path)) + for x in shlex.split(command)] + retval = gemato.cli.main(['gemato', 'gpg-wrap', + '--openpgp-key', + str(tmp_path / '.key.bin'), + '--no-refresh-keys', + '--'] + command) + if str(OpenPGPNoImplementation('')) in caplog.text: + pytest.skip('OpenPGP implementation missing') + + assert retval == expected + if match is not None: + assert match in caplog.text |