Search code examples
macosansiblekeychainansible-vault

ansible-vault with multiple ids and macOS keychain


My goal is to use ansible-vault with multiple IDs (e.g. dev and prod) and retrieve the correct password (for dev or prod) from macOS keychain.

I have tried many configuration combinations, but the most promising seems to be what I describe here. Unfortunately, this is, like everything else I have tried, not working.

I have a script called vault-keyring-client.py, fetched from Github which is executable and stored as ~/.vault/vault-keyring-client.py.

Also, I set the environment variable ANSIBLE_VAULT_PASSWORD_FILE to this full path.

The macOS keychain holds two "generic password" entries, one for dev and one for prod.

Now, I would expect the following command to work, meaning to output the encrypted string for whatever is input via STDIN:

ansible-vault encrypt_string --vault-id dev

I have also tried the very similar command

ansible-vault encrypt_string --vault-id dev --encrypt-vault-id dev

to even more clearly indicate what I am trying to do; the result is the same:

I am getting an error claiming that

vault-keyring-client could not find key="default" for user="<my-username>" via backend="macOS Keyring"

According to my understanding ansible-vault should call the mentioned script (because it is set in ANSIBLE_VAULT_PASSWORD_FILE) and pass it the parameter --vault-id dev (because this is what I give it on the CLI). With this, the script should return the password it finds in the keychain.

So my question is: why is ansible-vault looking for a key (password) called default in the keychain when I clearly indicate that I want dev?

The more complete output/error looks as follows:

[WARNING]: Error getting vault password file (None): The vault password file <cwd>/mgm/dev was not found
[WARNING]: Error in vault password file loading (default): Vault password client script ~/.vault/vault-keyring-client.py did not find a secret for vault-id=default: b'vault-keyring-client could not find key="default" for user="<my-username>" via backend="macOS Keyring"\n'
ERROR! Vault password client script ~/.vault/vault-keyring-client.py did not find a secret for vault-id=default: b'vault-keyring-client could not find key="default" for user="<my-username>" via backend="macOS Keyring"\n'

ansible-vault seems to be looking for a (password) file called dev in the current working directory (and correctly detects that this does not exist) but then stops respecting the dev ID and continues to look for something called default...

I know that not all hope is lost, because the following command actually does work:

ansible-vault encrypt_string --vault-id dev@~/.vault/vault-keyring-client.py

It is just a mouthful to type and I do not see why this should make a/the difference...

BTW: I am using ansible version 2.14.5.


Solution

  • Your problem is that you are using the env var ANSIBLE_VAULT_PASSWORD_FILE which declares a single default password (used without vault-id to say this fast...) instead of ANSIBLE_VAULT_IDENTITY_LIST which is the one dedicated for using several ids.

    Just unset the prior and set the latest to the correct list of ids with their respective password files. Since you are using a script, it will receive the id and is able to reply with the correct password. So you basically use the same file for each id:

    unset ANSIBLE_VAULT_PASSWORD_FILE
    export ANSIBLE_VAULT_IDENTITY_LIST="dev@${HOME}/.vault/vault-keyring-client.py,\
    staging@${HOME}/.vault/vault-keyring-client.py,\
    prod@${HOME}/.vault/vault-keyring-client.py"