From cb8f5b15374a5c09a674a07c35de072e472e5e73 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO <ynerant@crans.org> Date: Sun, 28 Feb 2021 11:26:21 +0100 Subject: [PATCH] Load vault passwords from local password store, then cache them Signed-off-by: Yohann D'ANELLO <ynerant@crans.org> --- ansible.cfg | 1 + group_vars/all/vault.yml | 1 - vars_plugins/pass.py | 57 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) delete mode 100644 group_vars/all/vault.yml create mode 100644 vars_plugins/pass.py diff --git a/ansible.cfg b/ansible.cfg index 52176e1d..2ebd2aad 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -6,6 +6,7 @@ roles_path = ./roles action_plugins = ./action_plugins lookup_plugins = ./lookup_plugins +vars_plugins = ./vars_plugins # Do not create .retry files retry_files_enabled = False diff --git a/group_vars/all/vault.yml b/group_vars/all/vault.yml deleted file mode 100644 index 9ba80a0d..00000000 --- a/group_vars/all/vault.yml +++ /dev/null @@ -1 +0,0 @@ -vault: "{{ lookup('pipe', 'pass show crans/ansible_vault') | from_yaml }}" diff --git a/vars_plugins/pass.py b/vars_plugins/pass.py new file mode 100644 index 00000000..228cebe7 --- /dev/null +++ b/vars_plugins/pass.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +from functools import lru_cache +from os import getenv +from pathlib import Path +import subprocess +import sys + +from ansible.plugins.vars import BaseVarsPlugin + + +DOCUMENTATION = """ + module: pass + vars: vault + version_added: 2.9 + short_description: Load vault passwords from pass + description: + - Works exactly as a vault, loading variables from pass. + - Decrypts the YAML file `ansible_vault` from cranspasswords. + - Loads the secret variables. + - Makes use of data caching in order to avoid calling cranspasswords multiple times. + - Uses the local gpg key from the user running ansible on the Control node. +""" + + + +class VarsModule(BaseVarsPlugin): + @staticmethod + @lru_cache + def vault_passwords(): + """ + Passwords are decrypted from the local password store, then are cached. + By that way, we don't decrypt these passwords everytime. + """ + password_store = Path(getenv('PASSWORD_STORE_DIR', Path.home() / '.password-store')) + full_command = ['gpg', '-d', password_store / getenv('CRANS_PASSWORD_STORE_SUBMODULE', 'crans') / 'ansible_vault.gpg'] + proc = subprocess.run(full_command, capture_output=True, close_fds=True) + clear_text = proc.stdout.decode('UTF-8') + sys.stderr.write(proc.stderr.decode('UTF-8')) + return clear_text + + def get_vars(self, loader, path, entities): + """ + Get all vars for entities, called by Ansible. + + loader: Ansible's DataLoader. + path: Current play's playbook directory. + entities: Host or group names pertinent to the variables needed. + """ + # VarsModule objects are called every time you need host vars, per host, + # and per group the host is part of. + # It is about 6 times per host per task in current state + # of Ansible Crans configuration. + + # It is way to much. + # So we cache the data into the DataLoader (see parsing/DataLoader). + + return {'vault': loader.load(VarsModule.vault_passwords())} -- GitLab