115 lines
4.7 KiB
YAML

---
# Phase: Setup and validation for Ansible Vault infrastructure on control node
# Concept: This role idempotently prepares the control node to encrypt/decrypt secrets
# without embedding plaintext credentials in playbooks or committed files.
# On first run, it creates directories and validates prerequisites.
# On repeat runs, it verifies infrastructure is still healthy.
- name: Create vault infrastructure directory
tags:
- bootstrap
block:
# Why ansible.builtin.file instead of 'mkdir'?
# - file module is idempotent: runs 100 times, same result
# - shell 'mkdir' fails if dir already exists (unless -p flag in separate task)
# - file module handles ownership, permissions, and state atomically
- name: Ensure vault base directory exists with secure permissions
ansible.builtin.file:
path: "{{ vault_base_dir }}"
state: directory
mode: "{{ vault_dir_mode }}"
recurse: false
register: vault_base_created
# Why ansible.builtin.file again (not just the above)?
# - Multiple tasks allow clear separation: one for base, one for vars subdir
# - Tags can be applied granularly (useful if debugging one phase)
- name: Ensure vault encrypted vars subdirectory exists
ansible.builtin.file:
path: "{{ vault_vars_dir }}"
state: directory
mode: "{{ vault_dir_mode }}"
recurse: false
register: vault_vars_created
- name: Validate vault prerequisites
tags:
- validate
block:
# Include external task file for readability and reusability
# - Keeps main.yml focused on the happy path
# - Allows the same validation to run standalone for testing
- name: Run vault validation checks
ansible.builtin.include_tasks: validate.yml
vars:
skip_validation: "{{ vault_skip_validation }}"
- name: Display setup status
tags:
- bootstrap
block:
# Why ansible.builtin.debug instead of 'echo' or shell?
# - debug module respects Ansible's verbosity levels (-v, -vv)
# - Output is properly formatted in Ansible logs and CI/CD systems
# - Can be silenced in automated runs, shown in verbose/interactive runs
- name: Report vault directory creation status
ansible.builtin.debug:
msg: |
Vault infrastructure ready.
Vault base dir: {{ vault_base_dir }}
Encrypted vars dir: {{ vault_vars_dir }}
Password file expected at: {{ vault_password_file }}
Next steps:
1. Create a vault password file (first run only):
echo 'your-strong-password' > {{ vault_password_file }}
chmod 0600 {{ vault_password_file }}
2. Create your first encrypted vars file:
ansible-vault create {{ vault_encrypted_file }}
3. Reference secrets in playbooks:
vars:
grafana_admin_password: "{{ vault_grafana_admin_password }}"
- name: Optional example vault setup
tags:
- example
block:
# This block is skipped by default (create_example_vault: false)
# Set create_example_vault: true to auto-generate an example encrypted file for learning
# Why skip by default?
# - Beginners need to understand password generation and encryption manually
# - Automated example creation bypasses the learning moment
# - Example includes a password_hash() to show Jinja2 + vault integration
- name: Create example vault content (for learning, runs with --tags example)
ansible.builtin.set_fact:
example_vault_content: |
---
# Example encrypted vars for Grafana
# Reference in playbook with: {{ vault_grafana_admin_password }}
vault_grafana_admin_password: "{{ 'change-me-to-strong-password' | password_hash('sha512') }}"
vault_authentik_outpost_dozzle_token: "your-authentik-token-here"
vault_docker_registry_password: "your-registry-password-here"
when: create_example_vault | bool
- name: Create example encrypted vars file
ansible.builtin.copy:
content: "{{ example_vault_content }}"
dest: "{{ vault_encrypted_file }}"
mode: "{{ vault_file_mode }}"
when: create_example_vault | bool
register: example_created
- name: Encrypt example file with ansible-vault (manual step)
ansible.builtin.debug:
msg: |
To encrypt the example vars file, run manually:
ansible-vault encrypt {{ vault_encrypted_file }}
Or use the vault password file:
ansible-vault encrypt --vault-password-file {{ vault_password_file }} {{ vault_encrypted_file }}
when: create_example_vault | bool and example_created is changed