Table of Contents
MySQL includes several plugins that implement security features:
Plugins for authenticating attempts by clients to connect to MySQL Server. Plugins are available for several authentication protocols. For general discussion of the authentication process, see Section 5.7, “Pluggable Authentication”. For characteristics of specific authentication plugins, see Section 7.1, “Authentication Plugins”.
A password-validation plugin for implementing password strength policies and assessing the strength of potential passwords. See Section 7.2, “The Password Validation Plugin”.
(MySQL Enterprise Edition only) MySQL Enterprise Audit, implemented using a server plugin, uses the open MySQL Audit API to enable standard, policy-based monitoring and logging of connection and query activity executed on specific MySQL servers. Designed to meet the Oracle audit specification, MySQL Enterprise Audit provides an out of box, easy to use auditing and compliance solution for applications that are governed by both internal and external regulatory guidelines.
(MySQL Enterprise Edition only) MySQL Enterprise Firewall, an application-level firewall that enables database administrators to permit or deny SQL statement execution based on matching against whitelists of accepted statement patterns. This helps harden MySQL Server against attacks such as SQL injection or attempts to exploit applications by using them outside of their legitimate query workload characteristics.
The following sections describe the authentication plugins available in MySQL.
The default plugin is mysql_native_password
unless the
--default-authentication-plugin
option is set otherwise at server startup.
MySQL includes two plugins that implement native authentication;
that is, authentication against passwords stored in the
Password column of the
mysql.user table. This section describes
mysql_native_password, which implements
authentication against the mysql.user table
using the native password hashing method. For information about
mysql_old_password, which implements
authentication using the older (pre-4.1) password hashing
method, see Section 7.1.2, “The Old Native Authentication Plugin”.
For information about these password hashing methods, see
Section 2.2.4, “Password Hashing in MySQL”.
The mysql_native_password native
authentication plugin is backward compatible. Clients older than
MySQL 5.5.7 do not support authentication
plugins but do use the native
authentication protocol, so they can
connect to servers from MySQL 5.5.7 and up.
The following table shows the plugin names on the server and client sides.
Table 7.1 MySQL Native Password Authentication Plugin
| Server-side plugin name | mysql_native_password |
| Client-side plugin name | mysql_native_password |
| Library file name | None (plugins are built in) |
The plugin exists in both client and server form:
The server-side plugin is built into the server, need not be loaded explicitly, and cannot be disabled by unloading it.
The client-side plugin is built into the
libmysqlclient client library as of MySQL
5.5.7 and available to any program linked against
libmysqlclient from that version or
higher.
MySQL client programs use
mysql_native_password by default. The
--default-auth option can be
used as a hint about which client-side plugin the program
can expect to use:
shell> mysql --default-auth=mysql_native_password ...
If an account row specifies no plugin name, the server
authenticates the account using either the
mysql_native_password or
mysql_old_password plugin, depending on
whether the password hash value in the
Password column used native hashing or the
older pre-4.1 hashing method. Clients must match the password in
the Password column of the account row.
For general information about pluggable authentication in MySQL, see Section 5.7, “Pluggable Authentication”.
MySQL includes two plugins that implement native authentication;
that is, authentication against passwords stored in the
Password column of the
mysql.user table. This section describes
mysql_old_password, which implements
authentication against the mysql.user table
using the older (pre-4.1) password hashing method. For
information about mysql_native_password,
which implements authentication using the native password
hashing method, see
Section 7.1.1, “The Native Authentication Plugin”. For information
about these password hashing methods, see
Section 2.2.4, “Password Hashing in MySQL”.
Passwords that use the pre-4.1 hashing method are less secure than passwords that use the native password hashing method and should be avoided. Pre-4.1 passwords are deprecated and support for them will be removed in a future MySQL release. For account upgrade instructions, see Section 7.1.3, “Migrating Away from Pre-4.1 Password Hashing and the mysql_old_password Plugin”.
The mysql_old_password native authentication
plugin is backward compatible. Clients older than MySQL 5.5.7 do
not support authentication plugins but do
use the native authentication protocol, so
they can connect to servers from MySQL 5.5.7 and up.
The following table shows the plugin names on the server and client sides.
Table 7.2 MySQL Old Native Authentication Plugin
| Server-side plugin name | mysql_old_password |
| Client-side plugin name | mysql_old_password |
| Library file name | None (plugins are built in) |
The plugin exists in both client and server form:
The server-side plugin is built into the server, need not be loaded explicitly, and cannot be disabled by unloading it.
The client-side plugin is built into the
libmysqlclient client library as of MySQL
5.5.7 and available to any program linked against
libmysqlclient from that version or
higher.
MySQL client programs can use the
--default-auth option to
specify the mysql_old_password plugin as
a hint about which client-side plugin the program can expect
to use:
shell> mysql --default-auth=mysql_old_password ...
If an account row specifies no plugin name, the server
authenticates the account using either the
mysql_native_password or
mysql_old_password plugin, depending on
whether the password hash value in the
Password column used native hashing or the
older pre-4.1 hashing method. Clients must match the password in
the Password column of the account row.
For general information about pluggable authentication in MySQL, see Section 5.7, “Pluggable Authentication”.
The MySQL server authenticates connection attempts for each
account listed in the mysql.user table using
the authentication plugin named in the plugin
column. If the plugin column is empty, the
server authenticates the account as follows:
Before MySQL 5.7.2, the server uses the
mysql_native_password or
mysql_old_password plugin implicitly,
depending on the format of the password hash in the
Password column. If the
Password value is empty or a 4.1 password
hash (41 characters), the server uses
mysql_native_password. If the password
value is a pre-4.1 password hash (16 characters), the server
uses mysql_old_password. (For additional
information about these hash formats, see
Section 2.2.4, “Password Hashing in MySQL”.)
As of MySQL 5.7.2, the server requires the
plugin column to be nonempty and disables
accounts that have an empty plugin value.
Pre-4.1 password hashes and the
mysql_old_password plugin are deprecated as
of MySQL 5.6.5 and support for them is removed in MySQL 5.7.5.
They provide a level of security inferior to that offered by 4.1
password hashing and the
mysql_native_password plugin.
Given the requirement in MySQL 5.7.2 that the
plugin column must be nonempty, coupled with
removal of mysql_old_password support in
5.7.5, DBAs are advised to upgrade accounts as follows:
Upgrade accounts that use
mysql_native_password implicitly to use
it explicitly
Upgrade accounts that use
mysql_old_password (either implicitly or
explicitly) to use mysql_native_password
explicitly
The instructions in this section describe how to perform those
upgrades. The result is that no account has an empty
plugin value and no account uses pre-4.1
password hashing or the mysql_old_password
plugin.
As a variant on these instructions, DBAs might offer users the
choice to upgrade to the sha256_password
plugin, which authenticates using SHA-256 password hashes. For
information about this plugin, see
Section 7.1.4, “The SHA-256 Authentication Plugin”.
The following table lists the types of
mysql.user accounts considered in this
discussion.
plugin Column | Password Column | Authentication Result | Upgrade Action |
|---|---|---|---|
| Empty | Empty | Implicitly uses mysql_native_password | Assign plugin |
| Empty | 4.1 hash | Implicitly uses mysql_native_password | Assign plugin |
| Empty | Pre-4.1 hash | Implicitly uses mysql_old_password | Assign plugin, rehash password |
mysql_native_password | Empty | Explicitly uses mysql_native_password | None |
mysql_native_password | 4.1 hash | Explicitly uses mysql_native_password | None |
mysql_old_password | Empty | Explicitly uses mysql_old_password | Upgrade plugin |
mysql_old_password | Pre-4.1 hash | Explicitly uses mysql_old_password | Upgrade plugin, rehash password |
Accounts corresponding to lines for the
mysql_native_password plugin require no
upgrade action (because no change of plugin or hash format is
required). For accounts corresponding to lines for which the
password is empty, consider asking the account owners to choose
a password (or require it by using ALTER
USER to expire empty account passwords).
Accounts that have an empty plugin and a 4.1 password hash use
mysql_native_password implicitly. To upgrade
these accounts to use mysql_native_password
explicitly, execute these statements:
UPDATE mysql.user SET plugin = 'mysql_native_password' WHERE plugin = '' AND (Password = '' OR LENGTH(Password) = 41); FLUSH PRIVILEGES;
Before MySQL 5.7.2, you can execute those statements to uprade accounts proactively. As of MySQL 5.7.2, you can run mysql_upgrade, which performs the same operation among its upgrade actions.
Notes:
The upgrade operation just described is safe to execute at
any time because it makes the
mysql_native_password plugin explicit
only for accounts that already use it implicitly.
This operation requires no password changes, so it can be performed without affecting users or requiring their involvement in the upgrade process.
Accounts that use mysql_old_password (either
implicitly or explicitly) should be upgraded to use
mysql_native_password explicitly. This
requires changing the plugin and changing
the password from pre-4.1 to 4.1 hash format.
For the accounts covered in this step that must be upgraded, one of these conditions is true:
The account uses mysql_old_password
implicitly because the plugin column is
empty and the password has the pre-4.1 hash format (16
characters).
The account uses mysql_old_password
explicitly.
To identify such accounts, use this query:
SELECT User, Host, Password FROM mysql.user WHERE (plugin = '' AND LENGTH(Password) = 16) OR plugin = 'mysql_old_password';
The following discussion provides two methods for updating that set of accounts. They have differing characteristics, so read both and decide which is most suitable for a given MySQL installation.
Method 1.
Characteristics of this method:
It requires that server and clients be run with
secure_auth=0 until all users have been
upgraded to mysql_native_password.
(Otherwise, users cannot connect to the server using their
old-format password hashes for the purpose of upgrading to a
new-format hash.)
It works for MySQL 5.5 through 5.7.1. As of 5.7.2, it does not work because the server requires accounts to have a nonempty plugin and disables them otherwise. Therefore, if you have already upgraded to 5.7.2 or later, choose Method 2, described later.
You should ensure that the server is running with
secure_auth=0.
For all accounts that use mysql_old_password
explicitly, set them to the empty plugin:
UPDATE mysql.user SET plugin = '' WHERE plugin = 'mysql_old_password'; FLUSH PRIVILEGES;
To also expire the password for affected accounts, use these statements instead:
UPDATE mysql.user SET plugin = '', password_expired = 'Y' WHERE plugin = 'mysql_old_password'; FLUSH PRIVILEGES;
Now affected users can reset their password to use 4.1 hashing. Ask each user who now has an empty plugin to connect to the server and execute these statements:
SET old_passwords = 0;
SET PASSWORD = PASSWORD('user-chosen-password');
In MySQL 5.6.5 or later, the client-side
--secure-auth option is enabled
by default, so remind users to disable it or they will be
unable to connect:
shell> mysql -u user_name -p --secure-auth=0
After an affected user has executed those statements, you can
set the corresponding account plugin to
mysql_native_password to make the plugin
explicit. Or you can periodically run these statements to find
and fix any accounts for which affected users have reset their
password:
UPDATE mysql.user SET plugin = 'mysql_native_password' WHERE plugin = '' AND (Password = '' OR LENGTH(Password) = 41); FLUSH PRIVILEGES;
When there are no more accounts with an empty plugin, this query returns an empty result:
SELECT User, Host, Password FROM mysql.user WHERE (plugin = '' AND LENGTH(Password) = 16);
At that point, all accounts have been migrated away from pre-4.1
password hashing and the server no longer need be run with
secure_auth=0.
Method 2.
Characteristics of this method:
It assigns each affected account a new password, so you must tell each such user the new password and ask the user to choose a new one. Communication of passwords to users is outside the scope of MySQL, but should be done carefully.
It does not require server or clients to be run with
secure_auth=0.
It works for any version of MySQL 5.5 or later (and for 5.7.6 or later has an easier variant).
With this method, you update each account separately due to the need to set passwords individually. Choose a different password for each account.
Suppose that 'user1'@'localhost' is one of
the accounts to be upgraded. Modify it as follows:
In MySQL 5.7.6 and higher, ALTER USER
provides the capability of modifying both the account
password and its authentication plugin, so you need not
modify the mysql.user table directly:
ALTER USER 'user1'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'DBA-chosen-password';
To also expire the account password, use this statement instead:
ALTER USER 'user1'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'DBA-chosen-password'
PASSWORD EXPIRE;
Then tell the user the new password and ask the user to connect to the server with that password and execute this statement to choose a new password:
ALTER USER USER() IDENTIFIED BY 'user-chosen-password';
Before MySQL 5.7.6, you must modify the
mysql.user table directly using these
statements:
SET old_passwords = 0;
UPDATE mysql.user SET plugin = 'mysql_native_password',
Password = PASSWORD('DBA-chosen-password')
WHERE (User, Host) = ('user1', 'localhost');
FLUSH PRIVILEGES;
To also expire the account password, use these statements instead:
SET old_passwords = 0;
UPDATE mysql.user SET plugin = 'mysql_native_password',
Password = PASSWORD('DBA-chosen-password'), password_expired = 'Y'
WHERE (User, Host) = ('user1', 'localhost');
FLUSH PRIVILEGES;
Then tell the user the new password and ask the user to connect to the server with that password and execute these statements to choose a new password:
SET old_passwords = 0;
SET PASSWORD = PASSWORD('user-chosen-password');
Repeat for each account to be upgraded.
As of MySQL 5.6.6, MySQL provides an authentication plugin that implements SHA-256 hashing for user account passwords.
To connect to the server using an account that authenticates
with the sha256_password plugin, you must
use either an SSL connection or an unencrypted connection that
encrypts the password using RSA, as described later in this
section. Either way, use of the
sha256_password plugin requires that MySQL
be built with SSL capabilities. See
Chapter 6, Using Secure Connections.
The following table shows the plugin names on the server and client sides.
Table 7.3 MySQL SHA-256 Authentication Plugin
| Server-side plugin name | sha256_password |
| Client-side plugin name | sha256_password |
| Library file name | None (plugins are built in) |
The server-side sha256_password plugin is
built into the server, need not be loaded explicitly, and cannot
be disabled by unloading it. Similarly, clients need not specify
the location of the client-side plugin.
To set up an account that uses SHA-256 password hashing, use the following procedure.
Create the account and specify that it authenticates using
the sha256_password plugin:
CREATE USER 'sha256user'@'localhost' IDENTIFIED WITH sha256_password;
Set the old_passwords
system variable to 2 to cause the
PASSWORD() function to use
SHA-256 hashing of password strings, then set the account
password:
SET old_passwords = 2;
SET PASSWORD FOR 'sha256user'@'localhost' = PASSWORD('Sh@256Pa33');
Alternatively, start the server with the default authentication
plugin set to sha256_password. For example,
put these lines in the server option file:
[mysqld] default-authentication-plugin=sha256_password
That causes the sha256_password plugin to be
used by default for new accounts. As a result, it is possible to
create the account and set its password without naming the
plugin explicitly using this CREATE
USER syntax:
CREATE USER 'sha256user'@'localhost' IDENTIFIED BY 'Sh@256Pa33';
In this case, the server assigns the
sha256_password plugin to the account and
encrypts the password using SHA-256.
Accounts in the mysql.user table that use
SHA-256 passwords can be identified as rows with
'sha256_password' in the
plugin column and a SHA-256 password hash in
the authentication_string column.
Another consequence of using sha256_password
as the default authentication plugin is that to create an
account that uses a different plugin, you must specify that
plugin using an IDENTIFIED WITH clause in the
CREATE USER statement, then set
old_passwords appropriately for
the plugin before using SET
PASSWORD to set the account password. For example, to
use the mysql_native_password plugin, do
this:
CREATE USER 'nativeuser'@'localhost' IDENTIFIED WITH mysql_native_password;
SET old_passwords = 0;
SET PASSWORD FOR 'nativeuser'@'localhost' = PASSWORD('N@tivePa33');
To set or change the password for any account that authenticates
using the sha256_password plugin, be sure
that the value of old_passwords
is 2 before using SET PASSWORD.
If old_passwords has a value
other than 2, an error occurs for attempts to set the password:
mysql>SET old_passwords = 0;mysql>SET PASSWORD FOR 'sha256user'@'localhost' = PASSWORD('NewSh@256Pa33');ERROR 1827 (HY000): The password hash doesn't have the expected format. Check if the correct password algorithm is being used with the PASSWORD() function.
For more information about
old_passwords and
PASSWORD(), see
Server System Variables, and
Encryption and Compression Functions.
MySQL can be compiled using either OpenSSL or yaSSL (see
Section 6.1, “OpenSSL Versus yaSSL”). The
sha256_password plugin works with
distributions compiled using either package, but if MySQL is
compiled using OpenSSL, RSA encryption is available and
sha256_password implements the following
additional capabilities. (To enable these capabilities, you must
also follow the RSA configuration procedure given later in this
section.)
It is possible for the client to transmit passwords to the server using RSA encryption during the client connection process, as described later.
The server exposes two additional system variables,
sha256_password_private_key_path
and
sha256_password_public_key_path.
It is intended that the database administrator will set
these to the names of the RSA private and public key-pair
files at server startup if the key files have names that
differ from the system variable default values.
The server exposes a status variable,
Rsa_public_key, that
displays the RSA public key value.
The mysql and
mysqltest client programs support a
--server-public-key-path
option for specifying an RSA public key file explicitly.
(This option was added in MySQL 5.6.6 under the name
--server-public-key and renamed in 5.6.7 to
--server-public-key-path.)
For clients that use the sha256_password
plugin, passwords are never exposed as cleartext when connecting
to the server. How password transmission occurs depends on
whether an SSL connection is used and whether RSA encryption is
available:
If an SSL connection is used, the password is sent as cleartext but cannot be snooped because the connection is encrypted using SSL.
If an SSL connection is not used but RSA encryption is available, the password is sent within an unencrypted connection, but the password is RSA-encrypted to prevent snooping. When the server receives the password, it decrypts it. A scramble is used in the encryption to prevent repeat attacks.
If an SSL connection is not used and RSA encryption is not
available, the sha256_password plugin
causes the connection attempt to fail because the password
cannot be sent without being exposed as cleartext.
As mentioned previously, RSA password encryption is available only if MySQL was compiled using OpenSSL. The implication for MySQL distributions compiled using yaSSL is that SHA-256 passwords can be used only when clients use SSL to access the server. See Section 6.4, “Configuring MySQL to Use Secure Connections”.
Assuming that MySQL has been compiled using OpenSSL, the following procedure describes how to enable RSA encryption of passwords during the client connection process:
Create the RSA private and public key-pair files using the instructions in Section 6.6, “Creating SSL and RSA Certificates and Keys”.
If the private and public key files are located in the data
directory and are named private_key.pem
and public_key.pem (the default values
of the
sha256_password_private_key_path
and
sha256_password_public_key_path
system variables), the server will use them automatically at
startup.
Otherwise, in the server option file, set the system variables to the key file names. If the files are located in the server data directory, you need not specify their full path names:
[mysqld] sha256_password_private_key_path=myprivkey.pem sha256_password_public_key_path=mypubkey.pem
If the key files are not located in the data directory, or to make their locations explicit in the system variable values, use full path names:
[mysqld] sha256_password_private_key_path=/usr/local/mysql/myprivkey.pem sha256_password_public_key_path=/usr/local/mysql/mypubkey.pem
Restart the server, then connect to it and check the
Rsa_public_key status
variable value. The value will differ from that shown here,
but should be nonempty:
mysql> SHOW STATUS LIKE 'Rsa_public_key'\G
*************************** 1. row ***************************
Variable_name: Rsa_public_key
Value: -----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO9nRUDd+KvSZgY7cNBZMNpwX6
MvE1PbJFXO7u18nJ9lwc99Du/E7lw6CVXw7VKrXPeHbVQUzGyUNkf45Nz/ckaaJa
aLgJOBCIDmNVnyU54OT/1lcs2xiyfaDMe8fCJ64ZwTnKbY2gkt1IMjUAB5Ogd5kJ
g8aV7EtKwyhHb0c30QIDAQAB
-----END PUBLIC KEY-----
If the value is empty, the server found some problem with the key files. Check the error log for diagnostic information.
After the server has been configured with the RSA key files,
clients have the option of using them to connect to the server
using accounts that authenticate with the
sha256_password plugin. As mentioned
previously, such accounts can use either an SSL connection (in
which case RSA is not used) or an unencrypted connection that
encrypts the password using RSA. Assume for the following
discussion that SSL is not used. Connecting to the server
involves no special preparation on the client side. For example:
shell>mysql --ssl-mode=DISABLED -u sha256user -pEnter password:Sh@256Pa33
For connection attempts by sha256user, the
server determines that sha256_password is the
appropriate authentication plugin and invokes it. The plugin
finds that the connection does not use SSL and thus requires the
password to be transmitted using RSA encryption. In this case,
the plugin sends the RSA public key to the client, which uses it
to encrypt the password and returns the result to the server.
The plugin uses the RSA key on the server side to decrypt the
password and accepts or rejects the connection based on whether
the password is correct.
The server sends the public key to the client as needed, but if a copy of the RSA public key is available on the client host, the client can use it to save a round trip in the client/server protocol:
shell> mysql --ssl-mode=DISABLED -u sha256user -p --server-public-key-path=file_name
The public key value in the file named by the
--server-public-key-path option
should be the same as the key value in the server-side file
named by the
sha256_password_public_key_path
system variable. If the key file contains a valid public key
value but the value is incorrect, an access-denied error occurs.
If the key file does not contain a valid public key, the client
program cannot use it. In this case, the
sha256_password plugin sends the public key
to the client as if no
--server-public-key-path option
had been specified.
Client users can get the RSA public key two ways:
The database administrator can provide a copy of the public key file.
A client user who can connect to the server some other way
can use a SHOW STATUS LIKE
'Rsa_public_key' statement and save the returned
key value in a file.
The PAM authentication plugin is an extension included in MySQL Enterprise Edition, a commercial product. To learn more about commercial products, see http://www.mysql.com/products/.
As of MySQL 5.6.10, MySQL Enterprise Edition includes an authentication plugin that enables MySQL Server to use PAM (Pluggable Authentication Modules) to authenticate MySQL users. PAM enables a system to use a standard interface to access various kinds of authentication methods, such as Unix passwords or an LDAP directory.
The PAM authentication plugin provides these capabilities:
External authentication: The plugin enables MySQL Server to accept connections from users defined outside the MySQL grant tables and that authenticate using methods supported by PAM.
Proxy user support: The plugin can return to MySQL a user
name different from the login user, based on the groups the
external user is in and the authentication string provided.
This means that the plugin can return the MySQL user that
defines the privileges the external PAM-authenticated user
should have. For example, a PAM user named
joe can connect and have the privileges
of the MySQL user named developer.
The PAM authentication plugin has been tested on Linux and Mac OS X.
The PAM plugin uses the information passed to it by MySQL Server
(such as user name, host name, password, and authentication
string), plus whatever method is available for PAM lookup. The
plugin checks the user credentials against PAM and returns
'Authentication succeeded, Username is
or
user_name''Authentication failed'.
The following table shows the plugin and library file names. The
file name suffix might be different on your system. The file
location must be the directory named by the
plugin_dir system variable. For
installation information, see
Section 7.1.5.1, “Installing the PAM Authentication Plugin”.
Table 7.4 MySQL PAM Authentication Plugin
| Server-side plugin name | authentication_pam |
| Client-side plugin name | mysql_clear_password |
| Library file name | authentication_pam.so |
The library file includes only the server-side plugin. The
client-side plugin is built into the
libmysqlclient client library. See
Section 7.1.7, “The Cleartext Client-Side Authentication Plugin”.
The server-side PAM authentication plugin is included only in MySQL Enterprise Edition. It is not included in MySQL community distributions. The client-side clear-text plugin that communicates with the server-side plugin is built into the MySQL client library and is included in all distributions, including community distributions. This permits clients from any MySQL 5.6.10 or higher distribution to connect to a server that has the server-side plugin loaded.
For general information about pluggable authentication in MySQL, see Section 5.7, “Pluggable Authentication”. For proxy user information, see Section 5.8, “Proxy Users”.
The PAM authentication plugin must be located in the MySQL
plugin directory (the directory named by the
plugin_dir system variable).
If necessary, set the value of
plugin_dir at server startup
to tell the server the plugin directory location.
To enable the plugin, start the server with the
--plugin-load option. For
example, put the following lines in your
my.cnf file. If library files have a
suffix different from .so on your system,
substitute the correct suffix.
[mysqld] plugin-load=authentication_pam.so
To verify plugin installation, examine the
INFORMATION_SCHEMA.PLUGINS table
or use the SHOW PLUGINS
statement (see
Obtaining Server Plugin Information). For example:
mysql>SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS->WHERE PLUGIN_NAME LIKE 'authentication%';+--------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +--------------------+---------------+ | authentication_pam | ACTIVE | +--------------------+---------------+
To associate a MySQL account with the PAM plugin, use the
plugin name authentication_pam in the
IDENTIFIED WITH clause of
CREATE USER or
GRANT statement that creates
the account.
This section describes how to use the PAM authentication plugin to connect from MySQL client programs to the server. It is assumed that the server-side plugin is enabled, as described previously.
The client-side plugin with which the PAM plugin communicates simply sends the password to the server in clear text so it can be passed to PAM. This may be a security problem in some configurations, but is necessary to use the server-side PAM library. To avoid problems if there is any possibility that the password would be intercepted, clients should connect to MySQL Server using a secure connection. See Section 7.1.7, “The Cleartext Client-Side Authentication Plugin”.
To refer to the PAM authentication plugin in the
IDENTIFIED WITH clause of a
CREATE USER or
GRANT statement, use the name
authentication_pam. For example:
CREATE USERuserIDENTIFIED WITH authentication_pam AS 'authentication_string';
The authentication string specifies the following types of information:
PAM supports the notion of “service name,” which is a name that the system administrator can use to configure the authentication method for a particular application. There can be several such “applications” associated with a single database server instance, so the choice of service name is left to the SQL application developer. When you define an account that should authenticate using PAM, specify the service name in the authentication string.
PAM provides a way for a PAM module to return to the server a MySQL user name other than the login name supplied at login time. Use the authentication string to control the mapping between login name and MySQL user name. If you want to take advantage of proxy user capabilities, the authentication string must include this kind of mapping.
For example, if the service name is mysql
and users in the root and
users PAM groups should be mapped to the
developer and data_entry
MySQL users, respectively, use a statement like this:
CREATE USER user
IDENTIFIED WITH authentication_pam
AS 'mysql, root=developer, users=data_entry';
Authentication string syntax for the PAM authentication plugin follows these rules:
The string consists of a PAM service name, optionally followed by a group mapping list consisting of one or more keyword/value pairs each specifying a group name and a MySQL user name:
pam_service_name[,group_name=mysql_user_name]...
The plugin parses the authentication string on each login check. To minimize overhead, keep the string as short as possible.
Each
pair must be preceded by a comma.
group_name=mysql_user_name
Leading and trailing spaces not inside double quotation marks are ignored.
Unquoted pam_service_name,
group_name, and
mysql_user_name values can
contain anything except equal sign, comma, or space.
If a pam_service_name,
group_name, or
mysql_user_name value is quoted
with double quotation marks, everything between the
quotation marks is part of the value. This is necessary,
for example, if the value contains space characters. All
characters are legal except double quotation mark and
backslash (\). To include either
character, escape it with a backslash.
If the plugin successfully authenticates a login name, it looks for a group mapping list in the authentication string and, if present, uses it to return a different user name to the MySQL server based on the groups the external user is a member of:
If the authentication string contains no group mapping list, the plugin returns the login name.
If the authentication string does contain a group mapping
list, the plugin examines each
pair in the list from left to right and tries to find a
match for the group_name=mysql_user_namegroup_name value
in a non-MySQL directory of the groups assigned to the
authenticated user and returns
mysql_user_name for the first
match it finds. If the plugin finds no match for any
group, it returns the login name. If the plugin is not
capable of looking up a group in a directory, it ignores
the group mapping list and returns the login name.
The following sections describe how to set up several authentication scenarios that use the PAM authentication plugin:
No proxy users. This uses PAM only to check login names
and passwords. Every external user permitted to connect to
MySQL Server should have a matching MySQL account that is
defined to use external PAM authentication. (For a MySQL
account of
to match the external user,
user_name@host_nameuser_name must be the login
name and host_name must match
the host from which the client connects.) Authentication
can be performed by various PAM-supported methods. The
discussion shows how to use traditional Unix passwords and
LDAP.
PAM authentication, when not done through proxy users or groups, requires the MySQL account to have the same user name as the Unix account. Because MySQL user names are limited to 16 characters (see Section 4.2, “Grant Tables”), this limits PAM nonproxy authentication to Unix accounts with names of at most 16 characters.
Proxy login only and group mapping. For this scenario, create one or a few MySQL accounts that define different sets of privileges. (Ideally, nobody should connect using those accounts directly.) Then define a default user authenticating through PAM that uses some mapping scheme (usually by the external groups the users are in) to map all the external logins to the few MySQL accounts holding the privilege sets. Any user that logs in is mapped to one of the MySQL accounts and uses its privileges. The discussion shows how to set this up using Unix passwords, but other PAM methods such as LDAP could be used instead.
Variations on these scenarios are possible. For example, you can permit some users to log in directly (without proxying) but require others to connect through proxy users.
The examples make the following assumptions. You might need to make some adjustments if your system is set up differently.
The PAM configuration directory is
/etc/pam.d.
The PAM service name is mysql, which
means that you must set up a PAM file named
mysql in the PAM configuration
directory (creating the file if it does not exist). If you
use a service name different from
mysql, the file name will be different
and you must use a different name in the AS
' clause
of auth_string'CREATE USER and
GRANT statements.
The examples use a login name of
antonio and password of
verysecret. Change these to correspond
to the users you want to authenticate.
The PAM authentication plugin checks at initialization time
whether the AUTHENTICATION_PAM_LOG
environment value is set in the server's startup environment.
If so, the plugin enables logging of diagnostic messages to
the standard output. Depending on how your server is started,
the message might appear on the console or in the error log.
These messages can be helpful for debugging PAM-related
problems that occur when the plugin performs authentication.
For more information, see
Section 7.1.5.6, “PAM Authentication Plugin Debugging”.
This authentication scenario uses PAM only to check Unix user login names and passwords. Every external user permitted to connect to MySQL Server should have a matching MySQL account that is defined to use external PAM authentication.
Verify that Unix authentication in PAM permits you to log
in as antonio with password
verysecret.
Set up PAM to authenticate the mysql
service by creating a file named
/etc/pam.d/mysql. The file contents
are system dependent, so check existing login-related
files in the /etc/pam.d directory to
see what they look like. On Linux, the
mysql file might look like this:
#%PAM-1.0 auth include password-auth account include password-auth
For Gentoo Linux, use system-login
rather than password-auth. For OS X,
use login rather than
password-auth.
On Ubuntu and other Debian-based systems, use these file contents instead:
@include common-auth @include common-account @include common-session-noninteractive
Create a MySQL account with the same user name as the Unix login name and define it to authenticate using the PAM plugin:
CREATE USER 'antonio'@'localhost' IDENTIFIED WITH authentication_pam AS 'mysql'; GRANT ALL PRIVILEGES ON mydb.* TO 'antonio'@'localhost';
Connect to the MySQL server using the mysql command-line client. For example:
mysql --user=antonio --password=verysecret --enable-cleartext-plugin mydb
The server should permit the connection and the following query should return output as shown:
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+-------------------+--------------+
| USER() | CURRENT_USER() | @@proxy_user |
+-------------------+-------------------+--------------+
| antonio@localhost | antonio@localhost | NULL |
+-------------------+-------------------+--------------+
This demonstrates that antonio uses the
privileges granted to the antonio MySQL
account, and that no proxying has occurred.
This authentication scenario uses PAM only to check LDAP user login names and passwords. Every external user permitted to connect to MySQL Server should have a matching MySQL account that is defined to use external PAM authentication.
Verify that LDAP authentication in PAM permits you to log
in as antonio with password
verysecret.
Set up PAM to authenticate the mysql
service through LDAP by creating a file named
/etc/pam.d/mysql. The file contents
are system dependent, so check existing login-related
files in the /etc/pam.d directory to
see what they look like. On Linux, the
mysql file might look like this:
#%PAM-1.0 auth required pam_ldap.so account required pam_ldap.so
If PAM object files have a suffix different from
.so on your system, substitute the
correct suffix.
The PAM file might have a different format on some systems.
MySQL account creation and connecting to the server is the same as previously described in Section 7.1.5.3, “Unix Password Authentication without Proxy Users”.
This authentication scheme uses proxying and group mapping to map users who connect to the MySQL server through PAM onto MySQL accounts that define different sets of privileges. Users do not connect directly through the accounts that define the privileges. Instead, they connect through a default proxy user authenticating through PAM that uses a mapping scheme to map all the external logins to the few MySQL accounts holding the privileges. Any user who connects is mapped to one of the MySQL accounts and uses its privileges.
The procedure shown here uses Unix password authentication. To use LDAP instead, see the early steps of Section 7.1.5.4, “LDAP Authentication without Proxy Users”.
Verify that Unix authentication in PAM permits you to log
in as antonio with password
verysecret and that
antonio is a member of the
root or users group.
Set up PAM to authenticate the mysql
service. Put the following in
/etc/pam.d/mysql:
#%PAM-1.0 auth include password-auth account include password-auth
use system-login rather than
password-auth. For OS X, use
login rather than
password-auth.
The PAM file might have a different format on some systems. For example, on Ubuntu and other Debian-based systems, use these file contents instead:
@include common-auth @include common-account @include common-session-noninteractive
Create a default proxy user (''@'')
that maps the external PAM users to the proxied accounts.
It maps external users from the root
PAM group to the developer MySQL
account and the external users from the
users PAM group to the
data_entry MySQL account:
CREATE USER ''@'' IDENTIFIED WITH authentication_pam AS 'mysql, root=developer, users=data_entry';
The mapping list following the service name is required when you set up proxy users. Otherwise, the plugin cannot tell how to map the name of PAM groups to the proper proxied user name.
If your MySQL installation has anonymous users, they might conflict with the default proxy user. For more information about this problem, and ways of dealing with it, see Default Proxy User and Anonymous User Conflicts.
Create the proxied accounts that will be used to access the databases:
CREATE USER 'developer'@'localhost' IDENTIFIED BY 'very secret password'; GRANT ALL PRIVILEGES ON mydevdb.* TO 'developer'@'localhost'; CREATE USER 'data_entry'@'localhost' IDENTIFIED BY 'very secret password'; GRANT ALL PRIVILEGES ON mydb.* TO 'data_entry'@'localhost';
If you do not let anyone know the passwords for these
accounts, other users cannot use them to connect directly
to the MySQL server. Instead, it is expected that users
will authenticate using PAM and that they will use the
developer or
data_entry account by proxy based on
their PAM group.
Grant the PROXY privilege
to the proxy account for the proxied accounts:
GRANT PROXY ON 'developer'@'localhost' TO ''@''; GRANT PROXY ON 'data_entry'@'localhost' TO ''@'';
Connect to the MySQL server using the mysql command-line client. For example:
mysql --user=antonio --password=verysecret --enable-cleartext-plugin mydb
The server authenticates the connection using the
''@'' account. The privileges
antonio will have depends on what PAM
groups he is a member of. If antonio is a
member of the root PAM group, the PAM
plugin maps root to the
developer MySQL user name and returns
that name to the server. The server verifies that
''@'' has the
PROXY privilege for
developer and permits the connection.
the following query should return output as shown:
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+---------------------+--------------+
| USER() | CURRENT_USER() | @@proxy_user |
+-------------------+---------------------+--------------+
| antonio@localhost | developer@localhost | ''@'' |
+-------------------+---------------------+--------------+
This demonstrates that antonio uses the
privileges granted to the developer
MySQL account, and that proxying occurred through the
default proxy user account.
If antonio is not a member of the
root PAM group but is a member of the
users group, a similar process occurs,
but the plugin maps user group
membership to the data_entry MySQL user
name and returns that name to the server. In this case,
antonio uses the privileges of the
data_entry MySQL account:
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+----------------------+--------------+
| USER() | CURRENT_USER() | @@proxy_user |
+-------------------+----------------------+--------------+
| antonio@localhost | data_entry@localhost | ''@'' |
+-------------------+----------------------+--------------+
The PAM authentication plugin checks at initialization time
whether the AUTHENTICATION_PAM_LOG
environment value is set (the value does not matter). If so,
the plugin enables logging of diagnostic messages to the
standard output. These messages may be helpful for debugging
PAM-related problems that occur when the plugin performs
authentication.
Some messages include reference to PAM plugin source files and line numbers, which enables plugin actions to be tied more closely to the location in the code where they occur.
The following transcript demonstrates the kind of information produced by enabling logging. It resulted from a successful proxy authentication attempt.
entering auth_pam_server entering auth_pam_next_token auth_pam_next_token:reading at [cups,admin=writer,everyone=reader], sep=[,] auth_pam_next_token:state=PRESPACE, ptr=[cups,admin=writer,everyone=reader], out=[] auth_pam_next_token:state=IDENT, ptr=[cups,admin=writer,everyone=reader], out=[] auth_pam_next_token:state=AFTERSPACE, ptr=[,admin=writer,everyone=reader], out=[cups] auth_pam_next_token:state=DELIMITER, ptr=[,admin=writer,everyone=reader], out=[cups] auth_pam_next_token:state=DONE, ptr=[,admin=writer,everyone=reader], out=[cups] leaving auth_pam_next_token on /Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/parser.c:191 auth_pam_server:password 12345qq received auth_pam_server:pam_start rc=0 auth_pam_server:pam_set_item(PAM_RUSER,gkodinov) rc=0 auth_pam_server:pam_set_item(PAM_RHOST,localhost) rc=0 entering auth_pam_server_conv auth_pam_server_conv:PAM_PROMPT_ECHO_OFF [Password:] received leaving auth_pam_server_conv on /Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/authentication_pam.c:257 auth_pam_server:pam_authenticate rc=0 auth_pam_server:pam_acct_mgmt rc=0 auth_pam_server:pam_setcred(PAM_ESTABLISH_CRED) rc=0 auth_pam_server:pam_get_item rc=0 auth_pam_server:pam_setcred(PAM_DELETE_CRED) rc=0 entering auth_pam_map_groups entering auth_pam_walk_namevalue_list auth_pam_walk_namevalue_list:reading at: [admin=writer,everyone=reader] entering auth_pam_next_token auth_pam_next_token:reading at [admin=writer,everyone=reader], sep=[=] auth_pam_next_token:state=PRESPACE, ptr=[admin=writer,everyone=reader], out=[] auth_pam_next_token:state=IDENT, ptr=[admin=writer,everyone=reader], out=[] auth_pam_next_token:state=AFTERSPACE, ptr=[=writer,everyone=reader], out=[admin] auth_pam_next_token:state=DELIMITER, ptr=[=writer,everyone=reader], out=[admin] auth_pam_next_token:state=DONE, ptr=[=writer,everyone=reader], out=[admin] leaving auth_pam_next_token on /Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/parser.c:191 auth_pam_walk_namevalue_list:name=[admin] entering auth_pam_next_token auth_pam_next_token:reading at [writer,everyone=reader], sep=[,] auth_pam_next_token:state=PRESPACE, ptr=[writer,everyone=reader], out=[] auth_pam_next_token:state=IDENT, ptr=[writer,everyone=reader], out=[] auth_pam_next_token:state=AFTERSPACE, ptr=[,everyone=reader], out=[writer] auth_pam_next_token:state=DELIMITER, ptr=[,everyone=reader], out=[writer] auth_pam_next_token:state=DONE, ptr=[,everyone=reader], out=[writer] leaving auth_pam_next_token on /Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/parser.c:191 walk, &error_namevalue_list:value=[writer] entering auth_pam_map_group_to_user auth_pam_map_group_to_user:pam_user=gkodinov, name=admin, value=writer examining member root examining member gkodinov substitution was made to mysql user writer leaving auth_pam_map_group_to_user on /Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/authentication_pam.c:118 auth_pam_walk_namevalue_list:found mapping leaving auth_pam_walk_namevalue_list on /Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/parser.c:270 auth_pam_walk_namevalue_list returned 0 leaving auth_pam_map_groups on /Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/authentication_pam.c:171 auth_pam_server:authenticated_as=writer auth_pam_server: rc=0 leaving auth_pam_server on /Users/gkodinov/mysql/work/x-5.5.16-release-basket/release/plugin/pam-authentication-plugin/src/authentication_pam.c:429
The Windows authentication plugin is an extension included in MySQL Enterprise Edition, a commercial product. To learn more about commercial products, see http://www.mysql.com/products/.
As of MySQL 5.6.10, MySQL Enterprise Edition for Windows includes an authentication plugin that performs external authentication on Windows, enabling MySQL Server to use native Windows services to authenticate client connections. Users who have logged in to Windows can connect from MySQL client programs to the server based on the information in their environment without specifying an additional password.
The client and server exchange data packets in the authentication handshake. As a result of this exchange, the server creates a security context object that represents the identity of the client in the Windows OS. This identity includes the name of the client account. The Windows authentication plugin uses the identity of the client to check whether it is a given account or a member of a group. By default, negotiation uses Kerberos to authenticate, then NTLM if Kerberos is unavailable.
The Windows authentication plugin provides these capabilities:
External authentication: The plugin enables MySQL Server to accept connections from users defined outside the MySQL grant tables.
Proxy user support: The plugin can return to MySQL a user
name different from the client user. This means that the
plugin can return the MySQL user that defines the privileges
the external Windows-authenticated user should have. For
example, a Windows user named joe can
connect and have the privileges of the MySQL user named
developer.
The following table shows the plugin and library file names. The
file location must be the directory named by the
plugin_dir system variable. For
installation information, see
Section 7.1.6.1, “Installing the Windows Authentication Plugin”.
Table 7.5 MySQL Windows Authentication Plugin
| Server-side plugin name | authentication_windows |
| Client-side plugin name | authentication_windows_client |
| Library file name | authentication_windows.dll |
The library file includes only the server-side plugin. The
client-side plugin is built into the
libmysqlclient client library.
The server-side Windows authentication plugin is included only in MySQL Enterprise Edition. It is not included in MySQL community distributions. The client-side plugin is included in all distributions, including community distributions. This permits clients from any distribution to connect to a server that has the server-side plugin loaded.
The Windows authentication plugin is supported on any version of Windows supported by MySQL 5.6 (see http://www.mysql.com/support/supportedplatforms/database.html). It requires MySQL Server 5.6.10 or higher.
For general information about pluggable authentication in MySQL, see Section 5.7, “Pluggable Authentication”. For proxy user information, see Section 5.8, “Proxy Users”.
This section describes how to install the Windows authentication plugin. For general information about installing plugins, see Installing and Uninstalling Plugins.
To be usable by the server, the plugin library file must be
located in the MySQL plugin directory (the directory named by
the plugin_dir system
variable). If necessary, set the value of
plugin_dir at server startup
to tell the server the plugin directory location.
To enable the plugin, start the server with the
--plugin-load option. For
example, put these lines in your my.ini
file:
[mysqld] plugin-load=authentication_windows.dll
To verify plugin installation, examine the
INFORMATION_SCHEMA.PLUGINS table
or use the SHOW PLUGINS
statement (see
Obtaining Server Plugin Information). For example:
mysql>SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS->WHERE PLUGIN_NAME LIKE 'authentication%';+------------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +------------------------+---------------+ | authentication_windows | ACTIVE | +------------------------+---------------+
To associate a MySQL account with the Windows authentication
plugin, use the plugin name
authentication_windows in the
IDENTIFIED WITH clause of
CREATE USER or
GRANT statement that creates
the account.
The Windows authentication plugin supports the use of MySQL accounts such that users who have logged in to Windows can connect to the MySQL server without having to specify an additional password. It is assumed that the server-side plugin is enabled, as described previously. Once the DBA has enabled the server-side plugin and set up accounts to use it, clients can connect using those accounts with no other setup required on their part.
To refer to the Windows authentication plugin in the
IDENTIFIED WITH clause of a
CREATE USER or
GRANT statement, use the name
authentication_windows. Suppose that the
Windows users Rafal and
Tasha should be permitted to connect to
MySQL, as well as any users in the
Administrators or Power
Users group. To set this up, create a MySQL account
named sql_admin that uses the Windows
plugin for authentication:
CREATE USER sql_admin IDENTIFIED WITH authentication_windows AS 'Rafal, Tasha, Administrators, "Power Users"';
The plugin name is authentication_windows.
The string following the AS keyword is the
authentication string. It specifies that the Windows users
named Rafal or Tasha are
permitted to authenticate to the server as the MySQL user
sql_admin, as are any Windows users in the
Administrators or Power
Users group. The latter group name contains a space,
so it must be quoted with double quote characters.
After you create the sql_admin account, a
user who has logged in to Windows can attempt to connect to
the server using that account:
C:\> mysql --user=sql_admin
No password is required here. The
authentication_windows plugin uses the
Windows security API to check which Windows user is
connecting. If that user is named Rafal or
Tasha, or is in the
Administrators or Power
Users group, the server grants access and the client
is authenticated as sql_admin and has
whatever privileges are granted to the
sql_admin account. Otherwise, the server
denies access.
Authentication string syntax for the Windows authentication plugin follows these rules:
The string consists of one or more user mappings separated by commas.
Each user mapping associates a Windows user or group name with a MySQL user name:
win_user_or_group_name=mysql_user_namewin_user_or_group_name
For the latter syntax, with no
mysql_user_name value given,
the implicit value is the MySQL user created by the
CREATE USER statement.
Thus, these statements are equivalent:
CREATE USER sql_admin
IDENTIFIED WITH authentication_windows
AS 'Rafal, Tasha, Administrators, "Power Users"';
CREATE USER sql_admin
IDENTIFIED WITH authentication_windows
AS 'Rafal=sql_admin, Tasha=sql_admin, Administrators=sql_admin,
"Power Users"=sql_admin';
Each backslash ('\') in a value must be
doubled because backslash is the escape character in MySQL
strings.
Leading and trailing spaces not inside double quotation marks are ignored.
Unquoted win_user_or_group_name
and mysql_user_name values can
contain anything except equal sign, comma, or space.
If a win_user_or_group_name and
or mysql_user_name value is
quoted with double quotation marks, everything between the
quotation marks is part of the value. This is necessary,
for example, if the name contains space characters. All
characters within double quotes are legal except double
quotation mark and backslash. To include either character,
escape it with a backslash.
win_user_or_group_name values
use conventional syntax for Windows principals, either
local or in a domain. Examples (note the doubling of
backslashes):
domain\\user .\\user domain\\group .\\group BUILTIN\\WellKnownGroup
When invoked by the server to authenticate a client, the
plugin scans the authentication string left to right for a
user or group match to the Windows user. If there is a match,
the plugin returns the corresponding
mysql_user_name to the MySQL
server. If there is no match, authentication fails.
A user name match takes preference over a group name match.
Suppose that the Windows user named
win_user is a member of
win_group and the authentication string
looks like this:
'win_group = sql_user1, win_user = sql_user2'
When win_user connects to the MySQL server,
there is a match both to win_group and to
win_user. The plugin authenticates the user
as sql_user2 because the more-specific user
match takes precedence over the group match, even though the
group is listed first in the authentication string.
Windows authentication always works for connections from the same computer on which the server is running. For cross-computer connections, both computers must be registered with Windows Active Directory. If they are in the same Windows domain, it is unnecessary to specify a domain name. It is also possible to permit connections from a different domain, as in this example:
CREATE USER sql_accounting IDENTIFIED WITH authentication_windows AS 'SomeDomain\\Accounting';
Here SomeDomain is the name of the other
domain. The backslash character is doubled because it is the
MySQL escape character within strings.
MySQL supports the concept of proxy users whereby a client can connect and authenticate to the MySQL server using one account but while connected has the privileges of another account (see Section 5.8, “Proxy Users”). Suppose that you want Windows users to connect using a single user name but be mapped based on their Windows user and group names onto specific MySQL accounts as follows:
The local_user and
MyDomain\domain_user local and domain
Windows users should map to the
local_wlad MySQL account.
Users in the MyDomain\Developers domain
group should map to the local_dev MySQL
account.
Local machine administrators should map to the
local_admin MySQL account.
To set this up, create a proxy account for Windows users to
connect to, and configure this account so that users and
groups map to the appropriate MySQL accounts
(local_wlad, local_dev,
local_admin). In addition, grant the MySQL
accounts the privileges appropriate to the operations they
need to perform. The following instructions use
win_proxy as the proxy account, and
local_wlad, local_dev,
and local_admin as the proxied accounts.
Create the proxy MySQL account:
CREATE USER win_proxy
IDENTIFIED WITH authentication_windows
AS 'local_user = local_wlad,
MyDomain\\domain_user = local_wlad,
MyDomain\\Developers = local_dev,
BUILTIN\\Administrators = local_admin';
For proxying to work, the proxied accounts must exist, so create them:
CREATE USER local_wlad IDENTIFIED BY 'wlad_pass'; CREATE USER local_dev IDENTIFIED BY 'dev_pass'; CREATE USER local_admin IDENTIFIED BY 'admin_pass';
If you do not let anyone know the passwords for these accounts, other users cannot use them to connect directly to the MySQL server.
You should also issue GRANT
statements (not shown) that grant each proxied account the
privileges it needs.
The proxy account must have the
PROXY privilege for each of
the proxied accounts:
GRANT PROXY ON local_wlad TO win_proxy; GRANT PROXY ON local_dev TO win_proxy; GRANT PROXY ON local_admin TO win_proxy;
Now the Windows users local_user and
MyDomain\domain_user can connect to the
MySQL server as win_proxy and when
authenticated have the privileges of the account given in the
authentication string—in this case,
local_wlad. A user in the
MyDomain\Developers group who connects as
win_proxy has the privileges of the
local_dev account. A user in the
BUILTIN\Administrators group has the
privileges of the local_admin account.
To configure authentication so that all Windows users who do
not have their own MySQL account go through a proxy account,
substitute the default proxy user (''@'')
for win_proxy in the preceding
instructions. For information about the default proxy user,
see Section 5.8, “Proxy Users”.
If your MySQL installation has anonymous users, they might conflict with the default proxy user. For more information about this problem, and ways of dealing with it, see Default Proxy User and Anonymous User Conflicts.
To use the Windows authentication plugin with Connector/Net connection strings in Connection/Net 6.4.4 and higher, see Using the Windows Native Authentication Plugin.
Additional control over the Windows authentication plugin is
provided by the
authentication_windows_use_principal_name
and
authentication_windows_log_level
system variables. See
Server System Variables.
As of MySQL 5.6.2, a client-side authentication plugin is available that sends the password to the server without hashing or encryption. This plugin is built into the MySQL client library.
The following table shows the plugin name.
Table 7.6 MySQL Cleartext Authentication Plugin
| Server-side plugin name | None, see discussion |
| Client-side plugin name | mysql_clear_password |
| Library file name | None (plugin is built in) |
With native MySQL authentication, the client performs one-way hashing on the password before sending it to the server. This enables the client to avoid sending the password in clear text. See Section 2.2.4, “Password Hashing in MySQL”. However, because the hash algorithm is one way, the original password cannot be recovered on the server side.
One-way hashing cannot be done for authentication schemes that
require the server to receive the password as entered on the
client side. In such cases, the
mysql_clear_password client-side plugin can
be used to send the password to the server in clear text. There
is no corresponding server-side plugin. Rather, the client-side
plugin can be used by any server-side plugin that needs a clear
text password. (The PAM authentication plugin is one such; see
Section 7.1.5, “The PAM Authentication Plugin”.)
For general information about pluggable authentication in MySQL, see Section 5.7, “Pluggable Authentication”.
Sending passwords in clear text may be a security problem in some configurations. To avoid problems if there is any possibility that the password would be intercepted, clients should connect to MySQL Server using a method that protects the password. Possibilities include SSL (see Chapter 6, Using Secure Connections), IPsec, or a private network.
As of MySQL 5.6.7, to make inadvertent use of this plugin less likely, it is required that clients explicitly enable it. This can be done several ways:
Set the LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN
environment variable to a value that begins with
1, Y, or
y. This enables the plugin for all client
connections.
The mysql, mysqladmin,
and mysqlslap client programs support an
--enable-cleartext-plugin option that
enables the plugin on a per-invocation basis.
The mysql_options() C API
function supports a
MYSQL_ENABLE_CLEARTEXT_PLUGIN option that
enables the plugin on a per-connection basis. Also, any
program that uses libmysqlclient and
reads option files can enable the plugin by including an
enable-cleartext-plugin option in an
option group read by the client library.
As of MySQL 5.6.2, a server-side authentication plugin is available that authenticates clients that connect from the local host through the Unix socket file.
The source code for this plugin can be examined as a relatively simple example demonstrating how to write a loadable authentication plugin.
The following table shows the plugin and library file names. The
file name suffix might differ on your system. The file location
is the directory named by the
plugin_dir system variable. For
installation information, see
Section 5.7, “Pluggable Authentication”.
Table 7.7 MySQL Socket Peer-Credential Authentication Plugin
| Server-side plugin name | auth_socket |
| Client-side plugin name | None, see discussion |
| Library file name | auth_socket.so |
The auth_socket authentication plugin
authenticates clients that connect from the local host through
the Unix socket file. The plugin uses the
SO_PEERCRED socket option to obtain
information about the user running the client program. Thus, the
plugin can be built only on systems that support the
SO_PEERCRED option, such as Linux.
The plugin checks whether the user name matches the MySQL user name specified by the client program to the server, and permits the connection only if the names match.
Suppose that a MySQL account is created for a user named
valerie who is to be authenticated by the
auth_socket plugin for connections from the
local host through the socket file:
CREATE USER 'valerie'@'localhost' IDENTIFIED WITH auth_socket;
If a user on the local host with a login name of
stefanie invokes mysql
with the option --user=valerie to connect
through the socket file, the server uses
auth_socket to authenticate the client. The
plugin determines that the --user option value
(valerie) differs from the client user's name
(stephanie) and refuses the connection. If a
user named valerie tries the same thing, the
plugin finds that the user name and the MySQL user name are both
valerie and permits the connection. However,
the plugin refuses the connection even for
valerie if the connection is made using a
different protocol, such as TCP/IP.
For general information about pluggable authentication in MySQL, see Section 5.7, “Pluggable Authentication”.
MySQL includes a test plugin that authenticates using MySQL native authentication, but is a loadable plugin (not built in) and must be installed prior to use. It can authenticate against either normal or older (shorter) password hash values.
This plugin is intended for testing and development purposes, and not for use in production environments. The test plugin source code is separate from the server source, unlike the built-in native plugin, so it can be examined as a relatively simple example demonstrating how to write a loadable authentication plugin.
The following table shows the plugin and library file names. The
file name suffix might differ on your system. The file location
is the directory named by the
plugin_dir system variable. For
installation information, see
Section 5.7, “Pluggable Authentication”.
Table 7.8 MySQL Test Authentication Plugin
| Server-side plugin name | test_plugin_server |
| Client-side plugin name | auth_test_plugin |
| Library file name | auth_test_plugin.so |
Because the test plugin authenticates the same way as native
MySQL authentication, provide the usual
--user and
--password options that you
normally use for accounts that use native authentication when
you connect to the server. For example:
shell> mysql --user=your_name --password=your_pass
For general information about pluggable authentication in MySQL, see Section 5.7, “Pluggable Authentication”.
The validate_password plugin (available as of
MySQL 5.6.6) serves to test passwords and improve security. The
plugin exposes a set of system variables that enable you to define
password policy.
This plugin implements two capabilities:
In statements that assign a password supplied as a cleartext
value, the plugin checks the password against the current
password policy and rejects it if it is weak (the statement
returns an
ER_NOT_VALID_PASSWORD error).
This affects the CREATE USER,
GRANT, and
SET PASSWORD statements.
Passwords given as arguments to the
PASSWORD() and
OLD_PASSWORD() functions are
checked as well.
The
VALIDATE_PASSWORD_STRENGTH()
SQL function assesses the strength of potential passwords. The
function takes a password argument and returns an integer from
0 (weak) to 100 (strong).
For example, the cleartext password in the following statement is checked. Under the default password policy, which requires passwords to be at least 8 characters long, the password is weak and the statement produces an error:
mysql> SET PASSWORD = PASSWORD('abc');
ERROR 1819 (HY000): Your password does not satisfy the current
policy requirements
Passwords specified as hashed values are not checked because the original password value is not available:
mysql> SET PASSWORD = '*0D3CED9BEC10A777AEC23CCC353A8C08A633045E';
Query OK, 0 rows affected (0.01 sec)
System variables having names of the form
validate_password_
represent the parameters that control password policy. To
configure password checking, modify these variables; see
Section 7.2.2, “Password Validation Plugin Options and Variables”.
xxx
If the validate_password plugin is not
installed, the
validate_password_
system variables are not available, passwords in statements are
not checked, and the
xxxVALIDATE_PASSWORD_STRENGTH()
function always returns 0. For example, without the plugin
installed, accounts can be assigned passwords shorter than 8
characters.
Assuming that the validate_password plugin is
installed, it implements three levels of password checking:
LOW, MEDIUM, and
STRONG. The default is
MEDIUM; to change this, modify the value of
validate_password_policy. The
policies implement increasingly strict password tests. The
following descriptions refer to default parameter values, which
can be modified by changing the appropriate system variables.
LOW policy tests password length only.
Passwords must be at least 8 characters long.
MEDIUM policy adds the conditions that
passwords must contain at least 1 numeric character, 1
lowercase and uppercase character, and 1 special
(nonalphanumeric) character.
STRONG policy adds the condition that
password substrings of length 4 or longer must not match words
in the dictionary file, if one has been specified.
This section describes how to install the
validate_password password-validation plugin.
For general information about installing plugins, see
Installing and Uninstalling Plugins.
To be usable by the server, the plugin library file must be
located in the MySQL plugin directory (the directory named by
the plugin_dir system
variable). If necessary, set the value of
plugin_dir at server startup to
tell the server the plugin directory location.
The plugin library file base name is
validate_password. The file name suffix
differs per platform (for example, .so for
Unix and Unix-like systems, .dll for
Windows).
To load the plugin at server startup, use the
--plugin-load option to name the
library file that contains the plugin. With this plugin-loading
method, the option must be given each time the server starts.
For example, put these lines in your my.cnf
file (adjust the .so suffix for your
platform as necessary):
[mysqld] plugin-load=validate_password.so
Alternatively, to register the plugin at runtime, use this statement (adjust the extension as necessary):
INSTALL PLUGIN validate_password SONAME 'validate_password.so';
INSTALL PLUGIN loads the plugin,
and also registers it in the mysql.plugins
table to cause the plugin to be loaded for each subsequent
normal server startup.
To verify plugin installation, examine the
INFORMATION_SCHEMA.PLUGINS table or
use the SHOW PLUGINS statement
(see Obtaining Server Plugin Information). For
example:
mysql>SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS->WHERE PLUGIN_NAME LIKE 'validate%';+-------------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +-------------------+---------------+ | validate_password | ACTIVE | +-------------------+---------------+
If the plugin has been previously registered with
INSTALL PLUGIN or is loaded with
--plugin-load, you can use the
--validate-password option at server startup to
control plugin activation. For example, to load the plugin at
startup and prevent it from being removed at runtime, use these
options:
[mysqld] plugin-load=validate_password.so validate-password=FORCE_PLUS_PERMANENT
If it is desired to prevent the server from running without the
password-validation plugin, use
--validate-password with a value
of FORCE or
FORCE_PLUS_PERMANENT to force server startup
to fail if the plugin does not initialize successfully.
To control the activation of the
validate_password plugin, use this option:
| Introduced | 5.6.6 | ||
| Command-Line Format | --validate-password[=value] | ||
| Permitted Values | Type | enumeration | |
| Default | ON | ||
| Valid Values | ON | ||
OFF | |||
FORCE | |||
FORCE_PLUS_PERMANENT | |||
This option controls how the server loads the
validate_password plugin at startup. The
value should be one of those available for plugin-loading
options, as described in
Installing and Uninstalling Plugins. For example,
--validate-password=FORCE_PLUS_PERMANENT
tells the server to load the plugin at startup and prevents
it from being removed while the server is running.
This option is available only if the
validate_password plugin has been
previously registered with INSTALL
PLUGIN or is loaded with
--plugin-load. See
Section 7.2.1, “Password Validation Plugin Installation”.
If the validate_password plugin is enabled,
it exposes several system variables representing the parameters
that control password checking:
mysql> SHOW VARIABLES LIKE 'validate_password%';
+--------------------------------------+--------+
| Variable_name | Value |
+--------------------------------------+--------+
| validate_password_dictionary_file | |
| validate_password_length | 8 |
| validate_password_mixed_case_count | 1 |
| validate_password_number_count | 1 |
| validate_password_policy | MEDIUM |
| validate_password_special_char_count | 1 |
+--------------------------------------+--------+
To change how passwords are checked, you can set these system variables at server startup or at runtime. The following list describes the meaning of each variable.
validate_password_dictionary_file
| Introduced | 5.6.6 | ||
| System Variable (<= 5.6.25) | Name | validate_password_dictionary_file | |
| Variable Scope | Global | ||
| Dynamic Variable | No | ||
| System Variable | Name | validate_password_dictionary_file | |
| Variable Scope | Global | ||
| Dynamic Variable | No | ||
| System Variable (>= 5.6.26) | Name | validate_password_dictionary_file | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | file name | |
The path name of the dictionary file used by the
validate_password plugin for checking
passwords. This variable is unavailable unless that plugin
is installed.
By default, this variable has an empty value and dictionary
checks are not performed. To enable dictionary checks, you
must set this variable to a nonempty value. If the file is
named as a relative path, it is interpreted relative to the
server data directory. Its contents should be lowercase, one
word per line. Contents are treated as having a character
set of utf8. The maximum permitted file
size is 1MB.
For the dictionary file to be used during password checking,
the password policy must be set to 2
(STRONG); see the description of the
validate_password_policy
system variable. Assuming that is true, each substring of
the password of length 4 up to 100 is compared to the words
in the dictionary file. Any match causes the password to be
rejected. Comparisons are not case sensitive.
For
VALIDATE_PASSWORD_STRENGTH()
the password is checked against all policies, including
STRONG, so the strength assessment
includes the dictionary check regardless of the
validate_password_policy
value.
Before MySQL 5.6.26, changes to the dictionary file while
the server is running require a restart for the server to
recognize the changes. As of MySQL 5.6.26,
validate_password_dictionary_file
can be set at runtime and assigning a value causes the named
file to be read without a restart.
| Introduced | 5.6.6 | ||
| System Variable | Name | validate_password_length | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | integer | |
| Default | 8 | ||
| Min Value | 0 | ||
The minimum number of characters that passwords checked by
the validate_password plugin must have.
This variable is unavailable unless that plugin is
installed.
The
validate_password_length
minimum value is a function of several other related system
variables. As of MySQL 5.6.10, the server will not set the
value less than the value of this expression:
validate_password_number_count + validate_password_special_char_count + (2 * validate_password_mixed_case_count)
If the validate_password plugin adjusts
the value of
validate_password_length
due to the preceding constraint, it writes a message to the
error log.
validate_password_mixed_case_count
| Introduced | 5.6.6 | ||
| System Variable | Name | validate_password_mixed_case_count | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | integer | |
| Default | 1 | ||
| Min Value | 0 | ||
The minimum number of lowercase and uppercase characters
that passwords checked by the
validate_password plugin must have if the
password policy is MEDIUM or stronger.
This variable is unavailable unless that plugin is
installed.
validate_password_number_count
| Introduced | 5.6.6 | ||
| System Variable | Name | validate_password_number_count | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | integer | |
| Default | 1 | ||
| Min Value | 0 | ||
The minimum number of numeric (digit) characters that
passwords checked by the
validate_password plugin must have if the
password policy is MEDIUM or stronger.
This variable is unavailable unless that plugin is
installed.
| Introduced | 5.6.6 | ||
| System Variable | Name | validate_password_policy | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | enumeration | |
| Default | 1 | ||
| Valid Values | 0 | ||
1 | |||
2 | |||
The password policy enforced by the
validate_password plugin. This variable
is unavailable unless that plugin is installed.
The
validate_password_policy
value can be specified using numeric values 0, 1, 2, or the
corresponding symbolic values LOW,
MEDIUM, STRONG. The
following table describes the tests performed for each
policy. For the length test, the required length is the
value of the
validate_password_length
system variable. Similarly, the required values for the
other tests are given by other
validate_password_
variables.
xxx
| Policy | Tests Performed |
|---|---|
0 or LOW | Length |
1 or MEDIUM | Length; numeric, lowercase/uppercase, and special characters |
2 or STRONG | Length; numeric, lowercase/uppercase, and special characters; dictionary file |
Before MySQL 5.6.10,
validate_password_policy was named
validate_password_policy_number.
validate_password_special_char_count
| Introduced | 5.6.6 | ||
| System Variable | Name | validate_password_special_char_count | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | integer | |
| Default | 1 | ||
| Min Value | 0 | ||
The minimum number of nonalphanumeric characters that
passwords checked by the
validate_password plugin must have if the
password policy is MEDIUM or stronger.
This variable is unavailable unless that plugin is
installed.
If the validate_password plugin is enabled,
it exposes status variables that provide operational
information:
mysql> SHOW STATUS LIKE 'validate_password%';
+-----------------------------------------------+---------------------+
| Variable_name | Value |
+-----------------------------------------------+---------------------+
| validate_password_dictionary_file_last_parsed | 2015-06-29 11:08:51 |
| validate_password_dictionary_file_words_count | 1902 |
+-----------------------------------------------+---------------------+
The following list describes the meaning of each status variable.
validate_password_dictionary_file_last_parsed
When the dictionary file was last parsed.
This variable was added in MySQL 5.6.26.
validate_password_dictionary_file_words_count
The number of words read from the dictionary file.
This variable was added in MySQL 5.6.26.
MySQL Enterprise Audit is an extension included in MySQL Enterprise Edition, a commercial product. To learn more about commercial products, see http://www.mysql.com/products/.
As of MySQL 5.6.10, MySQL Enterprise Edition includes MySQL Enterprise Audit, implemented using a
server plugin named audit_log. MySQL Enterprise Audit uses
the open MySQL Audit API to enable standard, policy-based
monitoring and logging of connection and query activity executed
on specific MySQL servers. Designed to meet the Oracle audit
specification, MySQL Enterprise Audit provides an out of box, easy to use
auditing and compliance solution for applications that are
governed by both internal and external regulatory guidelines.
When installed, the audit plugin enables MySQL Server to produce a log file containing an audit record of server activity. The log contents include when clients connect and disconnect, and what actions they perform while connected, such as which databases and tables they access.
After you install the plugin (see
Section 7.3.1, “Installing MySQL Enterprise Audit”), it writes an audit log
file. By default, the file is named audit.log
in the server data directory. To change the name of the file, set
the audit_log_file system
variable at server startup.
Audit log file contents are not encrypted. See Section 7.3.2, “MySQL Enterprise Audit Security Considerations”.
The audit log file is written in XML, with auditable events
encoded as <AUDIT_RECORD> elements. To
select the file format, set the
audit_log_format system variable
at server startup. For details on file format and contents, see
Section 7.3.3, “The Audit Log File”.
For more information about controlling how logging occurs, see Section 7.3.4, “Audit Log Logging Control”. To perform filtering of audited events, see Section 7.3.5, “Audit Log Filtering”. For descriptions of the parameters used to configure the audit log plugin, see Section 7.3.6.2, “Audit Log Options and System Variables”.
If the audit_log plugin is enabled, the
Performance Schema (see MySQL Performance Schema) has
instrumentation for the audit log plugin. To identify the relevant
instruments, use this query:
SELECT NAME FROM performance_schema.setup_instruments WHERE NAME LIKE '%/alog/%';
Several changes were made to the audit log plugin in MySQL 5.6.14 for better compatibility with Oracle Audit Vault.
A new audit log file format was implemented. It is possible to
select either the old or new format using the
audit_log_format system variable,
which has permitted values of OLD and
NEW (default OLD). The two
formats differ as follows:
Information within <AUDIT_RECORD>
elements written in the old format using attributes is written
in the new format using subelements.
The new format includes more information in
<AUDIT_RECORD> elements. Every
element includes a RECORD_ID value
providing a unique identifier. The
TIMESTAMP value includes time zone
information. Query records include HOST,
IP, OS_LOGIN, and
USER information, as well as
COMMAND_CLASS and
STATUS_CODE values.
Example of old <AUDIT_RECORD> format:
<AUDIT_RECORD TIMESTAMP="2013-09-15T15:27:27" NAME="Query" CONNECTION_ID="3" STATUS="0" SQLTEXT="SELECT 1" />
Example of new <AUDIT_RECORD> format:
<AUDIT_RECORD> <TIMESTAMP>2013-09-15T15:27:27 UTC</TIMESTAMP> <RECORD_ID>3998_2013-09-15T15:27:27</RECORD_ID> <NAME>Query</NAME> <CONNECTION_ID>3</CONNECTION_ID> <STATUS>0</STATUS> <STATUS_CODE>0</STATUS_CODE> <USER>root[root] @ localhost [127.0.0.1]</USER> <OS_LOGIN></OS_LOGIN> <HOST>localhost</HOST> <IP>127.0.0.1</IP> <COMMAND_CLASS>select</COMMAND_CLASS> <SQLTEXT>SELECT 1</SQLTEXT> </AUDIT_RECORD>
When the audit log plugin rotates the audit log file, it uses a
different file name format. For a log file named
audit.log, the plugin previously renamed the
file to
audit.log..
The plugin now renames the file to
TIMESTAMPaudit.log.
to indicate that it is an XML file.
TIMESTAMP.xml
If you change the value of
audit_log_format, use this
procedure to avoid writing log entries in one format to an
existing log file that contains entries in a different format:
Stop the server.
Rename the current audit log file manually.
Restart the server with the new value of
audit_log_format. The audit
log plugin creates a new log file, which will contain log
entries in the selected format.
The API for writing audit plugins has also changed. The
mysql_event_general structure has new members
to represent client host name and IP address, command class, and
external user. For more information, see
Writing Audit Plugins.
This section describes how to install MySQL Enterprise Audit, which is
implemented using the audit_log plugin. For
general information about installing plugins, see
Installing and Uninstalling Plugins.
If installed, the audit_log plugin involves
some minimal overhead even when disabled. To avoid this
overhead, do not install MySQL Enterprise Audit unless you plan to use it.
To be usable by the server, the plugin library file must be
located in the MySQL plugin directory (the directory named by
the plugin_dir system
variable). If necessary, set the value of
plugin_dir at server startup to
tell the server the plugin directory location.
The plugin library file base name is
audit_log. The file name suffix differs per
platform (for example, .so for Unix and
Unix-like systems, .dll for Windows).
To load the plugin at server startup, use the
--plugin-load option to name the
library file that contains the plugin. With this plugin-loading
method, the option must be given each time the server starts.
For example, put the following lines in your
my.cnf file (adjust the
.so suffix for your platform as necessary):
[mysqld] plugin-load=audit_log.so
Alternatively, to register the plugin at runtime, use this statement (adjust the suffix as necessary):
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
INSTALL PLUGIN loads the plugin,
and also registers it in the mysql.plugins
table to cause the plugin to be loaded for each subsequent
normal server startup.
To verify plugin installation, examine the
INFORMATION_SCHEMA.PLUGINS table or
use the SHOW PLUGINS statement
(see Obtaining Server Plugin Information). For
example:
mysql>SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS->WHERE PLUGIN_NAME LIKE 'audit%';+-------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +-------------+---------------+ | audit_log | ACTIVE | +-------------+---------------+
If the plugin has been previously registered with
INSTALL PLUGIN or is loaded with
--plugin-load, you can use the
--audit-log option at server startup to control
plugin activation. For example, to load the plugin at startup
and prevent it from being removed at runtime, use these options:
[mysqld] plugin-load=audit_log.so audit-log=FORCE_PLUS_PERMANENT
If it is desired to prevent the server from running without the
audit plugin, use --audit-log
with a value of FORCE or
FORCE_PLUS_PERMANENT to force server startup
to fail if the plugin does not initialize successfully.
For additional information about the parameters used to
configure operation of the audit_log plugin,
see Section 7.3.6.2, “Audit Log Options and System Variables”.
Audit log file contents are not encrypted. See Section 7.3.2, “MySQL Enterprise Audit Security Considerations”.
Contents of the audit log file produced by the
audit_log plugin are not encrypted and may
contain sensitive information, such as the text of SQL
statements. For security reasons, this file should be written to
a directory accessible only to the MySQL server and users with a
legitimate reason to view the log. The default file is
audit.log in the data directory. This can
be changed by setting the
audit_log_file system variable
at server startup.
Audit log file contents are not encrypted. See Section 7.3.2, “MySQL Enterprise Audit Security Considerations”.
The audit log file is written as XML, using UTF-8 (up to 4 bytes
per character). The root element is
<AUDIT>. The closing
</AUDIT> tag of the root element is
written when the audit log plugin terminates, so the tag is not
present in the file while the plugin is active.
The root element contains
<AUDIT_RECORD> elements, each of which
provides information about an audited event.
In MySQL 5.6.14, a new audit log file format was implemented for
better compatibility with Oracle Audit Vault. It is possible to
select either the old or new format using the
audit_log_format system
variable, which has permitted values of OLD
and NEW (default OLD).
If you change the value of
audit_log_format, use this
procedure to avoid writing log entries in one format to an
existing log file that contains entries in a different format:
Stop the server.
Rename the current audit log file manually.
Restart the server with the new value of
audit_log_format. The audit
log plugin will create a new log file, which will contain
log entries in the selected format.
Here is a sample log file in the default (old) format, reformatted slightly for readability:
<?xml version="1.0" encoding="UTF-8"?>
<AUDIT>
<AUDIT_RECORD
TIMESTAMP="2012-08-02T14:52:12"
NAME="Audit"
SERVER_ID="1"
VERSION="1"
STARTUP_OPTIONS="--port=3306"
OS_VERSION="i686-Linux"
MYSQL_VERSION="5.6.10-log"/>
<AUDIT_RECORD
TIMESTAMP="2012-08-02T14:52:41"
NAME="Connect"
CONNECTION_ID="1"
STATUS="0"
USER="root"
PRIV_USER="root"
OS_LOGIN=""
PROXY_USER=""
HOST="localhost"
IP="127.0.0.1"
DB=""/>
<AUDIT_RECORD
TIMESTAMP="2012-08-02T14:53:45"
NAME="Query"
CONNECTION_ID="1"
STATUS="0"
SQLTEXT="INSERT INTO t1 () VALUES()"/>
<AUDIT_RECORD
TIMESTAMP="2012-08-02T14:53:51"
NAME="Quit"
CONNECTION_ID="1"
STATUS="0"/>
<AUDIT_RECORD
TIMESTAMP="2012-08-06T14:21:03"
NAME="NoAudit"
SERVER_ID="1"/>
</AUDIT>
Here is a sample log file in the new format, reformatted slightly for readability:
<?xml version="1.0" encoding="UTF-8"?>
<AUDIT>
<AUDIT_RECORD>
<TIMESTAMP>2013-09-17T15:03:24 UTC</TIMESTAMP>
<RECORD_ID>1_2013-09-17T15:03:24</RECORD_ID>
<NAME>Audit</NAME>
<SERVER_ID>1</SERVER_ID>
<VERSION>1</VERSION>
<STARTUP_OPTIONS>/usr/local/mysql/bin/mysqld
--socket=/usr/local/mysql/mysql.sock
--port=3306</STARTUP_OPTIONS>
<OS_VERSION>x86_64-osx10.6</OS_VERSION>
<MYSQL_VERSION>5.7.2-m12-log</MYSQL_VERSION>
</AUDIT_RECORD>
<AUDIT_RECORD>
<TIMESTAMP>2013-09-17T15:03:40 UTC</TIMESTAMP>
<RECORD_ID>2_2013-09-17T15:03:24</RECORD_ID>
<NAME>Connect</NAME>
<CONNECTION_ID>2</CONNECTION_ID>
<STATUS>0</STATUS>
<STATUS_CODE>0</STATUS_CODE>
<USER>root</USER>
<OS_LOGIN></OS_LOGIN>
<HOST>localhost</HOST>
<IP>127.0.0.1</IP>
<COMMAND_CLASS>connect</COMMAND_CLASS>
<PRIV_USER>root</PRIV_USER>
<PROXY_USER></PROXY_USER>
<DB>test</DB>
</AUDIT_RECORD>
...
<AUDIT_RECORD>
<TIMESTAMP>2013-09-17T15:03:41 UTC</TIMESTAMP>
<RECORD_ID>4_2013-09-17T15:03:24</RECORD_ID>
<NAME>Query</NAME>
<CONNECTION_ID>2</CONNECTION_ID>
<STATUS>0</STATUS>
<STATUS_CODE>0</STATUS_CODE>
<USER>root[root] @ localhost [127.0.0.1]</USER>
<OS_LOGIN></OS_LOGIN>
<HOST>localhost</HOST>
<IP>127.0.0.1</IP>
<COMMAND_CLASS>drop_table</COMMAND_CLASS>
<SQLTEXT>DROP TABLE IF EXISTS t</SQLTEXT>
</AUDIT_RECORD>
<AUDIT_RECORD>
<TIMESTAMP>2013-09-17T15:03:41 UTC</TIMESTAMP>
<RECORD_ID>5_2013-09-17T15:03:24</RECORD_ID>
<NAME>Query</NAME>
<CONNECTION_ID>2</CONNECTION_ID>
<STATUS>0</STATUS>
<STATUS_CODE>0</STATUS_CODE>
<USER>root[root] @ localhost [127.0.0.1]</USER>
<OS_LOGIN></OS_LOGIN>
<HOST>localhost</HOST>
<IP>127.0.0.1</IP>
<COMMAND_CLASS>create_table</COMMAND_CLASS>
<SQLTEXT>CREATE TABLE t (i INT)</SQLTEXT>
</AUDIT_RECORD>
...
<AUDIT_RECORD>
<TIMESTAMP>2013-09-17T15:03:41 UTC</TIMESTAMP>
<RECORD_ID>7_2013-09-17T15:03:24</RECORD_ID>
<NAME>Quit</NAME>
<CONNECTION_ID>2</CONNECTION_ID>
<STATUS>0</STATUS>
<STATUS_CODE>0</STATUS_CODE>
<USER></USER>
<OS_LOGIN></OS_LOGIN>
<HOST></HOST>
<IP></IP>
<COMMAND_CLASS>connect</COMMAND_CLASS>
</AUDIT_RECORD>
...
<AUDIT_RECORD>
<TIMESTAMP>2013-09-17T15:03:47 UTC</TIMESTAMP>
<RECORD_ID>9_2013-09-17T15:03:24</RECORD_ID>
<NAME>Shutdown</NAME>
<CONNECTION_ID>3</CONNECTION_ID>
<STATUS>0</STATUS>
<STATUS_CODE>0</STATUS_CODE>
<USER>root[root] @ localhost [127.0.0.1]</USER>
<OS_LOGIN></OS_LOGIN>
<HOST>localhost</HOST>
<IP>127.0.0.1</IP>
<COMMAND_CLASS></COMMAND_CLASS>
</AUDIT_RECORD>
<AUDIT_RECORD>
<TIMESTAMP>2013-09-17T15:03:47 UTC</TIMESTAMP>
<RECORD_ID>10_2013-09-17T15:03:24</RECORD_ID>
<NAME>Quit</NAME>
<CONNECTION_ID>3</CONNECTION_ID>
<STATUS>0</STATUS>
<STATUS_CODE>0</STATUS_CODE>
<USER></USER>
<OS_LOGIN></OS_LOGIN>
<HOST></HOST>
<IP></IP>
<COMMAND_CLASS>connect</COMMAND_CLASS>
</AUDIT_RECORD>
<AUDIT_RECORD>
<TIMESTAMP>2013-09-17T15:03:49 UTC</TIMESTAMP>
<RECORD_ID>11_2013-09-17T15:03:24</RECORD_ID>
<NAME>NoAudit</NAME>
<SERVER_ID>1</SERVER_ID>
</AUDIT_RECORD>
</AUDIT>
Attributes of <AUDIT_RECORD> elements
have these characteristics:
Some attributes appear in every element, but most are optional and do not necessarily appear in every element.
Order of attributes within an element is not guaranteed.
Attribute values are not fixed length. Long values may be truncated as indicated in the attribute descriptions given later.
The <, >,
", and &
characters are encoded as <,
>, ",
and &, respectively. NUL bytes
(U+00) are encoded as the ? character.
Characters not valid as XML characters are encoded using numeric character references. Valid XML characters are:
#x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
Every <AUDIT_RECORD> element contains
a set of mandatory elements. Other optional elements may
appear, depending on the audit record type.
The following elements are mandatory in every
<AUDIT_RECORD> element:
<NAME>
A string representing the type of instruction that generated the audit event, such as a command that the server received from a client.
Example:
<NAME>Query</NAME>
Some common <NAME> values:
Audit When auditing starts, which may be server startup time Connect When a client connects, also known as logging in Query An SQL statement (executed directly) Prepare Preparation of an SQL statement; usually followed by Execute Execute Execution of an SQL statement; usually follows Prepare Shutdown Server shutdown Quit When a client disconnects NoAudit Auditing has been turned off
The possible values are Audit,
Binlog Dump, Change
user, Close stmt,
Connect Out,
Connect, Create DB,
Daemon, Debug,
Delayed insert, Drop
DB, Execute,
Fetch, Field List,
Init DB, Kill,
Long Data, NoAudit,
Ping, Prepare,
Processlist, Query,
Quit, Refresh,
Register Slave, Reset
stmt, Set option,
Shutdown, Sleep,
Statistics, Table
Dump, Time.
With the exception of Audit and
NoAudit, these values correspond to the
COM_
command values listed in the
xxxmysql_com.h header file. For example,
Create DB and
Shutdown correspond to
COM_CREATE_DB and
COM_SHUTDOWN, respectively.
<RECORD_ID>
A unique identifier for the audit record. The value is
composed from a sequence number and timestamp, in the
format
.
The sequence number is initialized to the size of the
audit log file at the time the audit log plugin opens it
and increments by 1 for each record logged. The timestamp
is a UTC value in
SEQ_TIMESTAMP
format indicating the time when the audit log plugin
opened the file.
yyyy-mm-ddThh:mm:ss
Example:
<RECORD_ID>28743_2013-09-18T21:03:24</RECORD_ID>
<TIMESTAMP>
The date and time that the audit event was generated. For
example, the event corresponding to execution of an SQL
statement received from a client has a
<TIMESTAMP> value occurring after
the statement finishes, not when it is received. The value
has the format
(with yyyy-mm-ddThh:mm:ss
UTCT, no decimals).
The format includes a time zone specifier at the end. The
time zone is always UTC.
Example:
<TIMESTAMP>2013-09-17T15:03:49 UTC</TIMESTAMP>
The following elements are optional in
<AUDIT_RECORD> elements. Many of them
occur only with specific <NAME>
values.
<COMMAND_CLASS>
A string that indicates the type of action performed.
Example:
<COMMAND_CLASS>drop_table</COMMAND_CLASS>
The values come from the
com_status_vars array in the
sql/mysqld.cc file in a MySQL source
distribution. They correspond to the status variables
displayed by this statement:
SHOW STATUS LIKE 'Com%';
<CONNECTION_ID>
An unsigned integer representing the client connection
identifier. This is the same as the
CONNECTION_ID() function
value within the session.
Example:
<CONNECTION_ID>127</CONNECTION_ID>
<DB>
A string representing the default database name. This
element appears only if the
<NAME> value is
Connect or Change
user.
<HOST>
A string representing the client host name. This element
appears only if the <NAME> value
is Connect, Change
user, or Query.
Example:
<HOST>localhost</HOST>
<IP>
A string representing the client IP address. This element
appears only if the <NAME> value
is Connect, Change
user, or Query.
Example:
<IP>127.0.0.1</IP>
<MYSQL_VERSION>
A string representing the MySQL server version. This is
the same as the value of the
VERSION() function or
version system variable.
This element appears only if the
<NAME> value is
Audit.
Example:
<MYSQL_VERSION>5.7.1-m11-log</MYSQL_VERSION>
<OS_LOGIN>
A string representing the external user name used during
the authentication process, as set by the plugin used to
authenticate the client. With native (built-in) MySQL
authentication, or if the plugin does not set the value,
this variable is NULL. The value is the
same as that of the
external_user system
variable. See Section 5.8, “Proxy Users”.
This element appears only if the
<NAME> value is
Connect, Change
user, or Query.
<OS_VERSION>
A string representing the operating system on which the
server was built or is running. This element appears only
if the <NAME> value is
Audit.
Example:
<OS_VERSION>x86_64-Linux</OS_VERSION>
<PRIV_USER>
A string representing the user that the server
authenticated the client as. This is the user name that
the server uses for privilege checking, and may differ
from the <USER> value. This
element appears only if the
<NAME> value is
Connect or Change
user.
<PROXY_USER>
A string representing the proxy user. The value is empty
if user proxying is not in effect. This element appears
only if the <NAME> value is
Connect or Change
user.
<SERVER_ID>
An unsigned integer representing the server ID. This is
the same as the value of the
server_id system
variable. This element appears only if the
<NAME> value is
Audit or NoAudit.
Example:
<SERVER_ID>1</SERVER_ID>
<SQLTEXT>
A string representing the text of an SQL statement. The
value can be empty. Long values may be truncated. This
element appears only if the
<NAME> value is
Query or Execute.
The string, like the audit log file itself, is written using UTF-8 (up to 4 bytes per character), so the value may be the result of conversion. For example, the original statement might have been received from the client as an SJIS string.
Example:
<SQLTEXT>DELETE FROM t1</SQLTEXT>
<STARTUP_OPTIONS>
A string representing the options that were given on the
command line or in option files when the MySQL server was
started. This element appears only if the
<NAME> value is
Audit.
Example:
<STARTUP_OPTIONS>/usr/local/mysql/bin/mysqld --port=3306 --log-output=FILE</STARTUP_OPTIONS>
<STATUS>
An unsigned integer representing the command status: 0 for
success, nonzero if an error occurred. This is the same as
the value of the
mysql_errno() C API
function.
The audit log does not contain the SQLSTATE value or error message. To see the associations between error codes, SQLSTATE values, and messages, see Server Error Codes and Messages.
Warnings are not logged.
See the description for
<STATUS_CODE> for information
about how it differs from
<STATUS>.
Example:
<STATUS>1051</STATUS>
<STATUS_CODE>
An unsigned integer representing the command status: 0 for success, 1 if an error occurred.
The STATUS_CODE value differs from the
STATUS value:
STATUS_CODE is 0 for success and 1 for
error, which is compatible with the EZ_collector consumer
for Audit Vault. STATUS is the value of
the mysql_errno() C API
function. This is 0 for success and nonzero for error, and
thus is not necessarily 1 for error.
Example:
<STATUS_CODE>0</STATUS_CODE>
<USER>
A string representing the user name sent by the client.
This may differ from the
<PRIV_USER> value. This element
appears only if the <NAME> value
is Connect, Change
user, or Query.
Example:
<USER>root[root] @ localhost [127.0.0.1]</USER>
<VERSION>
An unsigned integer representing the version of the audit
log file format. This element appears only if the
<NAME> value is
Audit.
Example:
<VERSION>1</VERSION>
Every <AUDIT_RECORD> element contains
a set of mandatory attributes. Other optional attributes may
appear depending on the audit record type.
The following attributes are mandatory in every
<AUDIT_RECORD> element:
NAME
A string representing the type of instruction that generated the audit event, such as a command that the server received from a client.
Example: NAME="Query"
Some common NAME values:
"Audit" When auditing starts, which may be server startup time "Connect" When a client connects, also known as logging in "Query" An SQL statement (executed directly) "Prepare" Preparation of an SQL statement; usually followed by Execute "Execute" Execution of an SQL statement; usually follows Prepare "Shutdown" Server shutdown "Quit" When a client disconnects "NoAudit" Auditing has been turned off
The possible values are "Audit",
"Binlog Dump", "Change
user", "Close stmt",
"Connect Out",
"Connect", "Create
DB", "Daemon",
"Debug", "Delayed
insert", "Drop DB",
"Execute", "Fetch",
"Field List", "Init
DB", "Kill", "Long
Data", "NoAudit",
"Ping", "Prepare",
"Processlist",
"Query", "Quit",
"Refresh", "Register
Slave", "Reset stmt",
"Set option",
"Shutdown", "Sleep",
"Statistics", "Table
Dump", "Time".
With the exception of "Audit" and
"NoAudit", these values correspond to
the COM_
command values listed in the
xxxmysql_com.h header file. For example,
"Create DB" and
"Shutdown" correspond to
COM_CREATE_DB and
COM_SHUTDOWN, respectively.
TIMESTAMP
The date and time that the audit event was generated. For
example, the event corresponding to execution of an SQL
statement received from a client has a
TIMESTAMP value occurring after the
statement finishes, not when it is received. The value is
UTC, in the format
(with yyyy-mm-ddThh:mm:ssT, no decimals).
Example:
TIMESTAMP="2012-08-09T12:55:16"
The following attributes are optional in
<AUDIT_RECORD> elements. Many of them
occur only for elements with specific values of the
NAME attribute.
CONNECTION_ID
An unsigned integer representing the client connection
identifier. This is the same as the
CONNECTION_ID() function
value within the session.
Example: CONNECTION_ID="127"
DB
A string representing the default database name. This
attribute appears only if the NAME
value is "Connect" or "Change
user".
HOST
A string representing the client host name. This attribute
appears only if the NAME value is
"Connect" or "Change
user".
Example: HOST="localhost"
IP
A string representing the client IP address. This
attribute appears only if the NAME
value is "Connect" or "Change
user".
Example: IP="127.0.0.1"
MYSQL_VERSION
A string representing the MySQL server version. This is
the same as the value of the
VERSION() function or
version system variable.
This attribute appears only if the NAME
value is "Audit".
Example: MYSQL_VERSION="5.6.11-log"
OS_LOGIN
A string representing the external user (empty if none).
The value may differ from USER, for
example, if the server authenticates the client using an
external authentication method. This attribute appears
only if the NAME value is
"Connect" or "Change
user".
OS_VERSION
A string representing the operating system on which the
server was built or is running. This attribute appears
only if the NAME value is
"Audit".
Example: OS_VERSION="x86_64-Linux"
PRIV_USER
A string representing the user that the server
authenticated the client as. This is the user name that
the server uses for privilege checking, and may be
different from the USER value. This
attribute appears only if the NAME
value is "Connect" or "Change
user".
PROXY_USER
A string representing the proxy user. The value is empty
if user proxying is not in effect. This attribute appears
only if the NAME value is
"Connect" or "Change
user".
SERVER_ID
An unsigned integer representing the server ID. This is
the same as the value of the
server_id system
variable. This attribute appears only if the
NAME value is
"Audit" or
"NoAudit".
Example: SERVER_ID="1"
SQLTEXT
A string representing the text of an SQL statement. The
value can be empty. Long values may be truncated. This
attribute appears only if the NAME
value is "Query" or
"Execute".
The string, like the audit log file itself, is written using UTF-8 (up to 4 bytes per character), so the value may be the result of conversion. For example, the original statement might have been received from the client as an SJIS string.
Example: SQLTEXT="DELETE FROM t1"
STARTUP_OPTIONS
A string representing the options that were given on the
command line or in option files when the MySQL server was
started. This attribute appears only if the
NAME value is
"Audit".
Example: STARTUP_OPTIONS="--port=3306
--log-output=FILE"
STATUS
An unsigned integer representing the command status: 0 for
success, nonzero if an error occurred. This is the same as
the value of the
mysql_errno() C API
function.
The audit log does not contain the SQLSTATE value or error message. To see the associations between error codes, SQLSTATE values, and messages, see Server Error Codes and Messages.
Warnings are not logged.
Example: STATUS="1051"
USER
A string representing the user name sent by the client.
This may be different from the
PRIV_USER value. This attribute appears
only if the NAME value is
"Connect" or "Change
user".
VERSION
An unsigned integer representing the version of the audit
log file format. This attribute appears only if the
NAME value is
"Audit".
Example: VERSION="1"
This section describes how the audit_log
plugin performs logging and the system variables that control
how logging occurs. It assumes familiarity with the log file
format described in Section 7.3.3, “The Audit Log File”.
The audit_log plugin can also control whether
audited events are written to the audit log file based on the
account from which events originate or event status. See
Section 7.3.5, “Audit Log Filtering”.
When the audit log plugin opens its log file, it checks whether
the XML declaration and opening <AUDIT>
root element tag must be written and writes them if so. When the
audit log plugin terminates, it writes a closing
</AUDIT> tag to the file.
If the log file exists at open time, the plugin checks whether
the file ends with an </AUDIT> tag and
truncates it if so before writing any
<AUDIT_RECORD> elements. If the log
file exists but does not end with
</AUDIT> or the
</AUDIT> tag cannot be truncated, the
plugin considers the file malformed and fails to initialize.
This can occur if the server crashes or is killed with the audit
log plugin running. No logging occurs until the problem is
rectified. Check the error log for diagnostic information:
[ERROR] Plugin 'audit_log' init function returned error.
To deal with this problem, either remove or rename the malformed log file and restart the server.
The MySQL server calls the audit log plugin to write an
<AUDIT_RECORD> element whenever an
auditable event occurs, such as when it completes execution of
an SQL statement received from a client. Typically the first
<AUDIT_RECORD> element written after
server startup has the server description and startup options.
Elements following that one represent events such as client
connect and disconnect events, executed SQL statements, and so
forth. Only top-level statements are logged, not statements
within stored programs such as triggers or stored procedures.
Contents of files referenced by statements such as
LOAD DATA
INFILE are not logged.
To permit control over how logging occurs, the
audit_log plugin provides several system
variables, described following. For more information, see
Section 7.3.6.2, “Audit Log Options and System Variables”.
To control the audit log file name, set the
audit_log_file system
variable at server startup. By default, the name is
audit.log in the server data directory.
For security reasons, the audit log file should be written to
a directory accessible only to the MySQL server and users with
a legitimate reason to view the log.
The audit log plugin can use any of several strategies for log
writes. To specify a strategy, set the
audit_log_strategy system
variable at server startup. By default, the strategy value is
ASYNCHRONOUS and the plugin logs
asynchronously to a buffer, waiting if the buffer is full.
It's possible to tell the plugin not to wait
(PERFORMANCE) or to log synchronously,
either using file system caching
(SEMISYNCHRONOUS) or forcing output with a
sync() call after each write request
(SYNCHRONOUS).
Asynchronous logging strategy has these characteristics:
Minimal impact on server performance and scalability.
Blocking of threads that generate audit events for the shortest possible time; that is, time to allocate the buffer plus time to copy the event to the buffer.
Output goes to the buffer. A separate thread handles writes from the buffer to the log file.
A disadvantage of PERFORMANCE strategy is
that it drops events when the buffer is full. For a heavily
loaded server, it is more likely that the audit log will be
missing events.
With asynchronous logging, the integrity of the log file may
be compromised if a problem occurs during a write to the file
or if the plugin does not shut down cleanly (for example, in
the event that the server host crashes). To reduce this risk,
set audit_log_strategy to use
synchronous logging. Regardless of strategy, logging occurs on
a best-effort basis, with no guarantee of consistency.
If the file system to which the audit log is being written fills up, a “disk full” error is written to the error log. Audit logging continues until the audit log buffer is full. If free disk space has not been made available by the time the buffer fills, client sessions will hang, and stopping the server at the time of client sessions hanging will result in audit log corruption. To avoid this if client sessions are hung, ensure that free space is available on the audit logging file system before stopping the server.
The audit log plugin provides several system variables that enable you to manage the space used by its log files:
audit_log_buffer_size:
Set this variable at server startup to set the size of the
buffer for asynchronous logging. The plugin uses a single
buffer, which it allocates when it initializes and removes
when it terminates. The plugin allocates this buffer only
if logging is asynchronous.
audit_log_rotate_on_size,
audit_log_flush: These
variables permit audit log file rotation and flushing. The
audit log file has the potential to grow very large and
consume a lot of disk space. To manage the space used,
either enable automatic log rotation, or manually rename
the audit file and flush the log to open a new file. The
renamed file can be removed or backed up as desired.
By default,
audit_log_rotate_on_size=0
and there is no log rotation. In this case, the audit log
plugin closes and reopens the log file when the
audit_log_flush value
changes from disabled to enabled. Log file renaming must
be done externally to the server. Suppose that you want to
maintain the three most recent log files, which cycle
through the names audit.log.1 through
audit.log.3. On Unix, perform
rotation manually like this:
From the command line, rename the current log files:
mv audit.log.2 audit.log.3 mv audit.log.1 audit.log.2 mv audit.log audit.log.1
At this point, the plugin is still writing to the
current log file, which has been renamed to
audit.log.1.
Connect to the server and flush the log file so the
plugin closes it and reopens a new
audit.log file:
SET GLOBAL audit_log_flush = ON;
If
audit_log_rotate_on_size
is greater than 0, setting
audit_log_flush has no
effect. In this case, the audit log plugin closes and
reopens its log file whenever a write to the file causes
its size to exceed the
audit_log_rotate_on_size
value. The plugin renames the original file to have a
timestamp extension. For example,
audit.log might be renamed to
audit.log.13440033615657730. The last
7 digits are a fractional second part. The first 10 digits
are a Unix timestamp value that can be interpreted using
the FROM_UNIXTIME()
function:
mysql> SELECT FROM_UNIXTIME(1344003361);
+---------------------------+
| FROM_UNIXTIME(1344003361) |
+---------------------------+
| 2012-08-03 09:16:01 |
+---------------------------+
The audit_log plugin can filter audited
events. This enables you to control whether audited events are
written to the audit log file based on the account from which
events originate or event status. Status filtering occurs
separately for connection events and statement events.
As of MySQL 5.6.20, to filter audited events based on the originating account, set one of these system variables at server startup or runtime:
audit_log_include_accounts:
The accounts to include in audit logging. If this variable
is set, only these accounts are audited.
audit_log_exclude_accounts:
The accounts to exclude from audit logging. If this
variable is set, all but these accounts are audited.
The value for either variable can be NULL
or a string containing one or more comma-separated account
names, each in
format. By default, both variables are
user_name@host_nameNULL, in which case, no account filtering
is done and auditing occurs for all accounts.
Modifications to
audit_log_include_accounts or
audit_log_exclude_accounts
affect only connections created subsequent to the
modification, not existing connections.
Example: To enable audit logging only for the
user1 and user2 local
host account accounts, set the
audit_log_include_accounts
system variable like this:
SET GLOBAL audit_log_include_accounts = 'user1@localhost,user2@localhost';
Only one of
audit_log_include_accounts or
audit_log_exclude_accounts
can be non-NULL at a time:
If you set
audit_log_include_accounts,
the server sets
audit_log_exclude_accounts
to NULL.
If you attempt to set
audit_log_exclude_accounts,
an error occurs unless
audit_log_include_accounts
is NULL. In this case, you must first
clear
audit_log_include_accounts
by setting it to NULL.
-- This sets audit_log_exclude_accounts to NULL SET GLOBAL audit_log_include_accounts =value; -- This fails because audit_log_include_accounts is not NULL SET GLOBAL audit_log_exclude_accounts =value; -- To set audit_log_exclude_accounts, first set -- audit_log_include_accounts to NULL SET GLOBAL audit_log_include_accounts = NULL; SET GLOBAL audit_log_exclude_accounts =value;
If you inspect the value of either variable, be aware that
SHOW VARIABLES displays
NULL as an empty string. To avoid this, use
SELECT instead:
mysql>SHOW VARIABLES LIKE 'audit_log_include_accounts';+----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | audit_log_include_accounts | | +----------------------------+-------+ mysql>SELECT @@audit_log_include_accounts;+------------------------------+ | @@audit_log_include_accounts | +------------------------------+ | NULL | +------------------------------+
If a user name or host name requires quoting because it
contains a comma, space, or other special character, quote it
using single quotes. If the variable value itself is quoted
with single quotes, double each inner single quote or escape
it with a backslash. The following statements each enable
audit logging for the local root account
and are equivalent, even though the quoting styles differ:
SET GLOBAL audit_log_include_accounts = 'root@localhost'; SET GLOBAL audit_log_include_accounts = '''root''@''localhost'''; SET GLOBAL audit_log_include_accounts = '\'root\'@\'localhost\''; SET GLOBAL audit_log_include_accounts = "'root'@'localhost'";
The last statement will not work if the
ANSI_QUOTES SQL mode is enabled because in
that mode double quotes signify identifier quoting, not string
quoting.
As of MySQL 5.6.20, to filter audited events based on status, set these system variables at server startup or runtime:
audit_log_connection_policy:
Logging policy for connection events
audit_log_statement_policy:
Logging policy for statement events
Each variable takes a value of ALL (log all
associated events; this is the default),
ERRORS (log only failed events), or
NONE (do not log events). For example, to
log all statement events but only failed connection events,
use these settings:
SET GLOBAL audit_log_statement_policy = ALL; SET GLOBAL audit_log_connection_policy = ERRORS;
Before MySQL 5.6.20,
audit_log_connection_policy
and
audit_log_statement_policy
are not available. Instead, use
audit_log_policy at server
startup or runtime. It takes a value of ALL
(log all events; this is the default),
LOGINS (log connection events),
QUERIES (log statement events), or
NONE (do not log events). For any of those
values, the audit log plugin logs all selected events without
distinction as to success or failure.
As of MySQL 5.6.20,
audit_log_policy is still
available but can be set only at server startup. At runtime,
it is a read-only variable. Its use at startup works as
follows:
If you do not set
audit_log_policy or set
it to its default of ALL, any explicit
settings for
audit_log_connection_policy
or
audit_log_statement_policy
apply as specified. If not specified, they default to
ALL.
If you set
audit_log_policy to a
non-ALL value, that value takes
precedence over and is used to set
audit_log_connection_policy
and
audit_log_statement_policy,
as indicated in the following table. If you also set
either of those variables to a value other than their
default of ALL, the server writes a
message to the error log to indicate that their values are
being overridden.
| Startup audit_log_policy Value | Resulting audit_log_connection_policy Value | Resulting audit_log_statement_policy Value |
|---|---|---|
LOGINS | ALL | NONE |
QUERIES | NONE | ALL |
NONE | NONE | NONE |
To check the effect of filtering, you can inspect the values of these status variables:
Audit_log_events: The number of events
handled by the audit log plugin, whether or not they were
written to the log based on filtering policy.
Audit_log_events_filtered: The number
of events handled by the audit log plugin that were
filtered (not written to the log) based on filtering
policy.
Audit_log_events_written: The number of
events written to the audit log.
These variables are available as of MySQL 5.6.20.
The following discussion serves as a reference to these MySQL Enterprise Audit components:
Audit log system variables
Audit log status variables
Table 7.9 Audit Log Option/Variable Reference
| Name | Cmd-Line | Option File | System Var | Status Var | Var Scope | Dynamic |
|---|---|---|---|---|---|---|
| audit-log | Yes | Yes | ||||
| audit_log_buffer_size | Yes | Yes | Yes | Global | No | |
| audit_log_connection_policy | Yes | Yes | Yes | Global | Yes | |
| audit_log_current_session | Yes | Both | No | |||
| Audit_log_current_size | Yes | Global | No | |||
| Audit_log_event_max_drop_size | Yes | Global | No | |||
| Audit_log_events | Yes | Global | No | |||
| Audit_log_events_filtered | Yes | Global | No | |||
| Audit_log_events_lost | Yes | Global | No | |||
| Audit_log_events_written | Yes | Global | No | |||
| audit_log_exclude_accounts | Yes | Yes | Yes | Global | Yes | |
| audit_log_file | Yes | Yes | Yes | Global | No | |
| audit_log_flush | Yes | Global | Yes | |||
| audit_log_format | Yes | Yes | Yes | Global | No | |
| audit_log_include_accounts | Yes | Yes | Yes | Global | Yes | |
| audit_log_policy | Yes | Yes | Yes | Global | Varies | |
| audit_log_rotate_on_size | Yes | Yes | Yes | Global | Yes | |
| audit_log_statement_policy | Yes | Yes | Yes | Global | Yes | |
| audit_log_strategy | Yes | Yes | Yes | Global | No | |
| Audit_log_total_size | Yes | Global | No | |||
| Audit_log_write_waits | Yes | Global | No |
This section describes the command options and system
variables that control operation of MySQL Enterprise Audit. If values
specified at startup time are incorrect, the
audit_log plugin may fail to initialize
properly and the server does not load it. In this case, the
server may also produce error messages for other audit log
settings because it will not recognize them.
To control the activation of the audit_log
plugin, use this option:
| Introduced | 5.6.10 | ||
| Command-Line Format | --audit-log[=value] | ||
| Permitted Values | Type | enumeration | |
| Default | ON | ||
| Valid Values | ON | ||
OFF | |||
FORCE | |||
FORCE_PLUS_PERMANENT | |||
This option controls how the server loads the
audit_log plugin at startup. It is
available only if the plugin has been previously
registered with INSTALL
PLUGIN or is loaded with
--plugin-load. See
Section 7.3.1, “Installing MySQL Enterprise Audit”.
The option value should be one of those available for
plugin-loading options, as described in
Installing and Uninstalling Plugins. For example,
--audit-log=FORCE_PLUS_PERMANENT
tells the server to load the plugin at startup and
prevents it from being removed while the server is
running.
If the audit_log plugin is enabled, it
exposes several system variables that permit control over
logging:
mysql> SHOW VARIABLES LIKE 'audit_log%';
+-----------------------------+--------------+
| Variable_name | Value |
+-----------------------------+--------------+
| audit_log_buffer_size | 1048576 |
| audit_log_connection_policy | ALL |
| audit_log_current_session | ON |
| audit_log_exclude_accounts | |
| audit_log_file | audit.log |
| audit_log_flush | OFF |
| audit_log_format | OLD |
| audit_log_include_accounts | |
| audit_log_policy | ALL |
| audit_log_rotate_on_size | 0 |
| audit_log_statement_policy | ALL |
| audit_log_strategy | ASYNCHRONOUS |
+-----------------------------+--------------+
You can set any of these variables at server startup, and some of them at runtime.
| Introduced | 5.6.10 | ||
| Command-Line Format | --audit_log_buffer_size=value | ||
| System Variable | Name | audit_log_buffer_size | |
| Variable Scope | Global | ||
| Dynamic Variable | No | ||
| Permitted Values (32-bit platforms) | Type | integer | |
| Default | 1048576 | ||
| Min Value | 4096 | ||
| Max Value | 4294967295 | ||
| Permitted Values (64-bit platforms) | Type | integer | |
| Default | 1048576 | ||
| Min Value | 4096 | ||
| Max Value | 18446744073709547520 | ||
When the audit log plugin writes events to the log asynchronously, it uses a buffer to store event contents prior to writing them. This variable controls the size of that buffer, in bytes. The server adjusts the value to a multiple of 4096. The plugin uses a single buffer, which it allocates when it initializes and removes when it terminates. The plugin allocates this buffer only if logging is asynchronous.
| Introduced | 5.6.20 | ||
| Command-Line Format | --audit_log_connection_policy=value | ||
| System Variable | Name | audit_log_connection_policy | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | enumeration | |
| Default | ALL | ||
| Valid Values | ALL | ||
ERRORS | |||
NONE | |||
The policy controlling how the audit log plugin writes connection events to its log file. The following table shows the permitted values.
| Value | Description |
|---|---|
ALL | Log all connection events |
ERRORS | Log only failed connection events |
NONE | Do not log connection events |
At server startup, any explicit value given for
audit_log_connection_policy
may be overridden if
audit_log_policy is
also specified, as described in
Section 7.3.4, “Audit Log Logging Control”.
| Introduced | 5.6.20 | ||
| System Variable | Name | audit_log_current_session | |
| Variable Scope | Global, Session | ||
| Dynamic Variable | No | ||
| Permitted Values | Type | boolean | |
| Default | depends on filtering policy | ||
Whether audit logging is enabled for the current session.
The session value of this variable is read only. It is set
when the session begins based on the values of the
audit_log_include_accounts
and
audit_log_exclude_accounts
system variables. The audit log plugin uses the session
value to determine whether to audit events for the
session. (There is a global value, but the plugin does not
use it.)
| Introduced | 5.6.20 | ||
| Command-Line Format | --audit_log_exclude_accounts=value | ||
| System Variable | Name | audit_log_exclude_accounts | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | string | |
| Default | NULL | ||
The accounts for which events should not be logged. The
value should be NULL or a string
containing a list of one or more comma-separated account
names. For more information, see
Section 7.3.4, “Audit Log Logging Control”.
Modifications to
audit_log_exclude_accounts
affect only connections created subsequent to the
modification, not existing connections.
| Introduced | 5.6.10 | ||
| Command-Line Format | --audit_log_file=file_name | ||
| System Variable | Name | audit_log_file | |
| Variable Scope | Global | ||
| Dynamic Variable | No | ||
| Permitted Values | Type | file name | |
| Default | audit.log | ||
The name of the file to which the audit log plugin writes
events. The default value is
audit.log. If the value of
audit_log_file is a
relative path name, the server interprets it relative to
the data directory. If the value is a full path name, the
server uses the value as is. A full path name may be
useful if it is desirable to locate audit files on a
separate file system or directory. For security reasons,
the audit log file should be written to a directory
accessible only to the MySQL server and users with a
legitimate reason to view the log. For more information,
see Section 7.3.4, “Audit Log Logging Control”.
| Introduced | 5.6.10 | ||
| System Variable | Name | audit_log_flush | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | boolean | |
| Default | OFF | ||
When this variable is set to enabled (1 or
ON), the audit log plugin closes and
reopens its log file to flush it. (The value remains
OFF so that you need not disable it
explicitly before enabling it again to perform another
flush.) Enabling this variable has no effect unless
audit_log_rotate_on_size
is 0. For more information, see
Section 7.3.4, “Audit Log Logging Control”.
| Introduced | 5.6.14 | ||
| Command-Line Format | --audit_log_format=value | ||
| System Variable | Name | audit_log_format | |
| Variable Scope | Global | ||
| Dynamic Variable | No | ||
| Permitted Values (>= 5.6.14) | Type | enumeration | |
| Default | OLD | ||
| Valid Values | OLD | ||
NEW | |||
The audit log file format. Permitted values are
OLD and NEW (default
OLD). For details about each format,
see Section 7.3.3, “The Audit Log File”.
If you change the value of
audit_log_format, use
this procedure to avoid writing log entries in one format
to an existing log file that contains entries in a
different format:
Stop the server.
Rename the current audit log file manually.
Restart the server with the new value of
audit_log_format. The
audit log plugin will create a new log file, which
will contain log entries in the selected format.
| Introduced | 5.6.20 | ||
| Command-Line Format | --audit_log_include_accounts=value | ||
| System Variable | Name | audit_log_include_accounts | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | string | |
| Default | NULL | ||
The accounts for which events should be logged. The value
should be NULL or a string containing a
list of one or more comma-separated account names. For
more information, see
Section 7.3.4, “Audit Log Logging Control”.
Modifications to
audit_log_include_accounts
affect only connections created subsequent to the
modification, not existing connections.
| Introduced | 5.6.10 | ||
| Command-Line Format | --audit_log_policy=value | ||
| System Variable (<= 5.6.19) | Name | audit_log_policy | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| System Variable (>= 5.6.20) | Name | audit_log_policy | |
| Variable Scope | Global | ||
| Dynamic Variable | No | ||
| Permitted Values | Type | enumeration | |
| Default | ALL | ||
| Valid Values | ALL | ||
LOGINS | |||
QUERIES | |||
NONE | |||
The policy controlling how the audit log plugin writes events to its log file. The following table shows the permitted values.
| Value | Description |
|---|---|
ALL | Log all events |
LOGINS | Log only login events |
QUERIES | Log only query events |
NONE | Log nothing (disable the audit stream) |
As of MySQL 5.6.20,
audit_log_policy can be
set only at server startup. At runtime, it is a read-only
variable. This is due to the introduction of two other
system variables,
audit_log_connection_policy
and
audit_log_statement_policy,
that provide finer control over logging policy and that
can be set either at startup or at runtime. If you
continue to use
audit_log_policy at
startup instead of the other two variables, the server
uses its value to set those variables. For more
information about the policy variables and their
interaction, see
Section 7.3.4, “Audit Log Logging Control”.
Before MySQL 5.6.20, the
audit_log_connection_policy
and
audit_log_statement_policy
system variables do not exist.
audit_log_policy is the
only policy control variable and it can be set at server
startup or runtime.
| Introduced | 5.6.10 | ||
| Command-Line Format | --audit_log_rotate_on_size=N | ||
| System Variable | Name | audit_log_rotate_on_size | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | integer | |
| Default | 0 | ||
If the
audit_log_rotate_on_size
value is greater than 0, the audit log plugin closes and
reopens its log file if a write to the file causes its
size to exceed this value. The original file is renamed to
have a timestamp extension.
If the
audit_log_rotate_on_size
value is 0, the plugin does not close and reopen its log
based on size. Instead, use
audit_log_flush to close
and reopen the log on demand. In this case, rename the
file externally to the server before flushing it.
For more information about audit log file rotation and timestamp interpretation, see Section 7.3.4, “Audit Log Logging Control”.
If you set this variable to a value that is not a multiple of 4096, it is truncated to the nearest multiple. (Thus, setting it to a value less than 4096 has the effect of setting it to 0 and no rotation occurs.)
| Introduced | 5.6.20 | ||
| Command-Line Format | --audit_log_statement_policy=value | ||
| System Variable | Name | audit_log_statement_policy | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | enumeration | |
| Default | ALL | ||
| Valid Values | ALL | ||
ERRORS | |||
NONE | |||
The policy controlling how the audit log plugin writes statement events to its log file. The following table shows the permitted values.
| Value | Description |
|---|---|
ALL | Log all statement events |
ERRORS | Log only failed statement events |
NONE | Do not log statement events |
At server startup, any explicit value given for
audit_log_statement_policy
may be overridden if
audit_log_policy is
also specified, as described in
Section 7.3.4, “Audit Log Logging Control”.
| Introduced | 5.6.10 | ||
| Command-Line Format | --audit_log_strategy=value | ||
| System Variable | Name | audit_log_strategy | |
| Variable Scope | Global | ||
| Dynamic Variable | No | ||
| Permitted Values | Type | enumeration | |
| Default | ASYNCHRONOUS | ||
| Valid Values | ASYNCHRONOUS | ||
PERFORMANCE | |||
SEMISYNCHRONOUS | |||
SYNCHRONOUS | |||
The logging method used by the audit log plugin. The following table describes the permitted values.
Table 7.10 Audit Log Strategies
| Value | Meaning |
|---|---|
ASYNCHRONOUS | Log asynchronously, wait for space in output buffer |
PERFORMANCE | Log asynchronously, drop request if insufficient space in output buffer |
SEMISYNCHRONOUS | Log synchronously, permit caching by operating system |
SYNCHRONOUS | Log synchronously, call sync() after each request |
If the audit_log plugin is enabled, it
exposes several status variables that provide operational
information.
The size of the current audit log file. The value increases when an event is written to the log and is reset to 0 when the log is rotated.
The size of the largest dropped event in performance logging mode. For a description of logging modes, see Section 7.3.4, “Audit Log Logging Control”.
The number of events handled by the audit log plugin, whether or not they were written to the log based on filtering policy (see Section 7.3.4, “Audit Log Logging Control”).
The number of events handled by the audit log plugin that were filtered (not written to the log) based on filtering policy (see Section 7.3.4, “Audit Log Logging Control”).
The number of events lost in performance logging mode
because an event was larger than than the available audit
log buffer space. This value may be useful for assessing
how to set
audit_log_buffer_size to
size the buffer for performance mode. For a description of
logging modes, see
Section 7.3.4, “Audit Log Logging Control”.
The number of events written to the audit log.
The total size of events written to all audit log files.
Unlike
Audit_log_current_size,
the value of
Audit_log_total_size
increases even when the log is rotated.
The number of times an event had to wait for space in the audit log buffer in asynchronous logging mode. For a description of logging modes, see Section 7.3.4, “Audit Log Logging Control”.
MySQL Enterprise Audit is subject to these general restrictions:
Only SQL statements are logged. Changes made by no-SQL APIs, such as memcached, Node.JS, and the NDB API, are not logged.
Only top-level statements are logged, not statements within stored programs such as triggers or stored procedures.
Contents of files referenced by statements such as
LOAD DATA
INFILE are not logged.
MySQL Cluster. It is possible to use MySQL Enterprise Audit with MySQL Cluster, subject to the following conditions:
All changes to be logged must be done using the SQL interface. Changes using no-SQL interfaces, such as those provided by the NDB API, memcached, or ClusterJ, are not logged.
The plugin must be installed on each MySQL server that is used to execute SQL on the cluster.
Audit plugin data must be aggregated amongst all MySQL servers used with the cluster. This aggregation is the responsibility of the application or user.
MySQL Enterprise Firewall is an extension included in MySQL Enterprise Edition, a commercial product. To learn more about commercial products, see http://www.mysql.com/products/.
As of MySQL 5.6.24, MySQL Enterprise Edition includes MySQL Enterprise Firewall, an application-level firewall that enables database administrators to permit or deny SQL statement execution based on matching against whitelists of accepted statement patterns. This helps harden MySQL Server against attacks such as SQL injection or attempts to exploit applications by using them outside of their legitimate query workload characteristics.
Each MySQL account registered with the firewall has its own statement whitelist, enabling protection to be tailored per account. For a given account, the firewall can operate in recording, protecting, or detecting mode, for training in the accepted statement patterns, active protection against unacceptable statements, or passive detection of unacceptable statements. The diagram illustrates how the firewall processes incoming statements in each mode.
The following sections describe the components of MySQL Enterprise Firewall, discuss how to install and use it, and provide reference information for its components.
MySQL Enterprise Firewall is based on a plugin library that implements these components:
A server-side plugin named MYSQL_FIREWALL
examines SQL statements before they execute and, based on
its in-memory cache, renders a decision whether to execute
or reject each statement.
Server-side plugins named
MYSQL_FIREWALL_USERS and
MYSQL_FIREWALL_WHITELIST implement
INFORMATION_SCHEMA tables that provide
views into the firewall data cache.
System tables named firewall_users and
firewall_whitelist in the
mysql database provide persistent storage
of firewall data.
Stored procedures named
sp_set_firewall_mode() and
sp_reload_firewall_rules() perform tasks
such as registering MySQL accounts with the firewall,
establishing their operational mode, and managing transfer
of firewall data between the cache and the underlying system
tables.
A set of user-defined functions provides an SQL-level API for lower-level tasks such as synchronizing the cache with the underlying system tables.
System variables enable firewall configuration and status variables provide runtime operational information.
MySQL Enterprise Firewall installation is a one-time operation that installs the components described in Section 7.4.1, “MySQL Enterprise Firewall Components”. Installation can be performed using a graphical interface or manually:
On Windows, MySQL Installer includes an option to enable MySQL Enterprise Firewall for you.
MySQL Workbench 6.3.4 or higher can install MySQL Enterprise Firewall, enable or disable an installed firewall, or uninstall the firewall.
Manual MySQL Enterprise Firewall installation involves running a script located
in the share directory of your MySQL
installation.
If installed, MySQL Enterprise Firewall involves some minimal overhead even when disabled. To avoid this overhead, do not install the firewall unless you plan to use it.
MySQL Enterprise Firewall does not work together with the query cache. If the query cache is enabled, disable it before installing the firewall (see Query Cache Configuration).
For usage instructions, see Section 7.4.3, “Using MySQL Enterprise Firewall”. For reference information, see Section 7.4.4, “MySQL Enterprise Firewall Reference”.
If MySQL Enterprise Firewall is already installed from an older version of MySQL, uninstall it using the instructions given later in this section and restart your server before installing the current version. In this case, it is also necessary to register your configuration again.
On Windows, you can use MySQL Installer to install MySQL Enterprise Firewall, as shown in Figure 7.2, “MySQL Enterprise Firewall Installation on Windows”. Check the Enable Enterprise Firewall checkbox. (Open Firewall port for network access has a different purpose. It refers to Windows Firewall and controls whether Windows blocks the TCP/IP port on which the MySQL server listens for client connections.)
To install MySQL Enterprise Firewall using MySQL Workbench 6.3.4 or higher, see MySQL Enterprise Firewall Interface.
To install MySQL Enterprise Firewall manually, look in the
share directory of your MySQL
installation and choose the script that is appropriate for
your platform. The available scripts differ in the suffix used
to refer to the plugin library file:
win_install_firewall.sql: Choose this
script for Windows systems that use
.dll as the file name suffix.
linux_install_firewall.sql: Choose
this script for Linux and similar systems that use
.so as the file name suffix.
The installation script creates stored procedures in the
default database, so choose a database to use. Then run the
script as follows, naming the chosen database on the command
line. The example here uses the mysql
database and the Linux installation script. Make the
appropriate substitutions for your system.
shell>mysql -u root -p mysql < linux_install_firewall.sqlEnter password:(enter root password here)
Installing MySQL Enterprise Firewall either using a graphical interface or manually should enable the firewall. To verify that, connect to the server and execute this statement:
mysql> SHOW GLOBAL VARIABLES LIKE 'mysql_firewall_mode';
+---------------------+-------+
| Variable_name | Value |
+---------------------+-------+
| mysql_firewall_mode | ON |
+---------------------+-------+
MySQL Enterprise Firewall can be uninstalled using MySQL Workbench or manually.
To uninstall MySQL Enterprise Firewall using MySQL Workbench 6.3.4 or higher, see MySQL Enterprise Firewall Interface.
To uninstall MySQL Enterprise Firewall manually, execute the following
statements. It is assumed that the stored procedures were
created in the mysql database. Adjust the
DROP PROCEDURE statements
appropriately if the procedures were created in a different
database.
DROP TABLE mysql.firewall_whitelist; DROP TABLE mysql.firewall_users; UNINSTALL PLUGIN mysql_firewall; UNINSTALL PLUGIN mysql_firewall_whitelist; UNINSTALL PLUGIN mysql_firewall_users; DROP FUNCTION set_firewall_mode; DROP FUNCTION normalize_statement; DROP FUNCTION read_firewall_whitelist; DROP FUNCTION read_firewall_users; DROP FUNCTION mysql_firewall_flush_status; # MySQL 5.6.26 and up only DROP PROCEDURE mysql.sp_set_firewall_mode; DROP PROCEDURE mysql.sp_reload_firewall_rules; # MySQL 5.6.26 and up only
Before using MySQL Enterprise Firewall, install it according to the instructions provided at Section 7.4.2, “Installing or Uninstalling MySQL Enterprise Firewall”. Also, MySQL Enterprise Firewall does not work together with the query cache; disable the query cache if it is enabled (see Query Cache Configuration).
This section describes how to configure MySQL Enterprise Firewall using SQL statements. Alternatively, MySQL Workbench 6.3.4 or higher provides a graphical interface for firewall control. See MySQL Enterprise Firewall Interface.
To enable or disable the firewall, set the
mysql_firewall_mode system
variable. By default, this variable is enabled when the firewall
is installed. To control the initial firewall state explicitly,
you can set the variable at server startup. For example, to
enable the firewall in an option file, use these lines:
[mysqld] mysql_firewall_mode=ON
It is also possible to disable or enable the firewall at runtime:
mysql>SET GLOBAL mysql_firewall_mode = OFF;mysql>SET GLOBAL mysql_firewall_mode = ON;
In addition to the global on/off firewall mode, each account registered with the firewall has its own operational mode. For an account in recording mode, the firewall learns an application's “fingerprint,” that is, the acceptable statement patterns that, taken together, form a whitelist. After training, switch the firewall to protecting mode to harden MySQL against access by statements that deviate from the fingerprint. For additional training, switch the firewall back to recording mode as necessary to update the whitelist with new statement patterns. As of MySQL 5.6.26, an intrusion-detection mode is available that writes suspicious statements to the error log but does not deny access.
The firewall maintains whitelist rules on a per-account basis, enabling implementation of protection strategies such as these:
For an application that has unique protection requirements, configure it to use an account that is not used for any other purpose.
For applications that are related and share protection requirements, configure them as a group to use the same account.
Firewall operation is based on conversion of SQL statements to
normalized digest form. Firewall digests are like the statement
digests used by the Performance Schema (see
Performance Schema Statement Digests).
However, unlike the Performance Schema, the relevant
digest-related system variable is
max_digest_length.
For a connection from a registered account, the firewall converts each incoming statement to normalized form and processes it according to the account mode:
In recording mode, the firewall adds the normalized statement to the account whitelist rules.
In protecting mode, the firewall compares the normalized
statement to the account whitelist rules. If there is a
match, the statement passes and the server continues to
process it. Otherwise, the server rejects the statement and
returns an error to the client. As of MySQL 5.6.25, the
firewall also writes the rejected statement to the error log
if the mysql_firewall_trace
system variable is enabled.
In detecting mode, the firewall matches statements as in protecting mode, but writes nonmatching statements to the error log without denying access.
Accounts that have a mode of OFF or are not
registered with the firewall are ignored by it.
Before MySQL 5.6.25, MySQL Enterprise Firewall records prepared statements as they are received by the server, not as normalized digests. Thus, spaces, tabs, and lettercase are signficant for comparison of whitelist rules against incoming statements.
To protect an account using MySQL Enterprise Firewall, follow these steps:
Register the account and put it in recording mode.
Connect to the MySQL server using the registered account and execute statements to be learned. This establishes the account's whitelist of accepted statements.
Switch the registered account to protecting mode.
The following example shows how to register an account with the
firewall, use the firewall to learn acceptable statements for
that account, and protect the account against execution of
unacceptable statements. The example account,
'fwuser'@'localhost', is for use by an
application that accesses tables in the
sakila database. (This database is available
at http://dev.mysql.com/doc/index-other.html.)
The user and host parts of the account name are quoted
separately for statements such as CREATE
USER and GRANT,
whereas to specify an account for use with a firewall
component, name it as a single quoted string
'fwuser@localhost'.
The convention for naming accounts as a single quoted string
for firewall components means that you cannot use accounts
that have embedded @ characters in the user
name.
Perform the steps in the following procedure using an
administrative MySQL account, except those designated for
execution by the account registered with the firewall. The
default database should be sakila for
statements executed using the registered account.
If necessary, create the account to be protected (choose an
appropriate password) and grant it privileges for the
sakila database:
mysql>CREATE USER 'fwuser'@'localhost' IDENTIFIED BY 'fWp@3sw0rd';mysql>GRANT ALL ON sakila.* TO 'fwuser'@'localhost';
Use the sp_set_firewall_mode() stored
procedure to register the account with the firewall and
place it in recording mode (if the procedure is located in a
database other than mysql, adjust the
statement accordingly):
mysql> CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'RECORDING');
During the course of its execution, the stored procedure invokes firewall user-defined functions, which may produce output of their own.
Using the registered account, connect to the server, then execute some statements that are legitimate for it:
mysql>SELECT first_name, last_name FROM customer WHERE customer_id = 1;mysql>UPDATE rental SET return_date = NOW() WHERE rental_id = 1;mysql>SELECT get_customer_balance(1, NOW());
The firewall converts the statements to digest form and records them in the account whitelist.
Until the account executes statements in recording mode, its whitelist is empty, which is equivalent to “deny all.” If switched to protecting mode, the account will be effectively prohibited from executing statements.
At this point, the user and whitelist information is cached
and can be seen in the firewall
INFORMATION_SCHEMA tables:
mysql>SELECT MODE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS->WHERE USERHOST = 'fwuser@localhost';+-----------+ | MODE | +-----------+ | RECORDING | +-----------+ mysql>SELECT RULE FROM INFORMATION_SCHEMA.MYSQL_FIREWALL_WHITELIST->WHERE USERHOST = 'fwuser@localhost';+----------------------------------------------------------------------------+ | RULE | +----------------------------------------------------------------------------+ | SELECT `first_name` , `last_name` FROM `customer` WHERE `customer_id` = ? | | SELECT `get_customer_balance` ( ? , NOW ( ) ) | | UPDATE `rental` SET `return_date` = NOW ( ) WHERE `rental_id` = ? | | SELECT @@`version_comment` LIMIT ? | +----------------------------------------------------------------------------+
The @@version_comment rule comes from a
statement sent automatically by the
mysql client when you connect to the
server as the registered user.
It is important to train the firewall under conditions matching application use. For example, a given MySQL connector might send statements to the server at the beginning of a connection to determine server characteristics and capabilities. If an application normally is used through that connector, train the firewall that way, too. That enables those initial statements to become part of the whitelist for the account associated with the application.
Use the stored procedure to switch the registered user to protecting mode:
mysql> CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'PROTECTING');
Switching the account out of RECORDING
mode synchronizes its firewall cache data to the
underlying mysql system database tables
for persistent storage. If you do not switch the mode for
a user who is being recorded, the cached whitelist data is
not written to the system tables and will be lost when the
server is restarted.
Using the registered account, execute some acceptable and unacceptable statements. The firewall matches each one against the account whitelist and accepts or rejects it.
This statement is not identical to a training statement but produces the same normalized statement as one of them, so the firewall accepts it:
mysql> SELECT first_name, last_name FROM customer WHERE customer_id = '48';
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| ANN | EVANS |
+------------+-----------+
These statements do not match anything in the whitelist and each results in an error:
mysql>SELECT first_name, last_name FROM customer WHERE customer_id = 1 OR TRUE;ERROR 1045 (28000): Statement was blocked by Firewall mysql>SHOW TABLES LIKE 'customer%';ERROR 1045 (28000): Statement was blocked by Firewall mysql>TRUNCATE TABLE mysql.slow_log;ERROR 1045 (28000): Statement was blocked by Firewall
As of MySQL 5.6.25, the firewall also writes the rejected
statements to the error log if the
mysql_firewall_trace system
variable is enabled. For example:
[Note] Plugin MYSQL_FIREWALL reported: 'ACCESS DENIED for fwuser@localhost. Reason: No match in whitelist. Statement: TRUNCATE TABLE `mysql` . `slow_log` '
You can use these log messages in your efforts to identify the source of attacks.
As of MySQL 5.6.26, you can log nonmatching statements as suspicious without denying access. To do this, put the account in intrusion-detecting mode:
mysql> CALL mysql.sp_set_firewall_mode('fwuser@localhost', 'DETECTING');
Using the registered account, connect to the server, then execute some statement does not match the whitelist:
mysql> SHOW TABLES LIKE 'customer%';
+------------------------------+
| Tables_in_sakila (customer%) |
+------------------------------+
| customer |
| customer_list |
+------------------------------+
In detecting mode, the firewall permits the nonmatching statement to execute but writes a message to the error log:
[Note] Plugin MYSQL_FIREWALL reported: 'SUSPICIOUS STATEMENT from 'fwuser@localhost'. Reason: No match in whitelist. Statement: SHOW TABLES LIKE ? '
To assess firewall activity, examine its status variables:
mysql> SHOW GLOBAL STATUS LIKE 'Firewall%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Firewall_access_denied | 3 |
| Firewall_access_granted | 4 |
| Firewall_access_suspicious | 1 |
| Firewall_cached_entries | 4 |
+----------------------------+-------+
The variables indicate the number of statements rejected,
accepted, logged as suspicious, and added to the cache,
respectively. The
Firewall_access_granted
count is 4 because of the
@@version_comment statement sent by the
mysql client each of the three time you
used it to connect as the registered user, plus the
SHOW TABLES statement that
was not blocked in DETECTING mode.
Should additional training for an account be necessary, switch it to recording mode again, then back to protecting mode after executing statements to be added to the whitelist.
The following discussion serves as a reference to these MySQL Enterprise Firewall components:
Firewall tables in the mysql and
INFORMATION_SCHEMA databases
Firewall procedures and functions
Firewall system variables
Firewall status variables
MySQL Enterprise Firewall maintains account and whitelist information. It uses
INFORMATION_SCHEMA tables to provide views
into cached data, and tables in the mysql
system database to store this data in persistent form. When
enabled, the firewall bases its operational decisions on the
cached data.
The INFORMATION_SCHEMA tables are
accessible by anyone. The mysql tables can
be accessed only by users with privileges for that database.
The INFORMATION_SCHEMA.MYSQL_FIREWALL_USERS
and mysql.firewall_users tables list
registered firewall accounts and their operational modes. The
tables have these columns:
USERHOST
An account registered with the firewall. Each account has
the format
and represents actual user and host names as authenticated
by the server. Patterns and netmasks should not be used
when registering users.
user_name@host_name
MODE
The current firewall operational mode for the account. The
permitted mode values are OFF,
DETECTING (as of MySQL 5.6.26),
PROTECTING,
RECORDING, and
RESET. For details about their
meanings, see the description of
sp_set_firewall_mode() in
Section 7.4.4.2, “MySQL Enterprise Firewall Procedures and Functions”.
The
INFORMATION_SCHEMA.MYSQL_FIREWALL_WHITELIST
and mysql.firewall_whitelist tables list
registered firewall accounts and their whitelists. The tables
have these columns:
USERHOST
An account registered with the firewall. The format is the same as for the user account tables.
RULE
A normalized statement indicating an acceptable statement pattern for the account. An account whitelist is the union of its rules.
MySQL Enterprise Firewall has stored procedures that perform tasks such as registering MySQL accounts with the firewall, establishing their operational mode, and managing transfer of firewall data between the cache and the underlying system tables. It also has a set of user-defined functions (UDFs) that provides an SQL-level API for lower-level tasks such as synchronizing the cache with the underlying system tables.
Under normal operation, the stored procedures implement the user interface. The UDFs are invoked by the stored procedures, not directly by users.
To invoke a stored procedure when the default database is not the database that contains the procedure, qualify the procedure name with the database name. For example:
CALL mysql.sp_set_firewall_mode(user,mode);
The following list describes each firewall stored procedure and UDF:
sp_reload_firewall_rules(
user)
This stored procedure uses firewall UDFs to reset a
registered account and reload the in-memory rules for it
from the rules stored in the
mysql.firewall_whitelist table. This
procedure provides control over firewall operation for
individual accounts.
The user argument names the
affected account, as a string in
format.
user_name@host_name
Example:
CALL mysql.sp_reload_firewall_rules('fwuser@localhost');
This procedure sets the account mode to
RESET, which clears the account
whitelist and sets its mode to OFF.
If the account mode was not OFF prior
to the sp_reload_firewall_rules()
call, use sp_set_firewall_mode() to
restore its previous mode after reloading the rules. For
example, if the account was in
PROTECTING mode, that is no longer
true after calling
sp_reload_firewall_rules() and you
must set it to PROTECTING again
explicitly.
sp_set_firewall_mode(
user,
mode)
This stored procedure registers a MySQL account with the
firewall and establishes its operational mode. The
procedure also invokes firewall UDFs as necessary to
transfer firewall data between the cache and the
underlying system tables. This procedure may be called
even if the mysql_firewall_mode system
variable is OFF, although setting the
mode for an account has no operational effect while the
firewall is disabled.
The user argument names the
affected account, as a string in
format.
user_name@host_name
The mode is the operational
mode for the user, as a string. These mode values are
permitted:
OFF: Disable the firewall for the
account.
DETECTING: Intrusion-detection
mode: Write suspicious (nonmatching) statements to the
error log but do not deny access.
PROTECTING: Protect the account by
matching incoming statements against the account
whitelist.
RECORDING: Training mode: Record
acceptable statements for the account. Incoming
statements that do not immediately fail with a syntax
error are recorded to become part of the account
whitelist rules.
RESET: Clear the account whitelist
and set the account mode to OFF.
Switching the mode for an account to any mode but
RECORDING synchronizes the firewall
cache data to the underlying mysql
system database tables for persistent storage. Switching
the mode from OFF to
RECORDING reloads the whitelist from
the mysql.firewall_whitelist table into
the cache.
If an account has an empty whitelist, setting its mode to
PROTECTING produces an error message
that is returned in a result set, but not an SQL error:
mysql> CALL mysql.sp_set_firewall_mode('a@b','PROTECTING');
+----------------------------------------------------------------------+
| set_firewall_mode(arg_userhost, arg_mode) |
+----------------------------------------------------------------------+
| ERROR: PROTECTING mode requested for a@b but the whitelist is empty. |
+----------------------------------------------------------------------+
1 row in set (0.02 sec)
Query OK, 0 rows affected (0.02 sec)
mysql_firewall_flush_status()
This UDF resets several firewall status variables to 0:
Firewall_access_denied Firewall_access_granted Firewall_access_suspicious
Example:
SELECT mysql_firewall_flush_status();
normalize_statement(
stmt)
This UDF normalizes an SQL statement into the digest form used for whitelist rules.
Example:
SELECT normalize_statement('SELECT * FROM t1 WHERE c1 > 2');
read_firewall_users(
user,
mode)
This aggregate UDF updates the firewall user cache through
a SELECT statement on the
mysql.firewall_users table.
Example:
SELECT read_firewall_users('fwuser@localhost', 'RECORDING')
FROM mysql.firewall_users;
read_firewall_whitelist(
user,
rule)
This aggregate UDF updates the recorded statement cache
through a SELECT statement on the
mysql.firewall_whitelist table.
Example:
SELECT read_firewall_whitelist('fwuser@localhost', 'RECORDING')
FROM mysql.firewall_whitelist;
set_firewall_mode(
user,
mode)
This UDF manages the user cache and establishes the user operational mode.
Example:
SELECT set_firewall_mode('fwuser@localhost', 'RECORDING');
MySQL Enterprise Firewall supports the following system variables. Use them to configure firewall operation. These variables are unavailable unless the firewall is installed (see Section 7.4.2, “Installing or Uninstalling MySQL Enterprise Firewall”).
| Introduced | 5.6.24 | ||
| Removed | 5.6.26 | ||
| Command-Line Format | --mysql_firewall_max_query_size=size | ||
| System Variable | Name | mysql_firewall_max_query_size | |
| Variable Scope | Global | ||
| Dynamic Variable | No | ||
| Permitted Values | Type | integer | |
| Default | 4096 | ||
| Min Value | 0 | ||
| Max Value | 4294967295 | ||
The maximum size of a normalized statement that can be
inserted in the MySQL Enterprise Firewall cache. Normalized statements longer
than this size are truncated. Truncated statements are
discarded if the firewall mode for the current user is
RECORDING and rejected if the mode is
PROTECTING.
mysql_firewall_max_query_size
was removed in MySQL 5.6.26.
max_digest_length should
be set large enough to avoid statement truncation.
| Introduced | 5.6.24 | ||
| Command-Line Format | --mysql_firewall_mode={OFF|ON} | ||
| System Variable | Name | mysql_firewall_mode | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | boolean | |
| Default | ON | ||
Whether MySQL Enterprise Firewall is enabled (the default) or disabled.
| Introduced | 5.6.24 | ||
| Command-Line Format | --mysql_firewall_trace={OFF|ON} | ||
| System Variable | Name | mysql_firewall_trace | |
| Variable Scope | Global | ||
| Dynamic Variable | Yes | ||
| Permitted Values | Type | boolean | |
| Default | OFF | ||
Whether the MySQL Enterprise Firewall trace is enabled or disabled (the
default). When enabled,
mysql_firewall_trace has
this effect:
In MySQL 5.6.24, the firewall writes a file named
firewall_trace.txt in the data
directory.
In MySQL 5.6.25 and higher, for
PROTECTING mode, the firewall
writes rejected statements to the error log.
MySQL Enterprise Firewall supports the following status variables. Use them to
obtain information about firewall operational status. These
variables are unavailable unless the firewall is installed
(see Section 7.4.2, “Installing or Uninstalling MySQL Enterprise Firewall”). Firewall status
variables are set to 0 whenever the
MYSQL_FIREWALL plugin is installed or the
server is started. Many of them are reset to zero by the
mysql_firewall_flush_status() UDF (see
Section 7.4.4.2, “MySQL Enterprise Firewall Procedures and Functions”).
The number of statements rejected by MySQL Enterprise Firewall.
The number of statements accepted by MySQL Enterprise Firewall.
The number of statements logged by MySQL Enterprise Firewall as suspicious
for users who are in DETECTING mode.
The number of statements recorded by MySQL Enterprise Firewall, including duplicates.