June 03, 2015

MySQL User Security

^ Ad space to help offset hosting costs :D

Learn how to setup users in MySQL to be accessible from various hosts, remote or local, as well as ranges of IP addresses. We'll cover giving users specific grants to determine what they can do to the databases they are assigned.Users in MySQL perform a few duties:

  • Define what databases & tables the user can use
  • Define what operations the user can do on those databases/tables
  • Define from where a user can connect

Create Database

Let's start with a database and table we can use.

CREATE DATABASE my_app 
    DEFAULT CHARACTER SET utf8mb4 
    COLLATE utf8mb4_unicode_ci;

CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
  `first_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `last_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `role` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
  `email_nonce` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
  `subscribed` int(11) NOT NULL DEFAULT '1',
  `created_at` timestamp NOT NULL,
  `updated_at` timestamp NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Create an Open User

We don't want the root user to be used, it has too much power. Let's create one and lock it down a bit.

First, we can make one that's very generic and just about as open as user root, except it can only use our specific database.

CREATE USER 'my_user'@'%' IDENTIFIED BY 'some_secure_password';
GRANT ALL PRIVILEGES on my_app.* TO 'my_user'@'%';
  • User can connect from any host (wildcard %)
  • We've granted all privileges for that user on that database (and all tables)

Host Restrictions

Let's do more about where this user can connect from.

'my_user'@'%' is not 'my_user'@'192.168.16.16' - the host pairing makes them different

If we have an application server with a specific IP or hostname, or if we want to just open up our office IP address, we can define a user to connect only from a specific IP or hostname:

# Hostname
CREATE USER 'my_user'@'serversforhackers.com' IDENTIFIED BY 'some_secure_password';

# Hostname with wildcard
CREATE USER 'my_user'@'%.serversforhackers.com' IDENTIFIED BY 'some_secure_password';

# Or by IP address
CREATE USER 'my_user'@'12.124.345.67' IDENTIFIED BY 'some_secure_password';

Most interesting is setting users who can connect from a subnet, so we can restrict connetions from a local network (perhaps the private network used for servers within your VPC or other cloud hosting).

# Subnet 192.168.1.1 through 192.168.1.254
CREATE USER 'my_user'@'192.168.1.%' IDENTIFIED BY 'some_secure_password';

Grants

We don't need to grant all privileges. You can limit a user to only what they need.

# A read-only user
GRANT CREATE VIEW, SELECT, SHOW VIEW on my_app.* TO 'my_user'@'-WHATEVER-';

# A "90% user case" user
GRANT ALTER, CREATE, DELETE, DROP, INDEX, INSERT, LOCK TABLES, SELECT, UPDATE on my_app.* TO 'my_user'@'-WHATEVER-';

There are plenty more, this is not exhaustive.

A mysqldump user often needs quite a few privileges to cover all use cases (depending on the complexity of your database), so I don't have an example here.

Delete User

DROP USER 'my_user'@'-WHATEVER-';
FLUSH PRIVILEGES;

Resources

Side note, If you're interested in a service to help you manage MySQL-optimized, backup and (eventually) replication-enabled database servers, sign up here to let me know! The idea is to allow you to better manage your MySQL servers, taking advantage of many of MySQL's more advanced options, especially around backup and recovery.

Current

MySQL User Security

All Topics