Often configuring a system involves running scripts and passing passwords as a parameter. If all goes well, this is fine, Ansible just reports the task has changed. If not, the password is logged, which is bad if the output is being sent to people who shouldn’t know it. Here are some thoughts on how to get round that.

Setup

Start with the following playbook for demonstration purposes:

1
2
3
4
5
6
7
8
9
---
 -  hosts: 127.0.0.1
    connection: local
    tasks:
    - name: This works
      command: "echo This is my secret password"

    - name: This fails
      shell: "echo This is my secret password && false"

And run it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ ansible-playbook  play.yml 

 [WARNING]: provided hosts list is empty, only localhost is
available. Note that the implicit localhost does not match 'all'


PLAY [127.0.0.1] ***********************************************

TASK [Gathering Facts] *****************************************
ok: [127.0.0.1]

TASK [This works] **********************************************
changed: [127.0.0.1]

TASK [This fails] **********************************************
fatal: [127.0.0.1]: FAILED! => {"changed": true,
"cmd": "echo This is my secret password && false",
"delta": "0:00:00.003950", "end": "2019-09-27 14:59:52.194098",
"msg": "non-zero return code", "rc": 1,
"start": "2019-09-27 14:59:52.190148", "stderr": "",
"stderr_lines": [], "stdout": "This is my secret password",
"stdout_lines": ["This is my secret password"]}

PLAY RECAP *****************************************************
127.0.0.1 : ok=2    changed=1    unreachable=0    failed=1
   skipped=0    rescued=0    ignored=0   

Oops, my secret password has been logged to the standard output. If this is picked up by logging software it could be stored where people who shouldn’t know the password can see it.

Hiding the password

I will just change the two tasks to set no_log:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
---
 -  hosts: 127.0.0.1
    connection: local
    tasks:
    - name: This works
      command: "echo This is my secret password"
      no_log: True

    - name: This fails
      shell: "echo This is my secret password && false"
      no_log: True

And run it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
$ ansible-playbook  play.yml 
 [WARNING]: provided hosts list is empty, only localhost is
available. Note that the implicit localhost does not match 'all'

PLAY [127.0.0.1] ************************************************

TASK [Gathering Facts] ******************************************
ok: [127.0.0.1]

TASK [This works] ***********************************************
changed: [127.0.0.1]

TASK [This fails] ***********************************************
fatal: [127.0.0.1]: FAILED! => {"censored": "the output has been
hidden due to the fact that 'no_log: true' was specified for this
result", "changed": true}

PLAY RECAP ******************************************************
127.0.0.1 : ok=2    changed=1    unreachable=0    failed=1
   skipped=0    rescued=0    ignored=0   

Brilliant" My password isn’t logged!. But, I have an error in my script that I want to debug. One of those really annoying ones where it works from the command prompt but not from Ansible. If only I could see the output, I would be able to debug it.

Hide the password when I want to

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
---
 -  hosts: 127.0.0.1
    connection: local
    tasks:
    - name: This works
      command: "echo This is my secret password"
      no_log: "{{ showpass is not defined }}"

    - name: This fails
      shell: "echo This is my secret password && false"
      no_log: "{{ showpass is not defined }}"

Here I have introduced a variable. If it isn’t defined it is false and produces the censored output as above. But if I define the variable and run it, as I do below, I get the error message (including the password) as at the top:

1
ansible-playbook --extra-vars "showpass=True" play.yml