def test_decrypt_file_tolocation(): expected = rekey.parse_yaml(join(PLAY, "group_vars/nosecrets.yml")) path = join(PLAY, "group_vars/encrypted.yml") newpath = join(TMP_DIR, 'decrypted.yml') password_file = join(PLAY, "vault-password.txt") rekey.decrypt_file(path, password_file, newpath) assert expected == rekey.parse_yaml(newpath)
def test_find_yaml_secrets(): d = rekey.parse_yaml(join(PLAY, "group_vars/inlinesecrets.yml")) expected = [['password'], ['users', 0, 'password'], ['users', 1, 'secrets', 1]] r = list(rekey.find_yaml_secrets(d)) for i in expected: assert i in r
def test_get_dict_value(): d = rekey.parse_yaml(join(PLAY, "group_vars/inlinesecrets.yml")) # expected = [ # ['password'], # ['users', 0, 'password'], # ['users', 1, 'secrets', 1] # ] r = rekey.find_yaml_secrets(d) for address in r: assert isinstance(rekey.get_dict_value(d, address), VaultString)
def test_rekey_file_withdecrypt(): expected = rekey.parse_yaml(join(PLAY, "group_vars/nosecrets.yml")) path = join(PLAY, "group_vars/encrypted.yml") password_file = join(PLAY, "vault-password.txt") alt_password_file = join(PLAY, 'alt-vault-password.txt') rekey.rekey_file(path, password_file, alt_password_file) assert expected == rekey.decrypt_file(path, alt_password_file) rekey.rekey_file(path, alt_password_file, password_file) assert expected == rekey.decrypt_file(path, password_file)
def test_put_dict_value(): d = rekey.parse_yaml(join(PLAY, "group_vars/nosecrets.yml")) oldval = ['one', 'two', 'three'] address = ['moo', 'too'] v = rekey.get_dict_value(d, address) assert isinstance(v, list) assert v == oldval assert rekey.put_dict_value(d, address, v + ['four']) != None newv = rekey.get_dict_value(d, address) assert isinstance(newv, list) assert newv == oldval + ['four']
def main(password_file, varsfile, code_path, dry_run, keep_backups, debug): """(Re)keys Ansible Vault repos.""" if debug: log_console.setLevel(logging.DEBUG) if not os.path.isdir(code_path): log.error("{} doesn't seem to exist".format(code_path)) sys.exit(1) code_path = os.path.realpath(code_path) backup_path = os.path.join(code_path, ".rekey-backups") log.debug('Backup path set to: {}'.format(backup_path)) if not password_file: password_file = os.path.join(code_path, 'vault-password.txt') else: if not os.path.isfile(password_file): log.error("{} doesn't seem to exist".format(password_file)) sys.exit(1) password_file = os.path.realpath(password_file) # find all YAML files files = [os.path.realpath(varsfile) ] if varsfile else rekey.find_files(code_path) vault_files = [] for f in files: if rekey.is_file_secret(f): vault_files.append({'file': f}) continue try: data = rekey.parse_yaml(f) except Exception as e: log.warning( 'Unable to parse file, probably not valid yaml: {}'.format( happy_relpath(f))) continue # enh, generator. w/e. secrets = list(rekey.find_yaml_secrets(data)) if data else None if secrets and len(secrets) > 0: vault_files.append({'file': f, 'secrets': secrets}) vflog = [] for i in vault_files: suffix = " (whole)" if 'secrets' not in i.keys() else "" vflog.append("{}{}".format(happy_relpath(i['file']), suffix)) log.debug('Found {} vault-enabled files: {}'.format( len(vflog), ', '.join(vflog))) log.info('Backing up encrypted and password files...') # backup password file rekey.backup_files([password_file], backup_path, code_path) # decrypt and write files out to unencbackup location (same relative paths) for f in vault_files: newpath = os.path.join(backup_path, f['file'][len(code_path) + 1:]) log.debug('Decrypting {} to {} using {}'.format( happy_relpath(f['file']), happy_relpath(newpath), happy_relpath(password_file))) rekey.decrypt_file(f['file'], password_file, newpath) # generate new password file log.info('Generating new password file...') if dry_run: log.info('>> Dry run enabled, skipping overwrite. <<') else: rekey.write_password_file(password_file, overwrite=True) log.info('Password file written: {}'.format( happy_relpath(password_file))) # loop through encrypted asset list, re-encrypt and overwrite originals log.info('Re-encrypting assets with new password file...') for f in vault_files: # log.debug('Raw file obj: {}'.format(f)) oldpath = os.path.join(backup_path, happy_relpath(f['file'])) newpath = os.path.realpath(f['file']) log.debug('Encrypting {} to {}'.format(happy_relpath(oldpath), happy_relpath(newpath))) if dry_run: log.info('>> Dry run enabled, skipping overwrite. <<') r = True else: r = rekey.encrypt_file(oldpath, password_file, newpath, f.get('secrets', None)) if not r: log.error('Encryption failed on {}'.format(oldpath)) # test decryption of newly written assets? # remove backups if not keep_backups: log.info('Removing backups...') shutil.rmtree(backup_path) log.info('Done!')
def test_get_dict_value_bad(): d = rekey.parse_yaml(join(PLAY, "group_vars/inlinesecrets.yml")) assert rekey.get_dict_value(d, ['fake', 'address']) == None
def test_find_yaml_secrets_none(): d = rekey.parse_yaml(join(PLAY, "group_vars/nosecrets.yml")) expected = [] r = list(rekey.find_yaml_secrets(d)) assert expected == r
def test_parse_yaml_bad(): with pytest.raises(Exception) as e: rekey.parse_yaml(join(PLAY, "group_vars/bad.yml"))
def test_parse_yaml_nosecrets(): assert isinstance(rekey.parse_yaml(join(PLAY, "group_vars/nosecrets.yml")), dict)