MySQL8认证插件——PAM Pluggable Authentication

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

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

● 外部身份验证:PAM身份验证使MySQL Server能够接受来自MySQL授权表之外定义的用户的连接,并使用PAM支持的方法进行身份验证。

● 代理用户支持:PAM身份验证可以根据外部用户所属的PAM组和提供的身份验证字符串,向MySQL返回与客户端程序传递的外部用户名不同的用户名。这意味着插件可以返回MySQL用户,该用户定义了外部PAM身份验证用户应该拥有的权限。例如,一个名为joe的操作系统用户可以连接,并拥有名为developer的MySQL用户的权限。

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

插件和库名称

插件或文件

插件或文件名称

Server-side plugin

authentication_pam

Client-side plugin

mysql_clear_password

Library file

authentication_pam.so

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

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

1. 客户端程序和服务器进行通信,客户端向服务器发送客户端用户名(默认为操作系统用户名)和密码:

■ 客户端用户名是外部用户名。

■ 对于使用PAM服务器端身份验证插件的帐户,对应的客户端插件是 mysql_clear_password 这个客户端插件不执行密码散列,结果是客户端将密码作为明文发送到服务器。

2. 服务器根据外部用户名和客户端连接的主机找到匹配的MySQL帐户。PAM插件使用MySQL Server传递给它的信息(例如用户名、主机名、密码和身份验证字符串)。当您定义一个使用PAM进行身份验证的MySQL帐户时,身份验证字符串包含:

■ PAM服务名称,系统管理员可以使用该名称来引用特定应用程序的身份验证方法。可以有多个应用程序与单个数据库服务器实例关联,因此服务名称的选择留给SQL应用程序开发人员。

■ 可选地,如果要使用代理,则可以使用从PAM组到MySQL用户名的映射。

3. 该插件使用身份验证字符串中命名的PAM服务来检查用户凭据,并返回 'Authentication succeeded, Username is user_name' or 'Authentication failed' 密码必须适用于PAM服务使用的密码存储。示例:

■ 对于传统的Unix密码,该服务会查找存储在/etc/shadow文件中的密码。

■ 对于LDAP,该服务查找存储在LDAP目录中的密码。

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

4. 否则,身份验证字符串指示是否发生代理。如果字符串不包含PAM组映射,则不会发生代理。在这种情况下,MySQL用户名与外部用户名相同。

5. 否则,代理是基于PAM组映射来指示的,MySQL用户名是基于映射列表中的第一个匹配组来确定的。“PAM组”的含义取决于PAM服务。示例:

■ 对于传统的Unix密码,组是在/etc/group文件中定义的Unix组,可能在/etc/security/group.conf等文件中添加额外的PAM信息。

■ 对于LDAP,组是在LDAP目录中定义的LDAP组。

如果代理用户(外部用户)对被代理的MySQL用户名具有proxy权限,则会发生代理,代理用户将承担被代理用户的权限。

安装PAM可插拔身份验证

要供服务器使用,插件库文件必须位于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 系统表中,以使服务器在每次后续正常启动时加载它,而不需要 --plugin-load-add

要验证插件安装,请检查 Information Schema PLUGINS表或使用SHOW PLUGINS语句。例如:

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

如果插件无法初始化,请查看服务器错误日志中的诊断消息。

卸载PAM可插拔身份验证

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

● 如果您在服务器启动时使用 --plugin-load-add 选项安装了插件,请在不使用该选项的情况下重新启动服务器。

● 如果您在运行时使用 INSTALL PLUGIN 语句安装插件,那么它将在服务器重新启动时保持安装状态。要卸载它,请使用

UNINSTALL PLUGIN authentication_pam;

使用PAM可插拔身份验证

以下部分提供了以特定方式使用PAM身份验证的说明。假设服务器运行时启用了服务器端PAM插件

CREATE USER user IDENTIFIED WITH authentication_pam AS 'auth_string';

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

