# role_include_vault-check An include-only Ansible role to check if HashiCorp Vault variables truly exist # Import Whenever you work with HashiCorp Vault data stored in a `kv` secrets engine you may want to import this role into whatever playbook you're running. Given a `role` directory create a `meta` subdirectory underneath it with a file named `requirements.yml`. ``` role ├── meta <--- Create this │   └── requirements.yml <--- Create this └── tasks └── main.yml ``` In `requirements.yml` add: ``` - src: 'https://quico.space/quico-ansible/role_include_vault-check.git' version: 'master' ``` Now whenver you import `role` for example via `ansible-galaxy install ...` you'll automatically get this one downloaded as well. You can optionally leave out `version: 'master'` since this is the default version anyways, meaning the `role_include_vault-check` newest master commit. The `version:` attribute helps you pin a version, for example as `version: 'v1.0.0'` which will instead pull `role_include_vault-check` Git tag `v1.0.0`. Side note, this role follows the [Semantic Versioning](https://semver.org/) standard. A Git tag name `v1.0.0` refers to Semantic Version `1.0.0`. # Use it ## Generic setup From your `role` call this one like so: ``` - name: 'If a secret is missing: Fail progress' import_role: name: 'role_include_vault-check' vars: - vault_check_base_path: '{{ vault_check_base_path }}' - vault_check_inc_vault_data: '{{ vault_check_vault_data }}' - vault_check_fail_checks: - 'password', - 'password_salt' ``` This `role_include_vault-check` expects two variables in your `import_role` task for example via the `vars` statement: 1. `vault_check_base_path`: The path in HashiCorp Vault's `kv` secrets engine where secrets are located. Has cosmetic purpose only to inform the user where a key-value check succeeded or failed. 1. `vault_check_inc_vault_data`: The Vault data dictionary we want checked. 1. `vault_check_fail_checks`: A list of keys located at `vault_check_base_path` for which you want to confirm that they are non-empty. Can either be defined in place like so: ``` - vault_check_fail_checks: - 'password' - 'password_salt' ``` Or can use a list variable defined elsewhere: ``` - vault_check_fail_checks: '{{ some_list }}' ``` ## In context In a real-world use case you'll likely first query HashiCorp Vault for key-value pairs for example like so: ``` - name: 'Get secrets' no_log: 'true' loop_control: loop_var: 'server' with_community.hashi_vault.vault_kv2_get: '{{ local_os_password_vault_paths }}' ansible.builtin.set_fact: vault_data: '{{ vault_data | default({}) | combine (server.secret) }}' ``` The `vault_kv2_get` lookup plug-in (see [vault_kv2_get lookup documentation](https://docs.ansible.com/ansible/devel/collections/community/hashi_vault/vault_kv2_get_lookup.html)) iterates over variables you want loaded from Vault. For each iteration it stores the iteration's output in `loop_var: 'server'`. From that output we only really care about the `server.secret` dictionary. We append that to a `vault_data` dictionary which is first initialized as an empty dictionary and then expanded per iteration. When done `vault_data` contains key-values pair for all Vault variables. The next step can be this `role_include_vault-check` to hard-fail in case a key turned out to have an empty value. ``` - name: 'If a secret is missing: Fail progress' import_role: name: 'role_include_vault-check' vars: - vault_check_base_path: '{{ local_os_password_vault_base }}' - vault_check_inc_vault_data: '{{ vault_data }}' - vault_check_fail_checks: '{{ local_os_password_vault_vars }}' ``` ## Output Ansible's task output will be for example: ``` TASK [...] **************************************************************************************** ok: ... TASK [role_include_vault-check : If a secret is missing: Fail progress] *************************** ok: [fully.qualified.domain.name] => (item=password) => { "msg": "Vault has secret 'password' at 'name/domain/qualified/fully/os/root'" } ok: [fully.qualified.domain.name] => (item=password_salt) => { "msg": "Vault has secret 'password_salt' at 'name/domain/qualified/fully/os/root'" } TASK [...] **************************************************************************************** ok: ... ```