22

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?

30

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.

|improve this answer|||||
9

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.

|improve this answer|||||
  • I'm getting an error when i use that directive.. Any idea what i'm doing wrong? ERROR: no_log is not a legal parameter in an Ansible task or handler – Bouke Versteegh Jun 13 '15 at 13:06
  • 2
    Turns out I had an old version of ansible! To fix (on ubuntu): sudo apt-add-repository ppa:ansible/ansible, sudo apt-get update, sudo apt-get install ansible – Bouke Versteegh Jun 13 '15 at 13:12
  • Same problem for me but I can't make n_log: true to work as expected. My Ansible version is 1.7.2. What is yours ? – jmcollin92 Jun 28 '16 at 12:51
  • @jmcollin92 I currently use 2.1. There is a guide here on how to install the latest version from source. I use that as ansible is still maturing. – claus Jun 30 '16 at 12:24
  • You probably also want to set diff: no – DylanYoung Dec 17 '19 at 17:52
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

|improve this answer|||||
2

I solved by upgrading Ansible version to 1.6.1

sudo pip install ansible==1.6.1
|improve this answer|||||
2

As per Ansible docs:

log_path

If present and configured in ansible.cfg, Ansible will log information about executions at the designated location. Be sure the user running Ansible has permissions on the logfile:

log_path=/var/log/ansible.log 

This behavior is not on by default. Note that ansible will, without this setting, record module arguments called to the syslog of managed machines. Password arguments are excluded.

Sounds like setting log_path on your control node will result in not having logs on destination nodes.

|improve this answer|||||
  • Actually I have an ansible.cfg in my local dir, where I call ansible, setting the log_path. The local log is created alright and uptodate after a new run (logging works). This does not (even though the doc that you pointed out promises it) prevent the remote host from logging. Also the statement "Password arguments are excluded" seems to be not 100% true? Is this a bug (or even two)? – claus Apr 13 '15 at 10:33
  • 2
    @claus "password arguments excuded" only applies to modules where password argument is explicit. There is no way for ansible to know which argument would be password and which wouldn't with general commands like debconf, shell, raw, etc. – Droopy4096 Apr 13 '15 at 16:27
  • Please scroll to the right in my initial playbook. It says vtype='password' . That should be explicit enough IMHO? I assume that the log message is also created by the debconf module. – claus Jun 30 '16 at 12:23
  • This is incorrect. The documentation should more accurately say "Note that ansible will, regardless of this setting, record module arguments called to the syslog of managed machines." – augurar Sep 14 '16 at 17:34
1

This is an additon to the answer of TheDESTROS from this thread:

  1. write a template, which wraps the command with a secret:

wrapper-script.sh.j2

echo {{ secret_eg_from_ansible_vault }} | su - "ls -l"
  1. Invoke the wrapper script and remove it at once:
- name: create template
  template:
    src: wrapper-script.sh.j2
    dest: /tmp/wrapper-script.sh
    mode: 0700
  no_log: True
- name: invoke command with secret and remove it
  shell: /tmp/wrapper-script.sh; rm -f /tmp/wrapper-script.sh

You need a little bit less code and can thee stdout of the commands in your logs. There is only one caveeat, if a secret is in the commands stdout. If you want to avoid the external template, the copy module with the parameter content might help to write a small wrapper script in the fly.

|improve this answer|||||
  • How will it hide passwords? when I run wsadmin.bat for WebSphere, the output will still be. By the same token, it’s quite not obvious what is better - fewer lines of code or less understanding of what is done in it. When you create a "template" file and execute something from it, it is absolutely not clear why this was done if the code is being watched by another person. – TheDESTROS Mar 4 at 9:17
  • In addition, the password file will be hosted on the server, which, to some extent, may be unacceptable. – TheDESTROS Mar 4 at 9:19
1

The no_log: true approach is to be used as last-resort if other attempts fail because it will make the task execution totally opaque and you will have no clue when it fail.

Security practices recommend giving credentials from stdin or when not possible using credential files (or even executables).

Here is an example on how to perform a secure podman login by avoiding exposing the password:

- name: secured login
  become: true
  command: >
    podman login --username={{ user }} --password-stdin ...
  args:
    stdin: "{{ secret }}"
  register: result

With this, the secret will not be exposed, in result but you will still be able to see the output of the command.

Most of tools needing login do implement one of the more secured approaches mentioned. Using credentials on CLI in code is like have 123456 as your bank password.

|improve this answer|||||
0

The environment argument in the playbook is suitable for keeping a secret hidden. The secret is not printed even with -vvvv. It is available for the whole play.

- hosts: control_host
  gather_facts: no
  become: no
  environment:
    PASSWORD: "{{ password }}"
  tasks:

   - local_action: "shell ./foobar.sh ${PASSWORD}"

   - local_action: "shell echo ${PASSWORD}"

output:

ansible-playbook -i ... playbooks/demo.yml -v

PLAY [control_host] *********************************************************************************

TASK [shell] *********************************************************************************
changed: [localhost -> localhost] => {
    "changed": true,
    "cmd": "./foobar.sh ${PASSWORD}",
    "delta": "0:00:00.013467",
    "end": "2020-04-03 17:42:03.950534",
    "rc": 0,
    "start": "2020-04-03 17:42:03.937067"
}

TASK [shell] *********************************************************************************
changed: [localhost -> localhost] => {
    "changed": true,
    "cmd": "echo ${PASSWORD}",
    "delta": "0:00:00.005925",
    "end": "2020-04-03 17:42:04.319085",
    "rc": 0,
    "start": "2020-04-03 17:42:04.313160"
}

STDOUT:

my_secret_password
|improve this answer|||||
New contributor
selle is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.