Subscribe to the feed

Ansible is a great tool to automate mundane or complex tasks. It also allows code reuse by passing variables to roles or collections. This is important when sharing code across a large base of users.

However, sometimes those variables are credentials that are specific to a user's access or password rather than a service account credential like you might use in Ansible Automation Platform. You wouldn't want to share sensitive credentials with your team, let alone place them into a Git repo for the world to see. Sometimes these variables are derived from an environment file, such as your .bashrc. And they could be things you need to access from the shell, not only in an Ansible playbook.

This is where Ansible Vault comes into play. Ansible Vault is a command-line tool that allows you to encrypt and decrypt any structured data file. In this article, I'll show you how to protect your shell environment variables while making them available for your typical Bash commands and your Ansible playbooks, roles, and collections.

[ Download now: A sysadmin's guide to Bash scripting. ]

Use encrypted environment variables with Ansible

First, create a .bash_vault file in your home directory:

$ touch ~/.bash_vault

Next, append the following code to your .bashrc file:

export EDITOR=vi

BASH_VAULT=${HOME}/.bash_vault

function bash_vault.load(){
  echo "Loading bash vault..."
  source <(ansible-vault view ${BASH_VAULT})
}

function bash_vault.edit(){
  ansible-vault edit ${BASH_VAULT}
}

function bash_vault.reload(){
  echo "Reloading bash vault..."
  source <(ansible-vault view ${BASH_VAULT})
}

After updating your .bashrc, create your secrets in the .bash_vault file. In this example, you want to keep your usernames, passwords, and destinations secret from prying eyes:

APP1_API_USERNAME='mike.wazowski'
APP1_API_PASSWORD='Ey3b4LL!'
APP1_API_URL='www.foo.com'

APP2_API_USERNAME='james.sullivan'
APP2_API_PASSWORD='H41rB4ll!'
APP2_API_URL='www.bar.com'

APP3_API_USERNAME='randall.boggs'
APP3_API_PASSWORD='Ch4m3l0N!'
APP3_API_URL='www.foobar.com'

export APP1_API_USERNAME APP1_API_PASSWORD APP1_API_URL APP2_API_USERNAME APP2_API_PASSWORD APP2_API_URL APP3_API_USERNAME APP3_API_PASSWORD APP3_API_URL

After updating your .bash_vault file, you must encrypt it using ansible-vault:

$ ansible-vault encrypt .bash_vault
New Vault password: ****
Confirm New Vault password: ****
Encryption successful

Now, validate you've encrypted the environment variables:

$ cat .bash_vault

$ANSIBLE_VAULT;1.1;AES256
66623436333962663336333666306230366230336465333865326363666232383365326233333836
6630393461333137633865303134616262353230636163330a386338366663633230343537303335
3635...shortened for brevity....

Reload your .bashrc file and reload the encrypted shell variables stored in .bash_vault using the functions available in your .bashrc file. You will be prompted for your Ansible Vault password:

$ source .bashrc
$ bash_vault.load
Loading bash vault...
Vault password: ****

Write a playbook showcasing how Ansible can access these variables:

- name: Example playbook to show vaulted shell variables
  hosts: localhost
  gather_facts: false
  become: false
  tasks:
  - name: Debug app1 shell variables
    ansible.builtin.debug:
        msg:
          - "{{ lookup('env','APP1_API_USERNAME') }}"
          - "{{ lookup('env','APP1_API_PASSWORD') }}"
          - "{{ lookup('env','APP1_API_URL') }}"

  - name: Debug app2 shell variables
    ansible.builtin.debug:
        msg:
          - "{{ lookup('env','APP2_API_USERNAME') }}"
          - "{{ lookup('env','APP2_API_PASSWORD') }}"
          - "{{ lookup('env','APP2_API_URL') }}"

  - name: Debug app3 shell variables
    ansible.builtin.debug:
        msg:
          - "{{ lookup('env','APP3_API_USERNAME') }}"
          - "{{ lookup('env','APP3_API_PASSWORD') }}"
          - "{{ lookup('env','APP3_API_URL') }}"

[ Write your first playbook in this hands-on interactive lab. ]

Finally, run the playbook to showcase the results:

$ ansible-playbook -i localhost, bash_vault_example.yml 

PLAY [Example playbook to show vaulted shell variables] ************************

TASK [Debug app1 shell variables] **********************************************
ok: [localhost] => {
    "msg": [
        "mike.wazowski",
        "Ey3b4LL!",
        "www.foo.com"
    ]
}

TASK [Debug app2 shell variables] **********************************************
ok: [localhost] => {
    "msg": [
        "james.sullivan",
        "H41rB4ll!",
        "www.bar.com"
    ]
}

TASK [Debug app3 shell variables] **********************************************
ok: [localhost] => {
    "msg": [
        "randall.boggs",
        "Ch4m3l30N!",
        "www.foobar.com"
    ]
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Use variables on the command line

But wait, these are shell environment variables, so you can also access them using the command line outside of Ansible.

Typically when users run commands, Bash stores them in command history. You can override this using set +o history or clear it using history -c, but sometimes you need the history to recall previously executed long commands more easily.

By using Ansible Vault-created environment variables, the history shows the variable name but not the variable value. To test this, first execute a command that uses one of the variables:

# Run a curl command with our encrypted shell variables
$ curl -o /dev/null -s -w "%{http_code}\n" ${APP1_API_URL}

# CURL RESULTS
200

Then review the history to check that it shows the variable name and not the variable value:

# Run the history command to check our shell variables
$ history|tail -2|grep -v history

# HISTORY RESULTS
1034 curl -o /dev/null -s -w "%{http_code}\n" ${APP1_API_URL}

Change the vaulted variables

If you need to add, delete, modify, or review your Ansible Vault-created environment variables, call the bash_vault.edit function:

$ bash_vault.edit

Once you've completed the updates, reload the shell variables using the bash_vault.reload function:

$ bash_vault.reload

Finally, when you're done, you can just log out and know that your sensitive shell variables are safe from prying eyes. This is possible because your variables are encrypted at rest.

[ Get started with automation controller in this hands-on interactive lab. ]

Words of caution

Your variables are only as secure as your security practices, so keep the following in mind:

  • Avoid logging your sensitive shell variables.
  • Avoid writing the environment variables to your logs when running tasks.
    • Use no_log=true in your Ansible tasks
    • Avoid using redirects to a log like > or |tee -a somelog

      Here's an example of using no_log=true to protect your sensitive information:
# Protect your creds using no_log
- name: Debug keep passwords private shell variables using nolog
  ansible.builtin.uri:
    url: "{{ destination_url }}"
    user: "{{ lookup('env','APP1_API_USERNAME') }}"
    password: "{{ lookup('env','APP1_API_PASSWORD') }}"
  no_log: true
  • Never reveal your environment variable to stdout.
  • Avoid printing your environment variables to stdout using the env command or echo commands. This is especially important, when:
    • Using a shared resource like Ansible Automation Platform
    • Using a shared system where others have admin access
    • A tool like tlog has been implemented for terminal session logging
# AVOID DOING THIS
$ env|grep APP
APP3_API_USERNAME=randall.boggs
APP1_API_PASSWORD=Ey3b4LL!
APP3_API_URL=www.foobar.com
APP3_API_PASSWORD=Ch4m3l30N!
APP2_API_PASSWORD=H41rB4ll!
APP1_API_URL=www.foo.com
APP2_API_URL=www.bar.com
APP2_API_USERNAME=james.sullivan
APP1_API_USERNAME=mike.wazowski

# AVOID DOING THIS
$ echo $APP1_API_PASSWORD
Ey3b4LL!

Wrap up

Keeping your personal data, such as web tokens, passphrases, and passwords, safe from prying eyes is imperative. In this article, you learned how to encrypt Bash shell variables with Ansible Vault for use inside and outside of Ansible playbooks. This article provides a straightforward solution for keeping your personal credentials and data private using Ansible Vault.


About the author

Randy Romero is a Senior Ansible Consultant and Red Hat Certified Architect at Red Hat where he specializes in IT automation with Ansible and Ansible Automation Platform.  He has experience in the cable, insurance, and loyalty-marketing industries, having performed multiple roles starting with junior Systems Administrator all the way to Cloud Architect with over 27 years of experience in the IT industry.    

Randy fervently advocates for automation with Ansible to increase an individual's ability to grow by removing mundane repeatable tasks that tend to stand in the way of a person's own professional development and growth.  He is also motivated in his mission to evangelize automation through Ansible by changing the minds of people who say "This is how we've always done it'.   In his spare time when he is not studying or working, he enjoys mentoring individuals (young and old)  seeking to achieve their Red Hat Certified System Administrator and Red Hat Certified Engineer certifications.  When he's not doing IT related things he enjoys watching/reading all things paranormal.

Read full bio
UI_Icon-Red_Hat-Close-A-Black-RGB

Browse by channel

automation icon

Automation

The latest on IT automation for tech, teams, and environments

AI icon

Artificial intelligence

Updates on the platforms that free customers to run AI workloads anywhere

open hybrid cloud icon

Open hybrid cloud

Explore how we build a more flexible future with hybrid cloud

security icon

Security

The latest on how we reduce risks across environments and technologies

edge icon

Edge computing

Updates on the platforms that simplify operations at the edge

Infrastructure icon

Infrastructure

The latest on the world’s leading enterprise Linux platform

application development icon

Applications

Inside our solutions to the toughest application challenges

Original series icon

Original shows

Entertaining stories from the makers and leaders in enterprise tech