6.4.1.7 PAM 可插入身份验证

Note

PAM 可插入身份验证是商业产品 MySQL Enterprise Edition 中包含的扩展。要了解有关商品的更多信息,请参阅https://www.mysql.com/products/

MySQL Enterprise Edition 支持一种身份验证方法,该方法使 MySQL Server 能够使用 PAM(可插入身份验证模块)来对 MySQL 用户进行身份验证。 PAM 使系统能够使用标准接口来访问各种身份验证方法,例如传统的 Unix 密码或 LDAP 目录。

PAM 可插入身份验证提供以下功能:

PAM 可插入身份验证已在 Linux 和 macOS 上进行了测试。

下 table 显示了插件和库文件名。文件名后缀可能在您的系统上有所不同。该文件必须位于plugin_dir系统变量命名的目录中。有关安装信息,请参见安装 PAM 可插入身份验证

table6.13 用于 PAM 身份验证的插件和库名称

插件或文件 插件或文件名
Server-side plugin authentication_pam
Client-side plugin mysql_clear_password
Library file authentication_pam.so

与服务器端 PAM 插件进行通信的 Client 端mysql_clear_password cleartext 插件内置在libmysqlclientClient 端库中,并包含在所有发行版中,包括社区发行版。在所有 MySQL 发行版中都包含 Client 端明文插件,使来自任何发行版的 Client 端都可以连接到已加载了服务器端 PAM 插件的服务器。

以下各节提供特定于 PAM 可插入身份验证的安装和使用信息:

有关 MySQL 中可插拔身份验证的一般信息,请参见第 6.2.13 节“可插入身份验证”。有关mysql_clear_password插件的信息,请参见第 6.4.1.6 节“Client 端明文可插入身份验证”。有关代理用户的信息,请参见第 6.2.14 节“代理用户”

MySQL 用户的 PAM 身份验证如何工作

本节概述了 MySQL 和 PAM 如何协同工作以认证 MySQL 用户。有关显示如何设置 MySQL 帐户以使用特定 PAM 服务的示例,请参见使用 PAM 可插入身份验证

如果凭据检查失败,则服务器拒绝连接。

如果代理用户(外部用户)对代理的 MySQL 用户名具有PROXY特权,则将进行代理,代理用户将承担代理用户的特权。

安装 PAM 可插入身份验证

本节介绍如何安装 PAM 身份验证插件。有关安装插件的一般信息,请参见第 5.5.1 节“安装和卸载插件”

要由服务器使用,插件库文件必须位于 MySQL 插件目录(由plugin_dir系统变量命名的目录)中。如有必要,通过在服务器启动时设置plugin_dir的值来配置插件目录位置。

插件库文件的基本名称为authentication_pam。每个平台的文件名后缀都不同(例如,对于 Unix 和类 Unix 系统,为.so,对于 Windows 为.dll)。

要在服务器启动时加载插件,请使用--plugin-load-add选项命名包含该插件的库文件。使用这种插件加载方法,每次服务器启动时都必须给出该选项。例如,将这些行放在服务器my.cnf文件中,并根据需要调整平台的.so后缀:

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

修改my.cnf后,重新启动服务器以使新设置生效。

或者,要在运行时加载插件,请使用以下语句,并根据需要调整平台的.so后缀:

INSTALL PLUGIN authentication_pam SONAME 'authentication_pam.so';

INSTALL PLUGIN立即加载该插件,并将其注册在mysql.plugins系统 table 中,以使服务器为每次后续的正常启动加载该插件,而无需--plugin-load-add

要验证插件安装,请检查INFORMATION_SCHEMA.PLUGINStable 或使用SHOW PLUGINS语句(请参见第 5.5.2 节“获取服务器插件信息”)。例如:

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

如果插件未能初始化,请检查服务器错误日志以获取诊断消息。

要将 MySQL 帐户与 PAM 插件关联,请参见使用 PAM 可插入身份验证

卸载 PAM 可插入身份验证

