def main(): args = parse_args() old_signatures = set() if args.full: log.info('Renerating all signatures') shutil.rmtree(signatures_dir, ignore_errors=True) elif os.path.exists(signatures_dir): for dirpath, dirnames, filenames in os.walk(signatures_dir): for f in filenames: old_signatures.add(os.path.join(dirpath, f)) for file in release_files_iter(): set_gpg('client') signature = verify_signature(file) if signature: log.debug('Preserving valid signature for {}', file) else: set_gpg('server') log.info('Signing {}', file) signature = sign_file(file) old_signatures.discard(signature) for file in old_signatures: log.info('Removing obsolete signature {}', file) os.unlink(file) try: subprocess.check_output( ('python', os.path.join('client', 'verify.py')), stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: sys.exit( 'Verify failed, try running bin/sign again. Output:\n{}'.format( e.output.decode('utf8')))
def background_code(args): log = get_logger('shell') pipe_id = args.pipe_id log.info('Initiating shell with pipe ID {}', pipe_id) try: set_gpg('client') with PenguinDomeServerPeer('client', pipe_id) as remote, \ PexpectPeer('/bin/bash') as shell: broker = InteractionBroker(shell, remote) broker.interact() except Exception: log.exception() sys.exit(1)
def generate_key(mode, user_id): set_gpg(mode) try: gpg_command('--list-keys', user_id, with_trustdb=True) except Exception: entropy_warning() try: gpg_command('--passphrase', '', '--quick-gen-key', user_id, with_trustdb=True) except subprocess.CalledProcessError as e: sys.exit('PenguinDome requires GnuPG version 2.1 or newer. ' 'gpg output:\n{}'.format(e.output))
def import_key(to_mode, user_id): from_mode = 'client' if to_mode == 'server' else 'server' set_gpg(to_mode) try: gpg_command('--list-keys', user_id) except Exception: with NamedTemporaryFile() as key_file: set_gpg(from_mode) gpg_command('--export', '-o', key_file.name, user_id) set_gpg(to_mode) gpg_command('--import', key_file.name)
import threading import time from penguindome import ( top_dir, collected_dir, plugins_dir, commands_dir, signatures_dir, set_gpg, ) from penguindome.client import get_logger, encrypt_document import penguindome.json as json os.chdir(top_dir) set_gpg('client') # Some commands the plugins use are in /sbin or /usr/sbin on some # distributions, and it isn't always in the search path used by cron scripts. for d in ('/sbin', '/usr/sbin'): if d not in os.environ['PATH'].split(':'): os.environ['PATH'] += ':' + d log = get_logger('collect') def run_file(run_path, run_name, results, parse_output=True, delete_after_success=False,
def enable_handler(args): if get_server_setting('secret_keeping:enabled'): sys.exit('Secret-keeping is already enabled.') if get_server_setting('secret_keeping:key_id'): if not (args.replace or args.preserve): sys.exit('Must specify --replace or --preserve.') else: args.replace = True args.shares = args.shares or \ get_server_setting('secret_keeping:num_shares') if args.shares < 2: sys.exit('--num-shares must be at least 2.') args.combine_threshold = args.combine_threshold or \ get_server_setting('secret_keeping:combine_threshold') if args.combine_threshold < 2: sys.exit('--combine-threshold must be at least 2.') if args.combine_threshold > args.shares: sys.exit( '--combine-threshold must be less than {}.'.format(args.shares + 1)) if args.replace: key_name = 'penguindome-secret-keeping-' + uuid.uuid4().hex output = gpg_command('--passphrase', '', '--quick-gen-key', key_name, with_trustdb=True, quiet=False) match = re.search(r'key (.*) marked as ultimately trusted', output) key_id = match.group(1) match = re.search(r'/([0-9A-F]+)\.rev', output) key_fingerprint = match.group(1) split_dir = os.path.join(var_dir, key_name) key_file = os.path.join(split_dir, 'private_key.asc') os.makedirs(split_dir) gpg_command('--export-secret-key', '--armor', '-o', key_file, key_id) subprocess.check_output(('gfsplit', '-n', str( args.combine_threshold), '-m', str(args.shares), key_file), stderr=subprocess.STDOUT) try: gpg_command('--delete-secret-keys', key_fingerprint) except subprocess.CalledProcessError as e: sys.exit('Failed to delete secret key:\n{}'.format( e.output.decode('utf8'))) subprocess.check_output(('shred', '-u', key_file), stderr=subprocess.STDOUT) with NamedTemporaryFile() as public_key_file: gpg_command('--export', '-o', public_key_file.name, key_id) set_gpg('client') try: gpg_command('--import', public_key_file.name) finally: set_gpg('server') set_server_setting('secret_keeping:key_name', key_name) set_server_setting('secret_keeping:key_id', key_id) set_server_setting('secret_keeping:key_fingerprint', key_fingerprint) set_client_setting('secret_keeping:key_id', key_id) set_server_setting('secret_keeping:num_shares', args.shares) set_server_setting('secret_keeping:combine_threshold', args.combine_threshold) set_server_setting('secret_keeping:enabled', True) save_server_settings() set_client_setting('secret_keeping:enabled', True) save_client_settings() print( distribute_secrets_note.format(m=args.shares, n=args.combine_threshold, split_dir=split_dir)) print(restart_note) log.info('Enabled secret-keeping')
from penguindome.server import ( get_db, get_setting as get_server_setting, set_setting as set_server_setting, save_settings as save_server_settings, get_selectors, encrypt_document, get_logger, ) from penguindome.client import ( set_setting as set_client_setting, save_settings as save_client_settings, ) os.chdir(top_dir) set_gpg('server') log = get_logger('secret_keeping') selectors_setting = 'secret_keeping:selectors' restart_note = ("\nNOTE: Don't forget to build a new client release!\n") distribute_secrets_note = ''' The {m} pieces of the secret-keeping key are in this directory: {split_dir} Please distribute these files securely to the secret-keepers and then remove them with "shred -u". At least {n} of these files will need to be provided to reconstruct the key so that secret data can be decrypted. ''' audit_trail_selectors = (SelectorVariants('old', 'old', 'old', 'old'), SelectorVariants('new', 'new', 'new', 'new'))