● PAM服务名称。以下讨论中的示例使用mysql-unix服务名称进行使用传统unix密码的身份验证,使用mysql-ldap进行使用ldap的身份验证。

● 对于代理支持,PAM为PAM模块提供了一种方法,使其在连接到服务器时向服务器返回MySQL用户名,而不是客户端程序传递的外部用户名。使用身份验证字符串来控制从外部用户名到MySQL用户名的映射。如果您想利用代理用户功能,身份验证字符串必须包括这种映射。

例如,如果一个帐户使用 mysql-unix PAM服务名称,并且应该将 root 和 users PAM 组中的操作系统用户分别映射到 developer 和 data_entry MySQL用户,请使用这样的语句:

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

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

● 该字符串由一个PAM服务名称组成,后面可选地跟有一个PAM组映射列表,该列表由一个或多个关键字/值对组成,每个关键字/值都指定PAM组名称和MySQL用户名:

pam_service_name[,pam_group_name=mysql_user_name] . . .

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

● 每个 pam_group_name=mysql_user_name 对的前面都必须有一个逗号。

● 不在双引号内的前导空格和尾随空格将被忽略。

● 不在双引号中的 pam_service_name, pam_group_name, and mysql_user_name 值可以包含除等号、逗号或空格之外的任何内容。

● 如果用双引号引起来的 pam_service_name, pam_group_name, or mysql_user_name 值,则引号之间的所有内容都是该值的一部分。例如,如果值包含空格字符,则这是必要的。除双引号和反斜杠(\)外,所有字符都是合法的。若要包含双引号和反斜杠(\),请使用反斜杠对其进行转义。

如果插件成功验证了外部用户名(客户端传递的名称),它会在验证字符串中查找PAM组映射列表,如果存在,则使用该列表向MySQL服务器返回不同的MySQL用户名,基于外部用户是哪个PAM组的成员:

● 如果身份验证字符串不包含PAM组映射列表,则插件将返回外部名称。

● 如果身份验证字符串确实包含PAM组映射列表,则插件会从左到右检查列表中的每个 pam_group_name=mysql_user_name 对,并尝试在认证用户的组的非mysql目录中查找 pam_group_name 值的匹配项,并为找到的第一个匹配项返回 mysql_user_name 。如果插件找不到任何PAM组的匹配项,则返回外部名称。如果插件无法在目录中查找组,它将忽略PAM组映射列表并返回外部名称。

以下部分描述了如何设置几个使用PAM身份验证插件的身份验证场景:

● 没有代理用户。只使用PAM来检查登录名和密码。每个被允许连接到MySQL Server的外部用户都应该有一个匹配的MySQL帐户,该帐户被定义为使用PAM身份验证。(对于'user_name'@'host_name'的MySQL帐户,要与外部用户匹配,user_name必须是外部用户名,host_name必须与客户端连接的主机匹配。)身份验证可以通过各种PAM支持的方法执行。

如果不是通过代理用户或PAM组进行PAM身份验证,则要求MySQL用户名与操作系统用户名相同。MySQL用户名限制为32个字符,这将PAM非代理身份验证限制为名称最多32个字符的Unix帐户。

● 仅限代理用户,带有PAM组映射。对于这种情况,请创建一个或多个MySQL帐户,这些帐户定义不同的权限集。(理想情况下,任何人都不应该直接使用这些帐户进行连接。)然后定义一个通过PAM进行身份验证的默认用户,该用户使用一些映射方案(通常基于用户所属的外部PAM组)将所有外部用户名映射到持有特权集的少数MySQL帐户。任何连接并指定外部用户名作为客户端用户名的客户端都会映射到其中一个MySQL帐户并使用其权限。

这些情况可能会发生变化:

● 您可以允许一些用户直接登录(无需代理),但要求其他用户通过代理帐户进行连接。

● 通过在经过PAM身份验证的帐户中使用不同的PAM服务名称,您可以对某些用户使用一种验证方法,对其他用户使用另一种方法。例如,您可以为一些用户使用 mysql-unix PAM服务,为其他用户使用mysql-ldap PAM服务。

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

