What problem do Ansible vault IDs (the --vault-id label@source form) solve, and how does Ansible decide which password to use for a given encrypted file?
answer
- label@source, several per run
- label lives in the file header
- 1.2 header carries the label
- matching identity tried first, then fallback
- vault_id_match makes it strict
basics
~20 sA vault ID pairs a label with a password source, such as --vault-id prod@prompt, so one run can carry several vault passwords at once. The label is written into the encrypted file's header and tells Ansible which password to try first.
solid answer
~50 sBefore vault IDs, a run had exactly one vault password, so separating dev secrets from production secrets meant separate runs or one shared password. `--vault-id` takes a `label@source` pair — the source being `prompt`, a password file path, or an executable script — and you can pass several. When you encrypt with a labelled identity the label is recorded in the file header, which becomes `$ANSIBLE_VAULT;1.2;AES256;prod` instead of the unlabelled `1.1` form. At decryption time Ansible matches that label against the identities you supplied and tries the matching one first; if it does not match or fails, by default it falls back to trying the others in order. That fallback is a convenience, not a security control — you can require an exact match by enabling the `vault_id_match` setting. When several identities are available for encryption, `--encrypt-vault-id` says which one to use.
code
bash · 10 lines# one run, two passwords: dev from a file, prod typed interactively
ansible-playbook site.yml \
--vault-id dev@/home/me/.vault/dev_pass \
--vault-id prod@prompt
# encrypt a file under a specific identity (label is stamped in the header)
ansible-vault encrypt --vault-id prod@prompt group_vars/prod/vault.yml
# set the identities once instead of repeating flags
export ANSIBLE_VAULT_IDENTITY_LIST="dev@/home/me/.vault/dev_pass,prod@prompt"go deeper
Recognise the --vault-id label@source syntax and know it exists so one command can carry more than one vault password, for example dev and prod at the same time.
Explain the mechanics: the label is stamped into the file header as the 1.2 format field, the matching identity is tried first, and unmatched identities are tried as fallback unless you change that setting.
Show how you use it in practice — separate passwords per environment so a developer cannot decrypt production, identities configured once via the identity list, and rekey used to move a file between identities.
Own the limits of the scheme: labels are hints, not authorization, and a shared production password has no revocation or audit story — decide when key separation is enough and when the estate needs a real secret manager.
## The problem A single vault password per run forces an uncomfortable choice. Either every environment shares one password — so the intern who can run the dev playbook can also decrypt production credentials — or each environment gets its own password and no playbook may ever touch two environments in one run. Neither is satisfying for a repository that holds `group_vars/dev/vault.yml` and `group_vars/prod/vault.yml` side by side. Vault IDs remove the constraint. An identity is a `label@source` pair, and you may supply as many as you like: ```bash ansible-playbook site.yml \ --vault-id dev@~/.vault/dev_pass \ --vault-id prod@prompt ``` The label is a free-form name you choose (`dev`, `prod`, `ci`, `legacy`). The source is one of three things: the literal `prompt`, which asks interactively and shows the label in the prompt so you know which password is wanted; a path to a file containing the password; or a path to an executable script, whose stdout Ansible takes as the password — that is the extension point for fetching from an external secret manager. ## How the label travels with the file Encrypting with a labelled identity stamps the label into the header. An unlabelled file starts: ``` $ANSIBLE_VAULT;1.1;AES256 ``` while one encrypted under the `prod` identity starts: ``` $ANSIBLE_VAULT;1.2;AES256;prod ``` The `1.2` format version exists precisely to carry that fourth field. Note what the label is and is not: it is a plaintext hint sitting next to the ciphertext, readable by anyone with the repository. It is not part of the key and not an authorization check — it simply tells Ansible which of the passwords you already possess is likely to be the right one. ## The matching algorithm, and the part people get wrong When Ansible needs to decrypt content it looks at the header label and compares it against the identities available in the run. The matching identity is tried first, which is the performance and usability win — no needless prompts, no wasted attempts. If the label matches nothing, or the matching password fails, the default behaviour is to try the remaining identities in the order they were supplied. That fallback is where the misconception lives. Candidates often say that labelling a file `prod` means only the `prod` password can open it. It does not. If someone runs with both the dev and prod identities present, a file labelled `prod` will still open under whichever supplied password actually decrypts it. Ansible exposes a configuration setting, `vault_id_match`, that turns off the fallback and requires the label to match — worth naming, because it shows you know the default is permissive. ## Encrypting when several identities are loaded Decryption can try several passwords, but encryption must pick exactly one. If more than one identity is available, tell Ansible which to use: ```bash ansible-vault encrypt --vault-id prod@prompt group_vars/prod/vault.yml # or, with several identities configured, select one explicitly ansible-vault encrypt --encrypt-vault-id prod group_vars/prod/vault.yml ``` Without that, with multiple identities and no default, the command errors rather than guessing — which is the right behaviour, since guessing would silently lock a file under the wrong password. ## Making it the default Typing several `--vault-id` flags on every invocation is how people end up sharing one password again. The identity list can be set once in `ansible.cfg` under `vault_identity_list`, or via the `ANSIBLE_VAULT_IDENTITY_LIST` environment variable, as a comma-separated list of the same `label@source` pairs. A CI job then sets one environment variable and every playbook invocation inherits the right identities, while a developer's local config lists only the environments they are entitled to. ## Where the boundary really is Be honest in an interview about what this buys. Vault IDs give you key separation — production secrets encrypted under a password that developers do not hold — plus readable prompts and a way to run across environments in one pass. They also give you a rotation path: `ansible-vault rekey --new-vault-id` moves a file from one identity to another. What they do not give you is per-user identity, revocation, or an audit trail; a label is a hint in a header, and anyone holding the production password holds all of production's secrets.
- Does labelling a file with the prod vault ID prevent it being decrypted by another password?No. The label is a plaintext hint that selects which identity Ansible tries first; by default it falls back to every other identity supplied to the run. Only enabling the `vault_id_match` setting makes the label required rather than advisory, and even then it is a client-side convention, not access control.
- How would you move an existing encrypted file from the dev identity to the prod identity?Use `ansible-vault rekey` with the current identity for reading and `--new-vault-id prod@prompt` for writing. The plaintext content is unchanged; the file is simply re-encrypted under the new password and its header label is updated. Anyone still holding the old password can read the old commit, so treat it as a re-encryption, not a rotation of the secret itself.
- How do you avoid typing several --vault-id flags on every command?Set the identities once as a comma-separated `label@source` list in `ansible.cfg` under `vault_identity_list`, or export `ANSIBLE_VAULT_IDENTITY_LIST`. CI sets it as part of the job environment; a developer's local config lists only the environments they are entitled to decrypt.
saying these in an interview costs you the question
- Thinking the vault ID label enforces which password may decrypt a file
- Believing the label is part of the encryption key
- Assuming a run can hold only one vault password
- Expecting encryption to guess an identity when several are loaded
- Treating vault IDs as per-user identity or an audit trail