示例#1
0
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')))
示例#2
0
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)
示例#3
0
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))
示例#4
0
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)
示例#5
0
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'))