MySQL8 authentication plug-in - PAM Pluggable Authentication

MySQL Enterprise Edition supports an authentication method that enables MySQL Server to authenticate MySQL users using PAM (Plugable Authentication Modules). PAM enables systems to use standard interfaces to access various authentication methods, such as traditional Unix passwords or LDAP directories.

PAM Pluggable Authentication provides the following features:

● External authentication: PAM authentication enables MySQL Server to accept connections from users defined outside of the MySQL authorization tables and authenticate using methods supported by PAM.

● Proxy user support: PAM authentication can return to MySQL a user name different from the external user name passed by the client program according to the PAM group to which the external user belongs and the provided authentication string. This means that a plugin can return a MySQL user that defines the privileges that the external PAM authenticated user should have. For example, an operating system user named joe can connect and have the privileges of a MySQL user named developer.

PAM pluggable authentication has been tested on Linux and macOS.

Plugin and library names

plugin or file

plugin or file name

Server-side plugin

authentication_pam

Client-side plugin

mysql_clear_password

Library file

authentication_pam.so

The client-side mysql_clear_password cleartext plugin that communicates with the server-side PAM plugin is built into the libmysqlclient client library and is included with all distributions, including community distributions. The client-side plaintext plugin is included in all MySQL distributions, enabling clients of any distribution to connect to servers loaded with the server-side PAM plugin.

How PAM Authentication for MySQL Users Works

1. The client program communicates with the server, and the client sends the client user name (the default is the operating system user name) and password to the server:

■ The client username is the external username.

■ For accounts using the PAM server-side authentication plugin, the corresponding client-side plugin is mysql_clear_password This client-side plugin does not perform password hashing, with the result that the client sends the password to the server as clear text.

2. The server finds a matching MySQL account based on the external user name and the host connected by the client. The PAM plugin uses information passed to it by MySQL Server (such as username, hostname, password, and authentication strings). When you define a MySQL account that uses PAM for authentication, the authentication string contains:

■ The PAM service name, which system administrators can use to refer to the authentication method for a particular application. There can be multiple applications associated with a single database server instance, so the choice of service name is left to the SQL application developer.

■ Optionally, if you want to use a proxy, you can use a mapping from PAM groups to MySQL usernames.

3. The plugin uses the PAM service named in the authentication string to check user credentials and returns 'Authentication succeeded, Username is user_name' or 'Authentication failed' The password must be suitable for the password store used by the PAM service. Example:

■ For traditional Unix passwords, the service looks for passwords stored in the /etc/shadow file.

■ For LDAP, the service looks up passwords stored in the LDAP directory.

If the credential check fails, the server will refuse the connection.

4. Otherwise, the authentication string indicates whether proxying occurs. If the string does not contain a PAM group mapping, no proxying will occur. In this case, the MySQL username is the same as the external username.

5. Otherwise, the proxy is indicated based on the PAM group mapping, and the MySQL username is determined based on the first matching group in the mapping list. The meaning of "PAM group" depends on the PAM service. Example:

■ For traditional Unix passwords, the group is the Unix group defined in the /etc/group file, possibly adding additional PAM information in files such as /etc/security/group.conf.

■ For LDAP, groups are LDAP groups defined in the LDAP directory.

If the proxy user (external user) has proxy privileges on the proxied MySQL user name, proxying will occur, and the proxy user will assume the privileges of the proxied user.

Install PAM Pluggable Authentication

To be used by the server, plugin library files must be located in the MySQL plugin directory (the directory named by the plugin_dir system variable). If necessary, configure the plugin directory location by setting the value of plugin_dir on server startup.

The base name of the plugin library file is authentication_pam. The filename suffix varies by platform (for example, .so for Unix and Unix-like systems, .dll for Windows).

To load a plugin at server startup, use the --plugin-load-add option to name the library file that contains the plugin. With this plugin loading method, this option must be given every time the server starts. For example, put these lines in the server my.cnf file, adjusting the platform's .so suffix as needed:

[mysqld]
plugin-load-add=authentication_pam.so

After modifying my.cnf, restart the server for the new settings to take effect. Alternatively, to load the plugin at runtime, use the following statement, adjusting the platform's .so suffix as needed:

INSTALL PLUGIN authentication_pam SONAME 'authentication_pam.so';

