Loading...

Lab 101: Secure Secrets with Ansible Vault

Encrypt secrets at rest using Ansible Vault so credentials can be version-controlled safely. Practice the full operator workflow: create, view, edit, use in a playbook run, and rotate vault passwords.

automation security ansible vault

Scenario

Your Ansible repo needs to store database credentials and API tokens, but storing secrets in plaintext is not acceptable. You will use ansible-vault to encrypt secrets at rest, load them during a playbook run, and rotate the vault password.

Operator context

Vault is the baseline for secrets-in-Git workflows. It reduces accidental leakage, supports reviews, and enables controlled rotation without rewriting your automation.

Objective

  • Create a Vault-encrypted secrets file using ansible-vault create.
  • Confirm ciphertext on disk and safely edit and view contents.
  • Load the vault file via vars_files in a playbook.
  • Run a playbook using --ask-vault-pass (interactive).
  • Rotate the vault password using ansible-vault rekey.

Concepts

  • Vault encrypts data at rest. Decryption happens at run time when you provide a vault secret.
  • A vault file should start with a vault header. Seeing plaintext with cat is a red flag.
  • Viewing secrets to stdout is operationally risky. Prefer using them in tasks without printing them.
  • Rekey changes the password that protects an encrypted file. The underlying content stays the same, the protection changes.

Walkthrough

Step 1 : Create a new Vault-encrypted file.
Command
ansible-vault create secrets.yml

You will be prompted for a vault password and dropped into an editor. Save and exit to write the encrypted file to disk.

secrets.yml (example content while editing)
db_user: appuser
db_pass: "S3cure!ChangeMe"
db_host: 10.10.20.15
api_token: "REPLACE_ME"
Step 2 : Confirm the file is encrypted on disk.
Command
head -n 5 secrets.yml

You should see the vault header and ciphertext. If you see plaintext, stop and fix your workflow before committing anything.

$ANSIBLE_VAULT;1.1;AES256
63343036626337373633623130316337306431393933623365323762313662613330656162666162
3437613934313637396537333663396161373535653733650a383132336231373431613765333834
64666130356161613161343364313834313565333235366535633333313433656365323131353631
Step 3 : Edit the vault file securely.
Command
ansible-vault edit secrets.yml

Vault decrypts in memory, opens your editor, and re-encrypts on save.

Step 4 : View decrypted contents to stdout (use carefully).
Command
ansible-vault view secrets.yml

This prints plaintext. Treat it like you would treat cat on a private key.

Step 5 : Create a playbook that loads the vault file via vars_files.
File
# vault-playbook.yml
- name: Test vault secrets
  hosts: localhost
  gather_facts: false
  vars_files:
    - secrets.yml
  tasks:
    - name: Show DB connection target
      debug:
        msg: "DB={{ db_user }}@{{ db_host }}"

The vault file is decrypted at run time when you provide the vault password.

Step 6 : Run the playbook and provide the vault password.
Command
ansible-playbook vault-playbook.yml --ask-vault-pass
Vault password:

PLAY [Test vault secrets] ******************************************************

TASK [Show DB connection target] ***********************************************
ok: [localhost] => {
    "msg": "DB=appuser@10.10.20.15"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0
Step 7 : Rotate the vault password (rekey).
Command
ansible-vault rekey secrets.yml

Rekey changes the password used to decrypt this file. This is a normal control for rotation workflows.

Common breakpoints

Playbook says it cannot decrypt the file

You either provided the wrong vault password, or the file was encrypted with a different vault secret. Rekey requires the current password to rotate.

You accidentally committed secrets in plaintext

Treat it as a leak. Remove the secret from history and rotate credentials. Vault prevents this scenario, but it does not fix it after the fact.

You ran view in a recorded or shared terminal

Avoid printing secrets to stdout. Prefer using secrets in tasks without exposing values, and avoid debug with sensitive variables.

Cleanup checklist

  • Delete the vault file if this was a throwaway exercise.
  • Delete the test playbook if you are keeping the repo clean.
Commands
rm -f secrets.yml vault-playbook.yml

Reference

  • ansible-vault create <file> : Create a new encrypted file (prompts for password, opens editor).
  • ansible-vault edit <file> : Edit an encrypted file (decrypts in memory, re-encrypts on save).
  • ansible-vault view <file> : View decrypted content to stdout.
  • ansible-vault rekey <file> : Rotate the vault password for a file.
  • ansible-playbook <playbook> --ask-vault-pass : Prompt for vault password during a run.
  • vars_files: : Load variables from external YAML files (including vault files).