Saving login credentials within ansible playbooks.
There are at least 4 possible methods on howto handle secret data within ansible playbooks.
The first 2 methods have been deprecated with the release of ansible 2.3. However they are still working, also within ansible 2.4 and is the simplest method to authenticate to a network device. The example is self explaining. The credentials are "cisco" and "cisco". I do not need to mention that it is generally a bad idea to save credentials in a plain text file like below. However it might be helpful to start with the simplest authentication method within a playbook.
#
# 01-show-version-simple-auth.yml
#
# As of ansible version 2.3 this method is deprecated
#
- hosts: test
connection: local
tasks:
- name: "Cisco IOS run show version"
ios_command:
commands: show version
username: cisco
password: cisco
The second example is similar to the first. This method is called top-level authentication. The credentials are declared at the top of the playbook. The advantage of this authentication method compared to the first one is, that within a playbook the username and password are defined at the top and stored in a variable called cli. The authentication within the playbook is called with a keyword provider. It is somehow simpler and less prone to error, and the credentials need to be declared only one time.
#
# 02-show-version-top-level-auth.yml
#
# As of ansible version 2.3 this method is deprecated
#
- hosts: staging
connection: local
vars:
cli:
username: cisco
password: cisco
tasks:
- name: "Cisco IOS run show version"
ios_command:
commands: show version
provider: "{{ cli }}"
The third authentication method has been released with ansible 2.4 and is at the time of writing the method that will replace the both that are described above. This is my favourite method of authentication since the authetication credentials are not stored at all. Credentials are called from the command line with the execution of the ansible playbook.
Execution of playbook for the user -u cisco with password -k cisco
ansible-playbook -i hosts show-version.yml -u cisco -k
Execution for the current username echo $USER
ansible-playbook -i hosts show-version.yml -k
#
# 03-show-version-current-auth.yml
#
- hosts: staging
connection: local
tasks:
- name: "Cisco IOS run show version"
ios_command:
commands: show version
The fourth authentication method uses a vault. A ansible vault is a encrypted file where the credentials are stored. A ansible-vault creation works with following command:
ansible-vault create vault.yml
After that the passphrase will be asked. With that passphrase or Vault password access to the file is given.
The content of the unencrypted vault.yml looks like here:
---
username: cisco
password: cisco
The content of the encrypted vault file is following:
# more test.yml
$ANSIBLE_VAULT;1.1;AES256
33643762323531343035333136623235373639316232306666623137323265386337366631353864
3464653430656533353862643438363530613164616336620a393261346530386335386262623233
64363163646538376365643832663333363834383465633135646638643038303330663134303664
3339363161373433390a346365323537383736363265383636663136323930323061643536303230
37303533323766396666643063656565616237373033303737653833393366623537666434373434
6132376365663062343030306462386339303064376365303732
After the vault file with encrypted credentials is stored in a file called vault.yml in the root of the ansible directory, point the playbook to the vault.yml file where credentials username and password are stored. This way one does not need to add an additional command line option while running the playbook. Additionally both credential variables have been aggregated in the var {{ cli }} for further usage. This is the same as described in the top-level authentication file 02-show-version-top-level-auth.yml.
#
# 04-show-version-vault-auth.yml
#
- hosts: staging
connection: local
gather_facts: no
vars_files:
- vault.yml
vars:
cli:
username: "{{ username }}"
password: "{{ password }}"
tasks:
- name: "Cisco IOS run show version"
ios_command:
commands: show version
provider: "{{ cli }}"
Peter Spryada has written a great article about Network device authentication with ansible 2.3, dealing with additional examples available on different networking device platforms, using API or HTTP authentication.