Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #223: Generate a random default root password #465

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
7 changes: 5 additions & 2 deletions defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
---
# Set a random password.
mysql_password: "{{ lookup('password', '/dev/null length=20 chars=ascii_letters') }}"
colans marked this conversation as resolved.
Show resolved Hide resolved

# Set this to the user ansible is logging in as - should have root
# or sudo access
mysql_user_home: /root
mysql_user_name: root
mysql_user_password: root
mysql_user_password: "{{ mysql_password }}"
colans marked this conversation as resolved.
Show resolved Hide resolved

# The default root user installed by mysql - almost always root
mysql_root_home: /root
mysql_root_username: root
mysql_root_password: root
mysql_root_password: "{{ mysql_password }}"

# Set this to `true` to forcibly update the root password.
mysql_root_password_update: false
Expand Down
42 changes: 30 additions & 12 deletions tasks/secure-installation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,56 @@
check_mode: false
when: mysql_install_packages | bool or mysql_root_password_update

- name: Set the .my.cnf file path.
set_fact:
mysql_root_cnf_path: "{{ mysql_root_home }}/.my.cnf"

- name: Copy .my.cnf file with root password credentials.
template:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In terms of backwards compatibility, could this break that for existing installs?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I think you're mostly concerned about here, and rightly so, is if there's a password already there (for example, the old default one). I tested that by changing it (and leaving the rest of the file alone). Both <5.7 and 5.7+ were skipped so we're all good there. force: no is the default so I think we're good. If the file's already there, it won't touch it. It'll just use what's there for running operations, which will just work.

src: "root-my.cnf.j2"
dest: "{{ mysql_root_cnf_path }}"
owner: root
group: root
mode: 0600
when: mysql_install_packages | bool or mysql_root_password_update
register: mysql_root_password_setting

- name: Fetch the .my.cnf file containing the root password
slurp:
src: "{{ mysql_root_cnf_path }}"
register: mysql_root_cnf_file

# It would be cleaner to use the `ini` lookup plugin, but that only works
# locally so we'd have to copy the file first, which we'd rather not do because
# it contains secrets.
- name: Extract the root password from .my.cnf
set_fact:
mysql_root_password_generated: "{{ mysql_root_cnf_file['content'] | b64decode | regex_findall('password=\"(.+)\"') | first }}"

# Note: We do not use mysql_user for this operation, as it doesn't always update
# the root password correctly. See: https://goo.gl/MSOejW
# Set root password for MySQL >= 5.7.x.
- name: Update MySQL root password for localhost root account (5.7.x).
shell: >
mysql -u root -NBe
'ALTER USER "{{ mysql_root_username }}"@"{{ item }}"
IDENTIFIED WITH mysql_native_password BY "{{ mysql_root_password }}"; FLUSH PRIVILEGES;'
IDENTIFIED WITH mysql_native_password BY "{{ mysql_root_password_generated }}"; FLUSH PRIVILEGES;'
with_items: "{{ mysql_root_hosts.stdout_lines|default([]) }}"
when: >
((mysql_install_packages | bool) or mysql_root_password_update)
and ('5.7.' in mysql_cli_version.stdout or '8.0.' in mysql_cli_version.stdout)
and (mysql_root_password_setting.changed is true)

# Set root password for MySQL < 5.7.x.
- name: Update MySQL root password for localhost root account (< 5.7.x).
shell: >
mysql -NBe
'SET PASSWORD FOR "{{ mysql_root_username }}"@"{{ item }}" = PASSWORD("{{ mysql_root_password }}"); FLUSH PRIVILEGES;'
'SET PASSWORD FOR "{{ mysql_root_username }}"@"{{ item }}" = PASSWORD("{{ mysql_root_password_generated }}"); FLUSH PRIVILEGES;'
with_items: "{{ mysql_root_hosts.stdout_lines|default([]) }}"
when: >
((mysql_install_packages | bool) or mysql_root_password_update)
and ('5.7.' not in mysql_cli_version.stdout and '8.0.' not in mysql_cli_version.stdout)

# Has to be after the root password assignment, for idempotency.
- name: Copy .my.cnf file with root password credentials.
template:
src: "root-my.cnf.j2"
dest: "{{ mysql_root_home }}/.my.cnf"
owner: root
group: root
mode: 0600
when: mysql_install_packages | bool or mysql_root_password_update
and (mysql_root_password_setting.changed is true)

- name: Get list of hosts for the anonymous user.
command: mysql -NBe 'SELECT Host FROM mysql.user WHERE User = ""'
Expand Down