INSTALL PLUGIN loads the plugin immediately and registers it in the mysql.plugins system table so that the server loads it on every subsequent normal startup without --plugin-load-add

To verify plugin installation, check the Information Schema PLUGINS table or use the SHOW PLUGINS statement. For example:

SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%pam%';
+--------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+--------------------+---------------+
| authentication_pam | ACTIVE |
+--------------------+---------------+

If the plugin fails to initialize, check the server error log for diagnostic messages.

Uninstall PAM Pluggable Authentication

The method used to uninstall the PAM authentication plugin depends on how you installed it:

● If you installed the plugin with the --plugin-load-add option at server startup, restart the server without this option.

● If you install a plug-in at runtime using the INSTALL PLUGIN statement, it remains installed across server restarts. To uninstall it, use

UNINSTALL PLUGIN authentication_pam;

Using PAM Pluggable Authentication

The following sections provide instructions for using PAM authentication in specific ways. Assuming the server is running with the server-side PAM plugin enabled

CREATE USER user IDENTIFIED WITH authentication_pam AS 'auth_string';

Authentication strings specify the following types of information:

● PAM service name. The examples in the discussion below use the mysql-unix service name for authentication using traditional unix passwords and mysql-ldap for authentication using ldap.

● For proxy support, PAM provides a way for PAM modules to return the MySQL username to the server when connecting to it, rather than the external username passed by the client program. Use authentication strings to control the mapping from external usernames to MySQL usernames. The authentication string must include this mapping if you want to take advantage of the proxy user functionality.

For example, if an account uses the mysql-unix PAM service name, and the operating system 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-unix, root=developer, users=data_entry';

The authentication string syntax for the PAM authentication plugin follows the following rules:

● The string consists of a PAM service name, optionally followed by a list of PAM group mappings consisting of one or more key/value pairs, each specifying a PAM group name and MySQL username:

pam_service_name[,pam_group_name=mysql_user_name] . . .

The plugin parses the authentication string for every connection attempt using the account. To minimize overhead, keep the strings as short as possible.

● Each pam_group_name=mysql_user_name pair must be preceded by a comma.

● Leading and trailing spaces not within double quotes are ignored.

● pam_service_name, pam_group_name, and mysql_user_name values ​​that are not enclosed in double quotes can contain anything except equal signs, commas, or spaces.

● If a pam_service_name, pam_group_name, or mysql_user_name value is enclosed in double quotes, everything between the quotes is part of the value. This is necessary, for example, if the value contains space characters. All characters are legal except double quotes and backslashes (\). To include double quotes and backslashes (\), escape them with a backslash.

If the plugin successfully authenticates the external username (the name passed by the client), it looks in the authentication string for a list of PAM group mappings, and if present, uses that list to return a different MySQL username to the MySQL server, based on what the external user is Member of which PAM group:

● If the authentication string does not contain a list of PAM group mappings, the plugin will return the external name.

● If the authentication string does contain a list of PAM group mappings, the plugin checks each pam_group_name=mysql_user_name pair in the list from left to right and tries to find a match for the pam_group_name value in a non-mysql directory of the authenticating user's group, and returns the mysql_user_name for the first match found. If the plugin cannot find a match for any PAM group, the external name is returned. If the plugin cannot look up the group in the directory, it ignores the PAM group mapping list and returns the external name.

The following sections describe how to set up several authentication scenarios that use the PAM authentication plugin:

● There are no proxy users. Only use PAM to check logins and passwords. Every external user that is allowed to connect to MySQL Server should have a matching MySQL account that is defined to use PAM authentication. (For a MySQL account of 'user_name'@'host_name', to match an external user, user_name must be the external username, and host_name must match the host the client is connecting to.) Authentication can be performed by various PAM-supported methods.

If PAM authentication is not via a proxy user or PAM group, the MySQL username is required to be the same as the operating system username. MySQL usernames are limited to 32 characters, which limits PAM non-proxy authentication to Unix accounts with names up to 32 characters.

● Proxy users only, with PAM group mappings. For this case, create one or more MySQL accounts that define different sets of privileges. (Ideally, no one should be connecting directly using these accounts.) Then define a default user that authenticates via PAM, which maps all external users to Names map to a small number of MySQL accounts that hold privileged sets. Any client that connects and specifies the external username as the client username is mapped to one of the MySQL accounts and uses its privileges.

