9

I'm trying to read the database password on a remote host from the file /etc/mysql/debian.cnf. Format of the file is below. Is there a way to parse out the password field so I can drop a mysql user via Ansible?

# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host     = localhost
user     = root
password = 5unnyv4l3
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host     = localhost
user     = root
password = 5unnyv4l3
socket   = /var/run/mysqld/mysqld.sock
basedir  = /usr
Server Fault
  • 3,714
  • 12
  • 54
  • 89

3 Answers3

16

It looks like the 'slurp' module will work for your requirements: https://docs.ansible.com/ansible/latest/modules/slurp_module.html

- name: extract password from file
  slurp:
    src: /etc/mysql/debian.cnf
register: mypasswordfile

- name: Set User Password
  user: name=newUser
    password="{{ passwordfile['content'] | b64decode | regex_findall('password = \"(.+)\"') | first }}"

Edited after testing and fixing.

colan
  • 520
  • 5
  • 9
relevantRope
  • 401
  • 2
  • 7
  • 1
    Uh..That second task actually creates a new user account (typo with `passwordfile` too), but I think I see what you're trying to do.. working on it. I've got this task: `msg: "Password is {{ mypasswordfile['content'] | b64decode | regex_findall('\bpassword\b') }}"`. It prints`Password is []` – Server Fault Feb 08 '19 at 14:50
  • I just edited it with a fix. Basically, `regex_findall()` returns an list so it's necessary to grab the first (and only) item. – colan Jul 23 '19 at 21:00
5

If the file is local to the ansible system you can use the ini lookup which will read in values from a ini style file. If your file is remote you can use fetch/slurp to pull a copy to the local system.

I would guess the lookup would be something like

- debug: msg="Password is {{ lookup('ini', 'password section=client file=my.cnf') }}"
Zoredache
  • 130,897
  • 41
  • 276
  • 420
  • Thanks, this is really close. It's printing `"msg": "Password is vRkfmDfYX2g3wXYt"` which isn't actually the password. Tried `| b64decode` on it but made it worse. Any thoughts? – Server Fault Feb 08 '19 at 14:57
  • Hrm, I might try using the lookup against a different attribute to see if you can look up the user/host or something. – Zoredache Feb 08 '19 at 17:38
  • Try `{{ lookup('ini', 'password section=client file=my.cnf') | password_hash('sha512') }}` for input into the user module. The password from the file is not encoded, it's plaintext. – Gothrek Feb 13 '19 at 19:35
0

You can use the command or shell module and do it with awk/sed, someting like:

- name: get the value in the block on the file
  command: >
         awk -F ' *= *' '{ if ($1 ~ /^\[/) section=$1;
         else if ($1 ~ /^password/ && section ~ /^\[client\]$/ ) print $2 }'
         "{{ file_path }}"
  register: password_value

In this case to handle a comment in the same line you can do

- name: setting the password without comments
  set_fact:
    password: "{{ password_value.stdout.split('#')[0] }}"