卸载 PAM 身份验证插件的方法取决于安装方式:

UNINSTALL PLUGIN authentication_pam;
使用 PAM 可插入身份验证

本节以一般术语描述如何使用 PAM 身份验证插件将 MySQLClient 端程序连接到服务器。以下各节提供了以特定方式使用 PAM 身份验证的说明。如安装 PAM 可插入身份验证所述,假定服务器正在启用服务器端 PAM 插件的情况下运行。

要在CREATE USER语句的IDENTIFIED WITH子句中引用 PAM 身份验证插件,请使用名称authentication_pam。例如:

CREATE USER user
  IDENTIFIED WITH authentication_pam
  AS 'auth_string';

身份验证字符串指定以下类型的信息:

例如,如果一个帐户使用mysql-unix PAM 服务名称,并且应将rootusers PAM 组中的 os 用户分别 Map 到developerdata_entry MySQL 用户,则使用如下语句:

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

PAM 身份验证插件的身份验证字符串语法遵循以下规则:

pam_service_name[,pam_group_name=mysql_user_name]...

该插件为使用该帐户的每次连接尝试解析身份验证字符串。为了最大程度地减少开销,请使字符串尽可能短。

如果插件成功验证了外部用户名(Client 端传递的名称),它将在身份验证字符串中查找 PAM 组 Map 列 table,如果存在,则使用该插件将基于以下内容的另一个 MySQL 用户名返回给 MySQL 服务器:外部用户属于哪个 PAM 组:

以下各节描述如何设置使用 PAM 身份验证插件的几种身份验证方案:

如果不通过代理用户或 PAM 组进行 PAM 身份验证,则需要 MySQL 用户名与 os 用户名相同。 MySQL 用户名限制为 32 个字符(请参阅第 6.2.3 节“授权 table”),这将 PAM 非代理身份验证限制为名称最多为 32 个字符的 Unix 帐户。

这些方案可能会有所不同:

这些示例进行以下假设。如果您的系统设置不同,则可能需要进行一些调整。

PAM 身份验证插件在初始化时检查服务器的启动环境中是否设置了AUTHENTICATION_PAM_LOG环境值。如果是这样,则插件可以将诊断消息记录到标准输出中。该消息可能会显示在控制台上或错误日志中,具体取决于服务器的启动方式。这些消息对于调试插件执行身份验证时发生的与 PAM 相关的问题很有帮助。有关更多信息,请参见PAM 身份验证调试

没有代理用户的 PAM Unix 密码认证

此身份验证方案使用 PAM 来检查根据 os 用户名和 Unix 密码定义的外部用户,而无需代理。每个允许连接到 MySQL Server 的此类外部用户都应具有一个匹配的 MySQL 帐户,该帐户定义为通过传统的 Unix 密码存储区使用 PAM 身份验证。

Note

使用/etc/shadow文件检查传统的 Unix 密码。有关与此文件有关的可能问题的信息,请参见对 Unix 密码存储的 PAM 身份验证访问

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

对于 macOS,请使用login而不是password-auth

在某些系统上,PAM 文件格式可能有所不同。例如,在 Ubuntu 和其他基于 Debian 的系统上,请改用以下文件内容:

@include common-auth
@include common-account
@include common-session-noninteractive
CREATE USER 'antonio'@'localhost'
  IDENTIFIED WITH authentication_pam
  AS 'mysql-unix';
GRANT ALL PRIVILEGES
  ON mydb.*
  TO 'antonio'@'localhost';

此处,认证字符串仅包含用于认证 Unix 密码的 PAM 服务名称mysql-unix

shell> mysql --user=antonio --password --enable-cleartext-plugin
Enter password: antonio_password

服务器应允许连接,并且以下查询返回输出,如下所示:

mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+-------------------+--------------+
| USER()            | CURRENT_USER()    | @@proxy_user |
+-------------------+-------------------+--------------+
| antonio@localhost | antonio@localhost | NULL         |
+-------------------+-------------------+--------------+