These conditions are subject to change:

● You can allow some users to log in directly (without a proxy), but require other users to connect through a proxy account.

● By using different PAM service names on PAM-authenticated accounts, you can use one authentication method for some users and another for others. For example, you can use the mysql-unix PAM service for some users and the mysql-ldap PAM service for others.

These examples make the following assumptions. If your system is set up differently, you may need to make some adjustments.

● The login and password are pamuser and pamuser_password respectively Change these to correspond to the user being authenticated.

● The PAM configuration directory is /etc/pam.d.

● The PAM service name corresponds to the authentication method (mysql-unix or mysql-ldap in this discussion). To use a given PAM service, a PAM file of the same name must be set up in the PAM configuration directory (or created if it does not exist). Additionally, for any account to authenticate with a PAM service, the PAM service must be named in the authentication string of the CREATE USER statement.

The PAM authentication plugin checks on initialization that the AUTHENTICATION_PAM_LOG environment value is set in the server's startup environment. If so, the plugin will allow logging of diagnostic messages to standard output. Depending on how the server was started, the message might appear in the console or in the error log. These messages are useful for debugging PAM-related problems when the plugin performs authentication.

PAM Unix password authentication for agentless users

This authentication scenario uses PAM to check external users defined in terms of operating system usernames and Unix passwords, without a proxy. Every external user that is allowed to connect to MySQL Server should have a matching MySQL account defined to use PAM authentication over traditional Unix password stores.

1. Verify that Unix authentication allows login to the operating system with username pamuser and password pamuser_password.

2. Set up PAM to authenticate MySQL connections using traditional Unix passwords by creating a mysql-unix PAM service file named /etc/pam.d/mysql-unix. The file contents are system dependent, so check the existing login-related files in the /etc/pam.d directory to see what they look like. On Linux, the mysql-unix file might look like this:

#%PAM-1.0
auth include password-auth
account include password-auth

For macOS, use login instead of password-auth

The PAM file format may vary on some systems. For example, on Ubuntu and other Debian-based systems, use the following file content:

@include common-auth
@include common-account
@include common-session-noninteractive

3. Create a MySQL account with the same username as the operating system username and define it to authenticate with the PAM plugin and the mysql-unix PAM service:

CREATE USER 'pamuser'@'localhost' IDENTIFIED WITH authentication_pam AS 'mysql-unix';
GRANT ALL PRIVILEGES ON mydb.* TO 'pamuser'@'localhost';

Here, the authentication string only contains the PAM service name, mysql-unix , to verify the unix password.

4. Use the mysql command line client to connect to the mysql server as pamuser. For example:

mysql --user=pamuser --password --enable-cleartext-plugin

The server should allow the connection, and the following query returns output as shown:

SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+-------------------+--------------+
| USER() | CURRENT_USER() | @@proxy_user |
+-------------------+-------------------+--------------+
| pamuser@localhost | pamuser@localhost | NULL |
+-------------------+-------------------+--------------+

This indicates that the pamuser operating system user is authenticated, has permissions granted to the pamuser MySQL user, and no proxying is occurring.

illustrate:

The client mysql_clear_password authentication plugin keeps the password unchanged, so client programs send it to the mysql server as clear text. This allows passwords to be passed to PAM as-is. Clear text passwords are required to use the server-side PAM library, but may be a security issue in some configurations. These measures minimize risk:

● To reduce the possibility of accidentally using the mysql_clear_password plugin, mysql clients must explicitly enable it (for example, using the --enable-cleartext-plugin plugin option).

● To avoid exposing passwords when the mysql_clear_password plugin is enabled, the mysql client should use an encrypted connection to connect to the mysql server.

PAM LDAP authentication for agentless users

This authentication scenario uses PAM to check external users defined against operating system usernames and LDAP passwords, without a proxy. Every external user that is allowed to connect to MySQL Server should have a matching MySQL account defined to use PAM authentication over LDAP.

To use PAM LDAP pluggable authentication with MySQL, the following prerequisites must be met:

● The LDAP server must be available for the PAM LDAP service to communicate.

● Every LDAP user to be authenticated by MySQL must exist in a directory managed by the LDAP server.

