#!/usr/bin/env python3 # -*- coding: utf-8 -*- import argparse import configparser import logging import os import subprocess import sys ANSIBLE_ENV_DIR = os.getenv("ANSIBLE_CONFIG") ANSIBLE_DIR = "/etc/ansible" CURRENT_DIR = os.getcwd() HOME_DIR = os.getenv("HOME") ANSIBLE_CONFIG_SECTION = "gopass" ANSIBLE_CONFIG_KEY = "key_path" class ShutdownHandler(logging.Handler): def emit(self, record): logging.shutdown() sys.exit(1) def find_ansible_config_value(section, key): config = configparser.ConfigParser() ansible_config_dirs = [CURRENT_DIR, HOME_DIR, ANSIBLE_DIR] if ANSIBLE_ENV_DIR: ansible_config_dirs.insert(0, ANSIBLE_ENV_DIR) for ansible_config_dir in ansible_config_dirs: ansible_config_path = os.path.join(ansible_config_dir, "ansible.cfg") config.read(ansible_config_path) try: return config[section][key] except KeyError: logging.debug(f"Cannot find '{key}' key in '{ansible_config_path}' config file") ansible_config_paths = ':'.join(ansible_config_dirs) raise RuntimeError(f"Cannot find key '{ANSIBLE_CONFIG_KEY}' in {ansible_config_paths}") def build_arg_parser(): parser = argparse.ArgumentParser(description='Get a vault password from user keyring') parser.add_argument('--vault-id', action='store', default='', dest='vault_id', help='Name of the vault secret to get from keyring') return parser def main(): logger = logging.getLogger() logger.setLevel(logging.NOTSET) formatter = logging.Formatter("%(levelname)s: %(message)s") stdout_handler = logging.StreamHandler(sys.stdout) stdout_handler.setLevel(logging.INFO) stdout_handler.addFilter(lambda record: record.levelno <= logging.INFO) stdout_handler.setFormatter(formatter) logger.addHandler(stdout_handler) stderr_handler = logging.StreamHandler(sys.stderr) stderr_handler.setLevel(logging.WARNING) stderr_handler.setFormatter(formatter) logger.addHandler(stderr_handler) logger.addHandler(ShutdownHandler(level=logging.ERROR)) try: ansible_config_value = find_ansible_config_value(ANSIBLE_CONFIG_SECTION, ANSIBLE_CONFIG_KEY) except RuntimeError as e: logging.error(e) arg_parser = build_arg_parser() args = arg_parser.parse_args() ansible_vault_id = args.vault_id gopass_key_path = os.path.join(ansible_config_value, ansible_vault_id) gopass_keys_cmd = subprocess.run(["gopass", "ls", "--flat"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) if gopass_keys_cmd.returncode != 0: logging.error(gopass_keys_cmd.stderr.decode()) gopass_keys = map(bytes.decode, gopass_keys_cmd.stdout.splitlines()) try: gopass_keyname = next(key for key in gopass_keys if key.endswith(gopass_key_path)) except StopIteration: logging.error(f"Cannot find '{gopass_key_path}' entry in gopass") ansible_vault_pass_cmd = subprocess.run(["gopass", "show", "-o", gopass_keyname], stdout=subprocess.PIPE, stderr=subprocess.PIPE) if ansible_vault_pass_cmd.returncode != 0: logging.error(ansible_vault_pass_cmd.stderr.decode()) print(ansible_vault_pass_cmd.stdout.decode()) if __name__ == '__main__': main()