ansible-infra/scripts/gopass-client.py

98 lines
3.2 KiB
Python
Executable File

#!/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()