● 登录名和密码分别是 pamuser 和 pamuser_password 将这些更改为与要进行身份验证的用户相对应。

● PAM配置目录为 /etc/pam.d.

● PAM服务名称对应于身份验证方法(本讨论中为 mysql-unix 或 mysql-ldap )。要使用给定的PAM服务,必须在PAM配置目录中设置一个同名的PAM文件(如果不存在,则创建该文件)。此外,对于使用PAM服务进行身份验证的任何帐户,必须在CREATE USER语句的身份验证字符串中命名PAM服务。

PAM身份验证插件在初始化时检查是否在服务器的启动环境中设置了 AUTHENTICATION_PAM_LOG 环境值。如果是这样,该插件将允许将诊断消息记录到标准输出中。根据服务器的启动方式,该消息可能会出现在控制台或错误日志中。这些消息有助于调试插件执行身份验证时出现的与PAM相关的问题。

无代理用户的PAM Unix密码身份验证

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

1. 验证Unix身份验证是否允许使用用户名 pamuser 和密码 pamuser_password 登录操作系统。

2. 通过创建一个名为 /etc/pam.d/mysql-unix 的 mysql-unix PAM 服务文件,设置PAM以使用传统的Unix密码验证MySQL连接。文件内容取决于系统,因此请检查 /etc/pam.d 目录中现有的与登录相关的文件,看看它们是什么样子。在Linux上,mysql-unix 文件可能如下所示:

#%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

3. 创建一个用户名与操作系统用户名相同的MySQL帐户,并将其定义为使用PAM插件和 mysql-unix PAM 服务进行身份验证:

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

这里,身份验证字符串只包含PAM服务名称, mysql-unix, 用于验证unix密码。

4. 使用 mysql 命令行客户端以 pamuser 的身份连接到 mysql 服务器。例如:

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

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

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

这表明pamuser操作系统用户已通过身份验证,具有授予pamuser MySQL用户的权限,并且没有发生代理。

说明:

客户端 mysql_clear_password 身份验证插件保持密码不变,因此客户端程序将其作为明文发送到mysql服务器。这使得密码可以按原样传递给PAM。明文密码是使用服务器端PAM库所必需的,但在某些配置中可能存在安全问题。这些措施将风险降至最低:

● 为了减少意外使用 mysql_clear_password 插件的可能性,mysql客户端必须显式启用它(例如,使用 --enable-cleartext-plugin 插件选项)。

● 为了避免在启用 mysql_clear_password 插件的情况下暴露密码,mysql客户端应使用加密连接连接到mysql服务器。

无代理用户的PAM LDAP身份验证

此身份验证场景使用PAM检查根据操作系统用户名和LDAP密码定义的外部用户,而无需代理。每个被允许连接到MySQL Server的外部用户都应该有一个匹配的MySQL帐户,该帐户被定义为通过LDAP使用PAM身份验证。

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

● LDAP服务器必须可用于PAM LDAP服务进行通信。

● 每个要通过MySQL进行身份验证的LDAP用户都必须存在于LDAP服务器管理的目录中。

说明: 使用LDAP进行MySQL用户身份验证的另一种方法是使用LDAP特定的身份验证插件。

为PAM LDAP身份验证配置MySQL,如下所示:

1. 验证Unix身份验证是否允许使用用户名pamuser和密码pamuser_password登录操作系统。

2. 通过创建一个名为/ /etc/pam.d/mysql-ldap 的 mysql-ldap PAM 服务文件,设置PAM认证使用LDAP验证的MySQL连接。该文件的内容取决于系统,因此请检查 /etc/pam.d 目录中现有的与登录相关的文件,看看它们是什么样子。在Linux上,mysql-ldap文件可能如下所示:

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

如果PAM对象文件的后缀与系统上的.so不同,请替换正确的后缀。PAM文件格式在某些系统上可能有所不同。