这 table 明对antonioos 用户进行了身份验证以具有授予antonio MySQL 用户的特权,并且没有发生代理。

Note

Client 端mysql_clear_password身份验证插件不会更改密码,因此 Client 端程序会将其以明文形式发送到 MySQL 服务器。这样可以将密码原样传递给 PAM。明文密码对于使用服务器端 PAM 库是必需的,但在某些配置中可能是安全问题。这些措施可最大程度地降低风险:

没有代理用户的 PAM LDAP 认证

此身份验证方案使用 PAM 来检查根据 os 用户名和 LDAP 密码定义的外部用户,而无需代理。每个允许连接到 MySQL Server 的此类外部用户应具有一个匹配的 MySQL 帐户,该帐户定义为通过 LDAP 使用 PAM 身份验证。

要将 PAM LDAP 可插拔身份验证用于 MySQL,必须满足以下先决条件:

Note

使用 LDAP 进行 MySQL 用户身份验证的另一种方法是使用 LDAP 特定的身份验证插件。参见第 6.4.1.9 节“ LDAP 可插拔身份验证”

配置 MySQL 以进行 PAM LDAP 身份验证,如下所示:

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

如果 PAM 对象文件的后缀与系统上的.so不同,请替换正确的后缀。

在某些系统上,PAM 文件格式可能有所不同。

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

此处,身份验证字符串仅包含使用 LDAP 进行身份验证的 PAM 服务名称mysql-ldap

使用代理用户和组 Map 的 PAM Unix 密码认证

此处描述的身份验证方案使用代理和 PAM 组 Map 将使用 PAM 进行身份验证的 MySQL 用户连接到定义了不同权限集的其他 MySQL 帐户。用户不会直接通过定义特权的帐户进行连接。相反,它们通过使用 PAM 进行身份验证的默认代理帐户连接,这样所有外部用户都将 Map 到拥有特权的 MySQL 帐户。使用代理帐户进行连接的任何用户都将 Map 到这些 MySQL 帐户之一,这些帐户的特权确定了允许外部用户执行的数据库操作。

此处显示的过程使用 Unix 密码身份验证。要改用 LDAP,请参阅没有代理用户的 PAM LDAP 认证的早期步骤。

Note

使用/etc/shadow文件检查传统的 Unix 密码。有关与此文件有关的可能问题的信息,请参见对 Unix 密码存储的 PAM 身份验证访问

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

对于 macOS,请使用login而不是password-auth

在某些系统上,PAM 文件格式可能有所不同。例如,在 Ubuntu 和其他基于 Debian 的系统上,请改用以下文件内容:

@include common-auth
@include common-account
@include common-session-noninteractive
CREATE USER ''@''
  IDENTIFIED WITH authentication_pam
  AS 'mysql-unix, root=developer, users=data_entry';

这里,认证字符串包含用于认证 Unix 密码的 PAM 服务名称mysql-unix。身份验证字符串还将rootusers PAM 组中的外部用户分别 Map 到developerdata_entry MySQL 用户名。

设置代理用户时,需要 PAM 服务名称后面的 PAM 组 Map 列 table。否则,插件将无法告诉您如何执行从外部用户名到正确的代理 MySQL 用户名的 Map。

Note

如果您的 MySQL 安装中有匿名用户,则它们可能与默认代理用户冲突。有关此问题及其处理方式的更多信息,请参见默认代理用户和匿名用户冲突

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';

代理帐户使用mysql_no_login身份验证插件来防止 Client 端使用帐户直接登录到 MySQL 服务器。相反,预期使用 PAM 进行身份验证的用户将根据其 PAM 组通过代理使用developerdata_entry帐户。 (这假定已安装插件.有关说明,请参阅第 6.4.1.10 节“无登录可插入身份验证”。)有关防止代理帐户直接使用的替代方法,请参阅防止直接登录到代理帐户

GRANT PROXY
  ON 'developer'@'localhost'
  TO ''@'';
GRANT PROXY
  ON 'data_entry'@'localhost'
  TO ''@'';