Description: An alternative to MySQL user authentication using LDAP is to use an LDAP-specific authentication plugin.

Configure MySQL for PAM LDAP authentication as follows:

1. Verify that Unix authentication allows login to the operating system with username pamuser and password pamuser_password.

2. Set up PAM authentication to use LDAP-authenticated MySQL connections by creating a mysql-ldap PAM service file named //etc/pam.d/mysql-ldap. The contents of this file are system dependent, so check the existing login-related files in the /etc/pam.d directory to see what they look like. On Linux, the mysql-ldap file might look like this:

#%PAM-1.0
auth required pam_ldap.so
account required pam_ldap.so

If the PAM object file has a different suffix than the .so on your system, substitute the correct suffix. The PAM file format may vary on some systems.

3. Create a MySQL account with the same username as the operating system username and define it to authenticate with the PAM plugin and the mysql-ldap PAM service:

CREATE USER 'pamuser'@'localhost' IDENTIFIED WITH authentication_pam AS 'mysql-ldap';
GRANT ALL PRIVILEGES ON mydb.* TO 'pamuser'@'localhost';

Here, the authentication string contains only the PAM service name, mysql-ldap , which uses ldap for authentication.

4. Connect to the server as described in "PAM Unix Password Authentication for Agentless Users".

PAM Unix password authentication using proxy user and group mapping

The authentication scheme described here uses proxies and PAM group mappings to map connecting MySQL users who authenticate using PAM to other MySQL accounts that define different sets of privileges. Users do not connect directly through accounts that define permissions. Instead, they connect by using the default proxy account for PAM authentication, so that all external users are mapped to privileged MySQL accounts. Any user connecting using a proxy account is mapped to one of the MySQL accounts, and the permissions of these accounts determine the database operations allowed by external users.

The procedure shown here uses Unix password authentication. To use LDAP, see the earlier steps in "PAM LDAP Authentication for Agentless Users".

1. Verify that Unix authentication allows login to the operating system with username pamuser and password pamuser_password.

2. Verify that pamuser is a member of the root or users PAM group.

3. Set up PAM to authenticate to the mysql-unix PAM service with the operating system user by creating a file named /etc/pam.d/mysql-unix. 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-unix file might look like this:

#%PAM-1.0
auth include password-auth
account include password-auth

For macOS, use login instead of password-auth

The PAM file format may vary on some systems. For example, on Ubuntu and other Debian-based systems, use the following file content:

@include common-auth
@include common-account
@include common-session-noninteractive