3. 创建一个用户名与操作系统用户名相同的MySQL帐户,并将其定义为使用PAM插件和 mysql-ldap PAM 服务进行身份验证:

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

这里,身份验证字符串只包含PAM服务名称, mysql-ldap, 它使用ldap进行身份验证。

4. 连接到服务器 "无代理用户的PAM Unix密码身份验证" 中描述的相同。

使用代理用户和组映射进行PAM Unix密码验证

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

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

1. 验证Unix身份验证是否允许使用用户名 pamuser 和密码 pamuser_password 登录操作系统。

2. 验证 pamuser 是否是 root 或 users PAM组的成员。

3. 通过创建一个名为 /etc/pam.d/mysql-unix 的文件,设置PAM以通过操作系统用户对 mysql-unix PAM 服务进行身份验证。文件内容取决于系统,因此请检查/etc/PAM.d目录中现有的与登录相关的文件,看看它们是什么样子的。在Linux上,mysql-unix文件可能如下所示:

#%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

4. 创建一个默认代理用户((''@'') ,将外部PAM用户映射到代理帐户:

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

这里,身份验证字符串包含PAM服务名称, mysql-unix, 用于验证unix密码。身份验证字符串还将 root 组和 users PAM组中的外部用户分别映射到 developer 和 data_entry MySQL用户名。

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

说明: 如果MySQL安装有匿名用户,他们可能与默认代理用户冲突。

5. 创建代理帐户并授予每个帐户应有的权限:

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 身份验证插件来防止客户端使用这些帐户直接登录mysql服务器。相反,使用PAM进行身份验证的用户应该根据其PAM组通过代理使用 developer或 data_entry 帐户。

6. 为代理帐户授予每个代理帐户的代理权限:

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

7. 使用mysql命令行客户端以pamuser的身份连接到mysql服务器。

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

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

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

这表明 pamuser 操作系统用户已通过身份验证,具有授予 developer MySQL用户的权限,并且代理是通过默认代理帐户进行的。

如果 pamuser 不是 root PAM组的成员,而是 users PAM组的一员,则会发生类似的过程,但插件会将 users PAM组成员身份映射到 data_entry MySQL用户名,并将该名称返回给服务器:

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

这表明 pamuser 操作系统用户已通过身份验证,具有 data_entry MySQL用户的权限,并且代理是通过默认代理帐户进行的。

说明:

客户端mysql_clear_password身份验证插件保持密码不变,因此客户端程序将其作为明文发送到mysql服务器。这使得密码可以按原样传递给PAM。明文密码是使用服务器端PAM库所必需的,但在某些配置中可能存在安全问题。这些措施将风险降至最低:

● 为了减少意外使用 mysql_clear_password 插件的可能性,mysql客户端必须显式启用它(例如,使用 --enable-cleartext-plugin 插件选项)。

● 为了避免在启用 mysql_clear_password 插件的情况下暴露密码,mysql客户端应使用加密连接连接到mysql服务器。

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

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

● 假设MySQL服务器是从 mysql 操作系统帐户运行的,请将该帐户放在具有/etc/shadow访问权限的shadow组中:

a. 在 /etc/group 中创建一个 shadow 组。

b. 将 mysql 操作系统用户添加到 /etc/group 中的 shadow 组中。

c. 将 /etc/group 分配给 shadow 组并启用组读取权限:

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

d. 重新启动MySQL服务器。

● 如果您使用的是pam_unix模块和unix_chkpwd实用程序,请按如下方式启用密码存储访问:

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

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

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

mysql-any-password 服务文件会导致任何身份验证尝试返回true,即使是不正确的密码。如果身份验证尝试失败,那么告诉配置问题在MySQL端。否则,问题出在操作系统/PAM方面。要查看可能发生的情况,请检查系统日志文件,如 /var/log/secure, /var/log/audit.log, /var/log/syslog, or /var/log/messages

确定问题所在后,删除 mysql-any-password PAM服务文件以禁用任意密码访问。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贺浦力特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值