shell> mysql --user=antonio --password --enable-cleartext-plugin
Enter password: antonio_password

服务器使用默认的''@''代理帐户对连接进行身份验证。 antonio的最终特权取决于antonio是哪个 PAM 组的成员。如果antonioroot PAM 组的成员,则 PAM 插件将rootMap 到developer MySQL 用户名并将该名称返回到服务器。服务器验证''@''拥有developerPROXY特权并允许连接。以下查询返回输出,如下所示:

mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+---------------------+--------------+
| USER()            | CURRENT_USER()      | @@proxy_user |
+-------------------+---------------------+--------------+
| antonio@localhost | developer@localhost | ''@''        |
+-------------------+---------------------+--------------+

这 table 明对antonioos 用户进行了身份验证以具有授予developer MySQL 用户的特权,并且通过默认代理帐户进行了代理。

如果antonio不是root PAM 组的成员,而是users PAM 组的成员,则会发生类似的过程,但是该插件将user PAM 组成员资格 Map 到data_entry MySQL 用户名,并将该名称返回给服务器:

mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-------------------+----------------------+--------------+
| USER()            | CURRENT_USER()       | @@proxy_user |
+-------------------+----------------------+--------------+
| antonio@localhost | data_entry@localhost | ''@''        |
+-------------------+----------------------+--------------+

这 table 明antonioos 用户已通过身份验证,具有data_entry MySQL 用户的特权,并且通过默认代理帐户进行了代理。

Note

Client 端mysql_clear_password身份验证插件不会更改密码,因此 Client 端程序会将其以明文形式发送到 MySQL 服务器。这样可以将密码原样传递给 PAM。明文密码对于使用服务器端 PAM 库是必需的,但在某些配置中可能是安全问题。这些措施可最大程度地降低风险:

对 Unix 密码存储库的 PAM 身份验证访问

在某些系统上,Unix 身份验证使用诸如/etc/shadow之类的密码存储,该文件通常具有受限的访问权限。这可能导致基于 MySQL PAM 的身份验证失败。不幸的是,PAM 实施不允许将“无法检查密码”(例如,由于无法读取/etc/shadow)与“密码不匹配”区分开。如果您使用 Unix 密码存储进行 PAM 身份验证,则可以使用以下方法之一启用从 MySQL 对其的访问:

chgrp shadow /etc/shadow
chmod g+r /etc/shadow
chmod u-s /usr/sbin/unix_chkpwd
setcap cap_dac_read_search+ep /usr/sbin/unix_chkpwd

根据您的平台的需要,将路径调整为 unix_chkpwd **。

PAM 身份验证调试

PAM 身份验证插件在初始化时检查是否设置了AUTHENTICATION_PAM_LOG环境值(该值无关紧要)。如果是这样,则插件可以将诊断消息记录到标准输出中。这些消息可能有助于调试插件执行身份验证时发生的与 PAM 相关的问题。

一些消息包括对 PAM 插件源文件和行号的引用,这使插件操作可以更紧密地与代码中发生它们的位置相关联。

用于调试连接失败并确定在尝试连接期间发生了什么的另一种技术是将 PAM 身份验证配置为允许所有连接,然后检查系统日志文件。此技术应仅在“临时”基础上使用,而不应在生产服务器上使用。

使用以下内容配置名为/etc/pam.d/mysql-any-password的 PAM 服务文件(格式在某些系统上可能会有所不同):

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

创建一个使用 PAM 插件的帐户并命名mysql-any-password PAM 服务:

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

mysql-any-password服务文件会导致任何身份验证尝试返回 true,即使密码错误也是如此。如果身份验证尝试失败,则 table 明配置问题在 MySQL 方面。否则,问题出在 os/ PAM 端。要查看可能发生的情况,请检查/var/log/secure/var/log/audit.log/var/log/syslog/var/log/messages之类的系统日志文件。

确定问题出在哪里之后,请删除mysql-any-password PAM 服务文件以禁用任何密码访问。

首页