How can I stop ansible from writing passwords to the logfiles?

I am setting up a MySQL server and want Ansible to set the mysql-root password during installation.

With the help of the internet I came up with this solution:

- name: Set MySQL root password before installing
  debconf: name='mysql-server' question='mysql-server/root_password' value='{{mysql_root_pwd | quote}}' vtype='password'
- name: Confirm MySQL root password before installing
  debconf: name='mysql-server' question='mysql-server/root_password_again' value='{{mysql_root_pwd | quote}}' vtype='password'
- name: Install Mysql
  apt: pkg=mysql-server state=latest

mysql_root_pwd is a variable loaded from the Ansible Vault. This runs fine, but now on the server there are many lines in the log:

Apr 10 14:39:59 servername ansible-debconf: Invoked with value=THEPASSWORD vtype=password question=mysql-server/root_password name=mysql-server unseen=None
Apr 10 14:39:59 servername ansible-debconf: Invoked with value=THEPASSWORD vtype=password question=mysql-server/root_password_again name=mysql-server unseen=None

How can I stop Ansible from writing clear text passwords to the logfiles?


Solution 1:

To prevent a task with confidential information from being logged, in syslog or other, set no_log: true on the task:

- name: secret stuff
  command: "echo {{secret_root_password}} | sudo su -"
  no_log: true

The running of the task will still be logged, but with little details. Also, the module used has to support no_log, so test custom modules.

See Ansible FAQ for further details. It can be applied to an entire playbook, however the output gets a little nasty with "censored!" messages.

Solution 2:

The observed behaviour seems to be a bug in the debconf module. I filed a bug report.

The user bcoca at github pointed out that one can use the no_log: true directive in tasks, that set passwords, to prevent logging. This is a workaround, that works for me until the bug is fixed.

Solution 3:

There is a better way than just no_log: True

- name: write in string variables login and password
  set_fact:
    temp_user: "{{ USER_VAR }}"
    temp_pass: "{{ PASSWORD_VAR }}"


- name: Your operation with password in output
  shell: '/opt/hello.sh'
  ignore_errors: True
  no_log: True
  register: myregister

- debug:
    msg: '{{ myregister.stderr | regex_replace(temp_user) | regex_replace(temp_pass) }}'
  when: myregister.stderr != ""

- debug:
    msg: '{{ myregister.stdout | regex_replace(temp_user) | regex_replace(temp_pass) }}'
  when: myregister.stdout != ""

- fail:
    msg: "error shell /opt/hello.sh"
  when: myregister.stderr != ""

As you can see, you need to add:

ignore_errors: true
no_log: true

And then make the output of the result of the command with regex_replace, where:

USER_VAR - login variable

PASSWORD_VAR - password variable

With this approach, you will not only hide the passwords and logins, but also get the output of your operation