185 lines
6.1 KiB
YAML

---
# Validation tasks for vault infrastructure health
# Concept: These assertions fail fast if vault prerequisites are missing or misconfigured.
# Run as part of the main role or standalone to diagnose vault setup issues.
# Why assert instead of conditional blocks?
# - assert provides clear, fail-fast feedback in the Ansible log
# - conditional blocks silently skip, hiding problems
# - assert messages are easy to test and CI-friendly
- name: Check vault password file exists
ansible.builtin.stat:
path: "{{ vault_password_file }}"
register: password_file_stat
tags:
- validate
# Why ansible.builtin.assert instead of shell 'test -f'?
# - assert provides human-readable failure messages
# - Multiple conditions can be checked in one task
# - Integrates with Ansible's fail_msg and exception handling
# - Shell 'test' silently passes/fails; harder to debug in logs
- name: Assert vault password file exists and has secure permissions
ansible.builtin.assert:
that:
- password_file_stat.stat.exists
- password_file_stat.stat.mode == "0600"
fail_msg: |
Vault password file is missing or has wrong permissions.
Expected: {{ vault_password_file }} with mode 0600
Actual: exists={{ password_file_stat.stat.exists }}, mode={{ password_file_stat.stat.mode | default('N/A') }}
To fix:
1. Create the file with a strong password:
echo 'YOUR-STRONG-PASSWORD' > {{ vault_password_file }}
2. Secure it:
chmod 0600 {{ vault_password_file }}
For interactive vault prompts (instead of password file), use:
ansible-playbook ansible/playbooks/onboarding/setup_ansible_secrets.yml --ask-vault-pass
when: not skip_validation | default(false)
tags:
- validate
- name: Check vault directory permissions
ansible.builtin.stat:
path: "{{ vault_base_dir }}"
register: vault_dir_stat
tags:
- validate
- name: Assert vault directory has secure permissions
ansible.builtin.assert:
that:
- vault_dir_stat.stat.exists
- vault_dir_stat.stat.isdir
- vault_dir_stat.stat.mode == "0700"
fail_msg: |
Vault directory has wrong permissions or does not exist.
Expected: {{ vault_base_dir }} as directory with mode 0700
Actual: exists={{ vault_dir_stat.stat.exists }}, isdir={{ vault_dir_stat.stat.isdir | default(false) }}, mode={{ vault_dir_stat.stat.mode | default('N/A') }}
To fix:
mkdir -p {{ vault_base_dir }}
chmod 0700 {{ vault_base_dir }}
when: not skip_validation | default(false)
tags:
- validate
- name: Check encrypted vars directory
ansible.builtin.stat:
path: "{{ vault_vars_dir }}"
register: vault_vars_dir_stat
tags:
- validate
- name: Assert encrypted vars directory exists
ansible.builtin.assert:
that:
- vault_vars_dir_stat.stat.exists
- vault_vars_dir_stat.stat.isdir
fail_msg: |
Vault encrypted vars directory does not exist.
Expected: {{ vault_vars_dir }}
To fix (automatic on next role run):
ansible-playbook playbooks/onboarding/setup_ansible_secrets.yml --tags bootstrap
when: not skip_validation | default(false)
tags:
- validate
- name: Check encrypted vars file state
ansible.builtin.stat:
path: "{{ vault_encrypted_file }}"
register: vault_encrypted_file_stat
tags:
- validate
- name: Assert encrypted vars file exists when required
ansible.builtin.assert:
that:
- vault_encrypted_file_stat.stat.exists
- vault_encrypted_file_stat.stat.isreg
fail_msg: |
Vault encrypted vars file is required but missing.
Expected: {{ vault_encrypted_file }}
To fix:
ansible-vault create {{ vault_encrypted_file }}
when:
- not skip_validation | default(false)
- vault_require_encrypted_vars_file | bool
tags:
- validate
- name: Read encrypted vars file header
ansible.builtin.slurp:
src: "{{ vault_encrypted_file }}"
register: vault_encrypted_file_content
when:
- not skip_validation | default(false)
- vault_require_encrypted_vars_file | bool
- vault_encrypted_file_stat.stat.exists
no_log: true
tags:
- validate
- name: Assert encrypted vars file is vault-encrypted
ansible.builtin.assert:
that:
- "(vault_encrypted_file_content.content | b64decode).startswith('$ANSIBLE_VAULT;')"
fail_msg: |
Vault vars file exists but is not encrypted with Ansible Vault.
File: {{ vault_encrypted_file }}
To fix:
ansible-vault encrypt {{ vault_encrypted_file }}
when:
- not skip_validation | default(false)
- vault_require_encrypted_vars_file | bool
- vault_encrypted_file_stat.stat.exists
no_log: true
tags:
- validate
- name: Load encrypted vars for required key checks
ansible.builtin.include_vars:
file: "{{ vault_encrypted_file }}"
name: loaded_vault_vars
when:
- not skip_validation | default(false)
- vault_require_encrypted_vars_file | bool
- vault_encrypted_file_stat.stat.exists
- (vault_encrypted_vars_required_keys | length) > 0
no_log: true
tags:
- validate
- name: Assert required encrypted keys exist
ansible.builtin.assert:
that:
- "item in loaded_vault_vars"
- "(loaded_vault_vars[item] | string | trim | length) > 0"
fail_msg: "Missing required vault key: {{ item }}"
loop: "{{ vault_encrypted_vars_required_keys }}"
when:
- not skip_validation | default(false)
- vault_require_encrypted_vars_file | bool
- vault_encrypted_file_stat.stat.exists
- (vault_encrypted_vars_required_keys | length) > 0
no_log: true
tags:
- validate
- name: Report validation success
ansible.builtin.debug:
msg: |
✓ Vault infrastructure is healthy.
✓ Vault password file: {{ vault_password_file }} (mode {{ password_file_stat.stat.mode }})
✓ Vault base directory: {{ vault_base_dir }} (mode {{ vault_dir_stat.stat.mode }})
✓ Encrypted vars directory: {{ vault_vars_dir }}
{% if vault_require_encrypted_vars_file | bool %}✓ Encrypted vars file: {{ vault_encrypted_file }}{% endif %}
when: not skip_validation | default(false)
tags:
- validate