Access ansible passwords securely with keyring from macOS keychain.
Install keyring with pip in your terminal
python3 -m pip install keyring
Add ansible password and check that it works.
keyring set [system] [username]
keyring get [system] [username]
All examples here uses the password: test
keyring set test test
Install community.general.keyring
The keyring plugin allows you to access data stored in the OS provided keyring/keychain. The keyring plugin is part of the Community General Collection. To use it you need to install community.general.
Collection Path. By default the community collection is installed in ~/.ansible/collections/ folder on macOS.
Check install path:
ansible-config dump | grep COLLECTIONS_PATHS
Costum Path:
ansible-galaxy collection install community.general -p [Your_Costum_Path]
Install from terminal:
ansible-galaxy collection install community.general
Verify and check community.general installation version:
ansible-galaxy collection verify community.general -vvv
NB! community.general can also be installed as part of requirements.txt in local .env folder.
community.general can be accessed in a yaml files like this:
collections:
- community.general
Check keyring doc's
ansible-doc -t lookup keyring
community.general.keyring examples:
- name : output secrets to screen (BAD IDEA)
ansible.builtin.debug:
msg: "Password: {{item}}"
with_community.general.keyring:
- 'servicename username'
ansible_become_pass=={{ lookup('community.general.keyring','test test') }}
ansible-playbook playbook_keyring.yml
NB! Fails on some macOS systems with more versions of python installed. See issue #1
Use Keyring to set a 'test' acount with label 'test':
keyring set test test
keyring get test test
Use get_pass.sh with macOS 'security' cli tool or get_pass.py with keyring to retrieve a password.
Remember to enable execute bits on the scripts:
chmod +x get_pass.sh
chmod +x get_pass.py
The pipe lookup plugin:
ansible-doc -t lookup pipe
In order to test the get_pass.sh or get_pass.py scripts, uncomment the respective lines in playbook_pipe.yml
ansible-playbook playbook_pipe.yml
Use 'ansible_become_pass' in an inventory / host file or any other yaml file like this:
ansible_become_pass="{{ lookup('pipe', './get_pass.py') }}"
Using community.general scripts vault-keyring.py and vault-keyring-client.py with macOS Keyring / keychain
open ~/.ansible/collections/ansible_collections/community/general/scripts/vault/
This is a new type of vault-password script (a 'client') that takes advantage of and enhances the multiple vault password support.
If a vault password script basename ends with the name '-client', consider it a vault password script client.
A vault password script 'client' just means that the script will take a '--vault-id' command line arg.
The previous vault password script (as invoked by --vault-password-file pointing to an executable) takes no args and returns the password on stdout. But it doesnt know anything about --vault-id or multiple vault passwords.
The new 'protocol' of the vault password script takes a cli arg ('--vault-id') so that it can lookup that specific vault-id and return it's password.
Since existing vault password scripts don't know the new 'protocol', a way to distinguish password scripts that do understand the protocol was needed. The convention now is to consider password scripts that are named like 'something-client.py' (and executable) to be vault password client scripts.
The new client scripts get invoked with the '--vault-id' they were requested for. An example:
ansible-playbook --vault-id my_vault_id@contrib/vault/vault-keyring-client.py some_playbook.yml
That will cause the 'contrib/vault/vault-keyring-client.py' script to be invoked as:
contrib/vault/vault-keyring-client.py --vault-id my_vault_id
The previous vault-keyring.py password script was extended to become vault-keyring-client.py. It uses the python 'keyring' module to request secrets from various backends. The plain 'vault-keyring.py' script would determine which key id and keyring name to use based on values that had to be set in ansible.cfg. So it was also limited to one keyring name.
The new vault-keyring-client.py will request the secret for the vault id provided via the '--vault-id' option. The script can be used without config and can be used for multiple keyring ids (and keyrings).
On success, a vault password client script will print the password to stdout and exit with a return code of 0. If the 'client' script can't find a secret for the --vault-id, the script will exit with return code of 2 and print an error to stderr.
playbook_pipe.yml
playbook_vault.yml
/vars/api_key.yml
vault-keyring.py
vault-keyring-client.py
The original ansible-vault scripts are found in community.general scripts/vault folder (ie. ~/.ansible/collections/ansible_collections/community/general/scripts/vault/)
Copy vault-keyring.py and vault-keyring-client.py to your project or your ansible folder outside source control (~/.ansible/).
Change the python shebang line in vault-keyring.py and vault-keyring-client.py to reflect your python 3 path (#!/usr/bin/env python3).
chmod +x vault-keyring.py vault-keyring-client.py
[defaults]
vault_password_file = vault-keyring.py
[vault]
keyname = ansible_key_test
username = test_user
and the set password
./vault-keyring.py set
or
./vault-keyring-client.py --vault-id 'ansible_key_test' --username 'test_user' --set
./vault-keyring.py
./vault-keyring-client.py --vault-id 'ansible_key_test' --username 'test_user'
ansible-vault encrypt vars/api_key.yml
vault-keyring.py is automaticly used when defined in ansible.cfg
ansible-vault view vars/api_key.yml --vault-password-file vault-keyring.py
The below will also work as ansible-vault will automaticly detect and decrypt the vars/api_key.yml file with vault-keyring.py
ansible-vault view vars/api_key.yml
ansible-vault view vars/api_key.yml --vault-id [email protected]
ansible-playbook playbook_vault.yml --vault-password-file vault-keyring.py
ansible-playbook --vault-id vault-keyring.py playbook_vault.yml
vault-keyring.py is automaticly detected and used when the credentials is defined in ansible.cfg, so this will also work:
ansible-playbook playbook_vault.yml
ansible-playbook --vault-id [email protected] playbook_vault.yml
NB! Somehow vault-keyring-client.py could not see the test_user in ansible.cfg, but kept on using the current system $USER.
vault-keyring-client.py and vault-keyring.py uses 2 different methods to get 'username'. vault-keyring.py works nicely and vault-keyring-client.py not!
After implementing the vault-keyring method for getting usernames in vault-keyring-client.py, it now works according to the description in vault-keyring-client comments.
NB! It's recommended to put any password files / scripts outside source control ie. git project folder for better security - example path: ~/.ansible
Welcome to keyring documentation
ansible-vault
Encrypting content with Ansible Vault
community.general/scripts/vault