예제 #1
0
def encrypt_handler(args):
    if not get_server_setting('secret_keeping:enabled'):
        sys.exit('You cannot encrypt when secret-keeping is disabled.')
    db = get_db()
    selectors = get_selectors()
    spec = {'$or': [{s.plain_mongo: {'$exists': True}} for s in selectors]}
    for doc in db.clients.find(spec):
        doc, update = encrypt_document(doc)
        if update:
            db.clients.update({'_id': doc['_id']}, update)
            log.info('Encrypted data in client document {} (host {})',
                     doc['_id'], doc['hostname'])
            print('Encrypted client document {} (host {})'.format(
                doc['_id'], doc['hostname']))
    spec = {'key': {'$in': [s.plain_mongo for s in selectors]}}
    for doc in db.audit_trail.find(spec):
        doc, update = encrypt_document(doc, selectors=audit_trail_selectors)
        if update:
            update['$set']['key'] = next(s.enc_mongo for s in selectors
                                         if s.plain_mongo == doc['key'])
            db.audit_trail.update({'_id': doc['_id']}, update)
            log.info('Encrypted data in audit trail document {} (host {})',
                     doc['_id'], doc['hostname'])
            print('Encrypted audit trail document {} (host {})'.format(
                doc['_id'], doc['hostname']))
예제 #2
0
def decrypt_iterator(document_iterator,
                     document_keys=None,
                     selectors=None,
                     full_documents=False):
    """Decrypt documents and return decrypted data

    `selectors` defaults to `get_selectors()`

    Each yield is a tuple of a document containing the document keys, a
    document containing the decrypted data in the same structure as the
    original document, and a list of tuples of selectors that were decrypted
    and the decrypted datum for each selector. I.e., the same decrypted data is
    returned in two different forms, to simplify the use of the data by the
    caller.

    if `full_documents` is true, then the document in each yield will be the
    full document returned by the iterator with encrypted fields replaced,
    rather than a document containing just the decrypted fields.

    Assumes that the secret key has already been combined _before_ this
    function is called.

    Note: There is a yield for every document that is returned by
    document_iterator, even if nothing was decrypted. If that's the case, then
    the document keys in the yield will be populated, but the decrypted data
    document and list will be empty.
    """
    if selectors is None:
        selectors = get_selectors()
    for doc in document_iterator:
        document_keys = {k: doc[k] for k in document_keys or ()}
        output_dict = doc if full_documents else {}
        output_tuples = []
        for s in selectors:
            encrypted_data = get_setting(doc, s.enc_mem, check_defaults=False)
            if not encrypted_data:
                continue
            with NamedTemporaryFile('w+b') as unencrypted_file, \
                    NamedTemporaryFile('w+b') as encrypted_file:
                encrypted_file.write(b64decode(encrypted_data['data']))
                encrypted_file.flush()
                gpg_command('--decrypt', '-o', unencrypted_file.name,
                            encrypted_file.name)
                unencrypted_file.seek(0)
                unencrypted_data = json.loads(
                    unencrypted_file.read().decode('utf-8'))
            # Order is important here. We unset before we set because the
            # selector key may be the same for both unencrypted and encrypted
            # fields.
            if full_documents:
                set_setting(output_dict, s.enc_mem, None)
            set_setting(output_dict, s.plain_mem, unencrypted_data)
            output_tuples.append((s, unencrypted_data))
        yield (document_keys, output_dict if output_tuples else {},
               output_tuples)
예제 #3
0
def access_handler(args):
    combine_secret_key()
    selectors = get_selectors()
    try:
        db = get_db()
        spec = {'$or': [{s.enc_mongo: {'$exists': True}} for s in selectors]}
        printed_header = not args.audit_trail
        for keys, dct, tuples in decrypt_iterator(db.clients.find(spec),
                                                  ('_id', 'hostname'),
                                                  full_documents=args.full,
                                                  selectors=selectors):
            if dct:
                if not printed_header:
                    print('Clients:\n')
                    printed_header = True
                pprint.pprint({**keys, **dct})
                log.info('Displayed encrypted data in document {} (host {})',
                         keys['_id'], keys['hostname'])
        if args.audit_trail:
            if printed_header:
                print('')
            spec = {'key': {'$in': [s.enc_mongo for s in selectors]}}
            printed_header = False
            for keys, dct, tuples in decrypt_iterator(
                    db.audit_trail.find(spec, sort=(('_id', DESCENDING), )),
                    selectors=audit_trail_selectors,
                    full_documents=True):
                if dct:
                    if not printed_header:
                        print('Audit trail:\n')
                        printed_header = True
                    dct['key'] = next(s.plain_mongo for s in selectors
                                      if s.enc_mongo == dct['key'])
                    pprint.pprint(dct)
                    log.info(
                        'Displayed encrypted audit trail in document {} '
                        '(host {})', dct['_id'], dct['hostname'])
    finally:
        delete_secret_key()
예제 #4
0
def decrypt_handler(args):
    combine_secret_key()
    selectors = get_selectors()
    try:
        db = get_db()
        spec = {'$or': [{s.enc_mongo: {'$exists': True}} for s in selectors]}
        for keys, dct, tuples in decrypt_iterator(db.clients.find(spec),
                                                  ('_id', 'hostname'),
                                                  selectors=selectors):
            if dct:
                spec = {'_id': keys['_id']}
                update = {
                    '$set': {s.plain_mongo: u
                             for s, u in tuples},
                    '$unset': {s.enc_mongo: True
                               for s, u in tuples}
                }
                db.clients.update(spec, update)
                log.info('Decrypted data in client document {} (host {})',
                         keys['_id'], keys['hostname'])
                print('Decrypted client document {} (host {})'.format(
                    keys['_id'], keys['hostname']))

        spec = {'key': {'$in': [s.enc_mongo for s in selectors]}}
        for keys, dct, tuples in decrypt_iterator(
                db.audit_trail.find(spec),
                selectors=audit_trail_selectors,
                full_documents=True):
            if dct:
                dct['key'] = next(s.plain_mongo for s in selectors
                                  if s.enc_mongo == dct['key'])
                spec = {'_id': dct['_id']}
                db.audit_trail.update(spec, dct)
                log.info('Decrypted data in audit trail document {} (host {})',
                         dct['_id'], dct['hostname'])
                print('Decrypted audit trail document {} (host {})'.format(
                    dct['_id'], dct['hostname']))
    finally:
        delete_secret_key()