13

I am using Puppet to provision MySQL with a parameterised class:

class mysql::server( $password ) {

        package { 'mysql-server': ensure => installed }
        package { 'mysql': ensure => installed }

        service { 'mysqld':
                enable => true,
                ensure => running,
                require => Package['mysql-server'],
        }

        exec { 'set-mysql-password':
                unless => "mysqladmin -uroot -p$password status",
                path => ['/bin', '/usr/bin'],
                command => "mysqladmin -uroot password $password",
                require => Service['mysqld'],
        }
}

How can I protect $password? Currently, I removed the default world readable permission from the node definition file and explicitly gave puppet read permission via ACL.

I'm assuming others have come across a similar situation so perhaps there's a better practice.

4 Answers 4

3

When working with Puppet and MySQL, I tend to put the root password in /root/.my.cnf, lock this file down, and then restrict SSH access onto the database server.

Yes, storing the root password on the db server in clear text isn't the most secure solution. However if you write the mysql root password in this file, securing the mysql root account to allow logins from localhost only will keep the password out of puppet, and also out of the process list ps table.

Additionally, if someone has root access to read the file at /root/.my.cnf, then they probably also have access to stop the local MySQL daemon and restart the daemon without the users table to gain immediate root access to the database.

1
  • 2
    Use mysql_config_editor if on mysql 5.6 and later. Then at least the password will not be in plain text. Jun 26, 2016 at 15:01
1

Someone else can likely point out some plug-in or similar that corrects me, but the general way to go about this is to store the encrypted password, not the plain text password.

However, I can tell you right now, MySQL doesn't allow you to use an encrypted password--otherwise, that WOULD be the password, and the hash would allow you to login anyways.

There are a lot of "hacks" around that allow you to use third-party utilities such as Hiera and GPG. Obviously, you can roll your own--but even Puppet's own mailing lists suggests this method.

1

You didn't specify who you are protecting this password from. I'm going to assume it's other sysadmins or possibly developers who have access to the puppet master and/or the client boxes but don't need to know the root password.

For setting the password initially, you could use this syntax:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*6DF1FC54F0CCD999F55D59D3D88526878230C77C' WITH GRANT OPTION;

Which would allow you to store an encrypted password in your puppet configuration instead of a plaintext one.

For using mysqladmin and the mysql client on the command line, the best I can think of is to add a .my.cnf file to your puppet config that gets deployed into an appropriate user's home directory. The file both in the puppet master and on the clients should have appropriate, restrictive file permissions.

There are plenty of ways around those file permissions when you add puppet into the mix (such as writing an exec() that pulls the file from the clients) but it would seem to be an improvement over storing the password in a world readable file. This would be more difficult if you use a versioning system for your puppet config.

4
  • 1
    But if someone retrieved the encrypted password, couldn't they just use the encrypted string to login?
    – Andrew M.
    Jan 3, 2012 at 14:10
  • @Redmumba All my testing seems to indicate so. Perhaps I'm missing something that Ladadadada could elaborate on. Jan 3, 2012 at 14:22
  • 3
    No. When you use IDENTIFIED BY PASSWORD '*HASH-HERE' instead of IDENTIFIED BY 'PASSWORD-HERE' MySQL inserts the hash directly into the user table. You then have to use the password that generated that hash to log in. You can see what your grant command with the password hash would look like by logging in normally and typing SHOW GRANTS;. You can also check other users with SHOW GRANTS FOR user@host;
    – Ladadadada
    Jan 3, 2012 at 14:25
  • Ah, so you can't use the hash itself to login, I see. However, if he has a client that needs to connect to the database--say, his front end--he would also need a way of storing the encrypted password, which is food for thought.
    – Andrew M.
    Jan 3, 2012 at 21:28
0

This link suggests two methods: using environment variables, and using subshell.

I think you can also create a simple wrapper around your command mysqladmin and pass your encrypted password to it. This wrapper will then decrypt the password and pass it to mysqladmin. You need to protect your wrapper as it contains the decryption part.

You can choose the way you feel it more secure based on your environment and who has access to your system.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .