ansible-role-mysql
ansible-role-mysql copied to clipboard
Default insecure passwords seems bad
I think that setting a default password of 'root' is dangerous. Instead, it might be worth considering:
- aborting with an error if no password is defined
- setting a large random one if none is defined
That should reduce the risk of people ending up with an insecure setup because they were in a hurry or something. Relatedly, it could be interesting to have a little aside in the docs on how to securely create a password file for when you drop this role in as a git submodule, and so want to avoid making changes to it if possible.
I think that setting a default password of 'root' is dangerous.
At least it's more secure than MySQL's traditional default of having no password :)
I've considered doing something like this from time to time... but it's difficult to think of a way to randomize it (where it's random on first run, then consistent on future runs), and it's also just security-through-obscurity to simply set a more secure default.
Throwing a warning if it's root, I might be amenable to, since it would be the least invasive and most reliable way of highlighting insecure passwords.
But one thing to keep in mind is that many people (myself included) end up using the defaults for things like one-off database environments where we need to build something quick, run some commands, then tear it down. I usually either use 'root' or '' (no password) for that, just because it's fast and works quickly with defaults in many of the downstream tools I use with MySQL...
Presumably the root password is only set if the .my.cnf exists (excluding that override option), so if a random one were generated, it would be set and written into that file the first time, and wouldn't change again?
But even a loud warning would be enough I think.
Thanks for the role btw, it's a very handy thing for me finally getting my wordpress installation ansibleised :)
maybe optionally prompting for a password based on config parameter. this would not break it for people just needing an easy way to set a password and still allow for a bit more control over access to password.
This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution!
Please read this blog post to see the reasons why I mark issues as stale.
This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details.
@geerlingguy wrote:
I've considered doing something like this from time to time... but it's difficult to think of a way to randomize it (where it's random on first run, then consistent on future runs), and it's also just security-through-obscurity to simply set a more secure default.
Agreed on those points. The solution here is to do the following:
- Set a random password on each run (unless there's already one there and there's no reason to change it).
- Place the generated password in
/root/.my.cnf.
But one thing to keep in mind is that many people (myself included) end up using the defaults for things like one-off database environments where we need to build something quick, run some commands, then tear it down. I usually either use 'root' or '' (no password) for that, just because it's fast and works quickly with defaults in many of the downstream tools I use with MySQL...
As proven time and time again, with routers and other IoT devices for example, setting passwords to common defaults is a terrible idea.
For this particular use case, you don't need to know what the password is. It'll be in /root/.my.cnf, which can be accessed indirectly by running sudo -H mysql. That logs you in as root, with whatever root password is in the file. It can be used in scripts, etc.
Please have a look at my Matomo role for an example of how to do this, generating a random password and then sticking it in the file. Specifically, see how I set the default password securely:
matomo_superuser_password: "{{ lookup('password', '/dev/null length=20 chars=ascii_letters') }}"
I believe that this issue should be reopened (and ideally labelled as a security issue). I can't see a "Reopen" button so I can't do this myself.
This issue is no longer marked for closure.
This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution!
Please read this blog post to see the reasons why I mark issues as stale.
@geerlingguy Any chance you could roadmap this one? Thanks.
This issue is no longer marked for closure.
Just adding how we currently randomly change the root password on the first run of our playbook in case if it is of any use:
- name: install openssl to make sure we can generate a random password
apt: name=openssl update_cache=yes cache_valid_time=3600
tags:
- packages
- name: make a random password for mysql root user
shell: openssl rand -base64 48 | tr -d "=+/" | cut -c1-40
register: mysql_root_password
- name: set mysql root password to something random if it is still set as the default
mysql_user:
append_privs: yes
login_password: root
login_user: root
name: root
password: "{{ mysql_root_password.stdout }}"
ignore_errors: yes
register: mysql_root_pw_set
- name: update root .my.cnf with new password
ini_file:
dest: "~/.my.cnf"
section: client
option: "{{ item.option }}"
value: "{{ item.value }}"
mode: 0600
with_items:
- { option: user, value: root }
- { option: password, value: "{{ mysql_root_password.stdout }}" }
when: mysql_root_pw_set.changed
This makes sure we have a random secure password setup for every new MySQL server and the password is stored in the root .my.cnf file so we can ssh in to grab the password.
I'm sure there will be a way of generating a password without the requirement of openssl but I don't know of a good way yet.
I'm sure there will be a way of generating a password without the requirement of openssl but I don't know of a good way yet.
As I stated in my earlier comment, you can do this in Ansible natively. There's no need to shell for openssl. Here's that same example again:
matomo_superuser_password: "{{ lookup('password', '/dev/null length=20 chars=ascii_letters') }}"
@geerlingguy : I think this MR should do the trick. Thoughts?
This was more complicated that I thought. See the new PR for details, #465 (I closed the original one.)