4. Create a default proxy user ((''@'') to map the external PAM user to the proxy account:

CREATE USER ''@'' IDENTIFIED WITH authentication_pam AS 'mysql-unix, root=developer, users=data_entry';

Here, the authentication string contains the PAM service name, mysql-unix , which is used to verify the unix password. The authentication string also maps external users in the root and users PAM groups to the developer and data_entry MySQL usernames, respectively.

When setting up a proxy user, a list of PAM group mappings following the PAM service name is required. Otherwise, the plugin cannot tell how to perform the mapping from the external username to the correct proxy's MySQL username.

Explanation: If MySQL is installed with anonymous users, they may conflict with the default proxy user.

5. Create proxy accounts and grant each account the appropriate permissions:

CREATE USER 'developer'@'localhost' IDENTIFIED WITH mysql_no_login;
CREATE USER 'data_entry'@'localhost' IDENTIFIED WITH mysql_no_login;
GRANT ALL PRIVILEGES ON mydevdb.* TO 'developer'@'localhost';
GRANT ALL PRIVILEGES ON mydb.* TO 'data_entry'@'localhost';

Proxy accounts use the mysql_no_login authentication plugin to prevent clients from directly logging into the mysql server using these accounts. Instead, users authenticating with PAM should use the developer or data_entry account via proxy, depending on their PAM group.

6. Grant the proxy accounts proxy permissions for each proxy account:

GRANT PROXY ON 'developer'@'localhost' TO ''@'';
GRANT PROXY ON 'data_entry'@'localhost' TO ''@'';

7. Use the mysql command line client to connect to the mysql server as pamuser.

mysql --user=pamuser --password --enable-cleartext-plugin
Enter password: pamuser_password

The server authenticates the connection using the default ''@'' proxy account. The final privileges of pamuser depend on which PAM group pamuser is a member of. If pamuser is a member of the root PAM group, the PAM plugin maps root to the developer MySQL username and returns that name to the server. The server verifies that ''@'' has proxy permissions for developer and allows the connection. The following query returns output as shown:

SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+---------------------+--------------+
| USER() | CURRENT_USER() | @@proxy_user |
+-------------------+---------------------+--------------+
| pamuser@localhost | developer@localhost | ''@'' |
+-------------------+---------------------+--------------+

This indicates that the pamuser operating system user is authenticated, has privileges granted to the developer MySQL user, and that proxying is through the default proxy account.

If pamuser is not a member of the root PAM group, but a member of the users PAM group, a similar process occurs, but the plugin maps the users PAM group membership to the data_entry MySQL username and returns that name to the server:

SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+----------------------+--------------+
| USER() | CURRENT_USER() | @@proxy_user |
+-------------------+----------------------+--------------+
| pamuser@localhost | data_entry@localhost | ''@'' |
+-------------------+----------------------+--------------+

This shows that the pamuser operating system user is authenticated, has the privileges of the data_entry MySQL user, and that proxying is through the default proxy account.

illustrate:

The client mysql_clear_password authentication plugin leaves the password unchanged, so the client program sends it to the mysql server as clear text. This allows passwords to be passed to PAM as-is. Clear text passwords are required to use the server-side PAM library, but may be a security issue in some configurations. These measures minimize risk:

● To reduce the possibility of accidentally using the mysql_clear_password plugin, mysql clients must explicitly enable it (for example, using the --enable-cleartext-plugin plugin option).

● To avoid exposing passwords when the mysql_clear_password plugin is enabled, the mysql client should use an encrypted connection to connect to the mysql server.

PAM authentication to access Unix password storage

On some systems, Unix authentication uses password storage, such as /etc/shadow, which is a file that usually has restricted access. This may cause MySQL PAM based authentication to fail. Unfortunately, the PAM implementation does not allow the distinction between "password cannot be checked" (e.g. due to failure to read /etc/shadow) and "password mismatch". If you use a Unix password store for PAM authentication, you can access it from MySQL using one of the following methods:

● Assuming the MySQL server is running from the mysql operating system account, put that account in the shadow group with /etc/shadow access:

a. Create a shadow group in /etc/group.

b. Add the mysql operating system user to the shadow group in /etc/group.

c. Assign /etc/group to the shadow group and enable group read permissions:

chgrp shadow /etc/shadow
chmod g+r /etc/shadow

d. Restart the MySQL server.

● If you are using the pam_unix module and the unix_chkpwd utility, enable password store access as follows:

chmod u-s /usr/sbin/unix_chkpwd
setcap cap_dac_read_search+ep /usr/sbin/unix_chkpwd

According to the needs of the platform, adjust the unix_chkpwd path

PAM authentication debug

The PAM authentication plugin checks on initialization whether the AUTHENTICATION_PAM_LOG environment value is set (the value does not matter). If so, the plugin will allow logging of diagnostic messages to standard output. These messages may be helpful in debugging PAM-related problems with the authentication performed by the plugin.

Some messages include references to PAM plugin source files and line numbers, which allow plugin operations to be more closely tied to where in the code they occur.

Another technique for debugging connection failures and determining what is happening during connection attempts is to configure PAM authentication to allow all connections and then examine the system log files. This technique should only be used on an ad hoc basis, not on a production server.

Configure a PAM service file named //etc/pam.d/mysql-any-password with the following content
(the format may be different on some systems):

#%PAM-1.0
auth required pam_permit.so
account required pam_permit.so

Create an account using the PAM plugin named mysql-any-password:

CREATE USER 'testuser'@'localhost' IDENTIFIED WITH authentication_pam AS 'mysql-any-password';

The mysql-any-password service file causes any authentication attempt to return true, even an incorrect password. If the authentication attempt fails, then that tells the configuration that the problem is on the MySQL side. Otherwise, the problem is on the OS/PAM side. To see what might be happening, check system log files such as /var/log/secure, /var/log/audit.log, /var/log/syslog, or /var/log/messages

After identifying the problem, delete the mysql-any-password PAM service file to disable any-password access.

Guess you like

Origin blog.csdn.net/weixin_44496870/article/details/131380526