6.4.1.9 LDAP 可插拔身份验证

Note

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

从 MySQL 5.7.19 开始,MySQL Enterprise Edition 支持一种身份验证方法,该方法使 MySQL Server 可以通过访问目录服务(例如 X.500)使用 LDAP(轻型目录访问协议)来对 MySQL 用户进行身份验证。 MySQL 使用 LDAP 来获取用户,凭证和组信息。

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

下 table 显示了用于简单的基于 SASL 的 LDAP 身份验证的插件和库文件名。文件名后缀可能在您的系统上有所不同。这些文件必须位于plugin_dir系统变量命名的目录中。

table6.15 用于简单 LDAP 身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件名称 authentication_ldap_simple
Client 端插件名称 mysql_clear_password
库文件名 authentication_ldap_simple.so

table6.16 基于 SASL 的 LDAP 身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件名称 authentication_ldap_sasl
Client 端插件名称 authentication_ldap_sasl_client
库文件名 authentication_ldap_sasl.so , authentication_ldap_sasl_client.so

库文件仅包含authentication_ldap_XXX身份验证插件。Client 端mysql_clear_password插件内置在libmysqlclientClient 端库中。

每个服务器端 LDAP 插件均与特定的 Client 端插件一起使用:

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

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

Note

如果您的系统支持 PAM 并允许 LDAP 作为 PAM 身份验证方法,则将 LDAP 用于 MySQL 用户身份验证的另一种方法是使用服务器端authentication_pam插件。参见第 6.4.1.7 节“ PAM 可插入身份验证”

LDAP 可插入身份验证的先决条件

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

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

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

Client 端连接到 MySQL 服务器,并提供 MySQLClient 端用户名和 LDAP 密码:

如果 Client 端用户名和主机名不匹配任何 MySQL 帐户,则连接被拒绝。

如果存在匹配的 MySQL 帐户,则会针对 LDAP 进行身份验证。 LDAP 服务器查找与用户匹配的条目,并根据 LDAP 密码对条目进行身份验证:

如果 LDAP 服务器找不到匹配项或多个匹配项,则身份验证将失败并且 Client 端连接将被拒绝。

如果 LDAP 服务器找到单个匹配项,则 LDAP 身份验证成功(假设密码正确),LDAP 服务器返回 LDAP 条目,并且身份验证插件根据该条目确定经过身份验证的用户的名称:

MySQL 服务器将 Client 端用户名与经过身份验证的用户名进行比较,以确定 Client 端会话是否发生代理:

安装 LDAP 可插入身份验证

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

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

服务器端插件库文件的基本名称为authentication_ldap_simpleauthentication_ldap_sasl。文件名后缀因平台而异(例如,对于 Unix 和类 Unix 系统,为.so;对于 Windows,为.dll)。

要在服务器启动时加载插件,请使用--plugin-load-add选项命名包含它们的库文件。使用这种插件加载方法,每次服务器启动时必须给出选项。另外,为要配置的任何插件提供的系统变量指定值。

每个服务器端 LDAP 插件都公开了一组系统变量,这些变量可以对其操作进行配置。设置大多数选项是可选的,但是必须设置变量以指定 LDAP 服务器主机(以便插件知道连接的位置)和 LDAP 绑定操作的基础专有名称(以限制搜索范围并获得更快的搜索)。有关所有 LDAP 系统变量的详细信息,请参见第 6.4.1.13 节,“可插入身份验证系统变量”

要加载插件并为 LDAP 绑定操作设置 LDAP 服务器主机和基本专有名称,请在您的my.cnf文件中放入诸如此类的行,并根据需要调整平台的.so后缀:

[mysqld]
plugin-load-add=authentication_ldap_simple.so
authentication_ldap_simple_server_host=127.0.0.1
authentication_ldap_simple_bind_base_dn="dc=example,dc=com"
plugin-load-add=authentication_ldap_sasl.so
authentication_ldap_sasl_server_host=127.0.0.1
authentication_ldap_sasl_bind_base_dn="dc=example,dc=com"

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

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

INSTALL PLUGIN authentication_ldap_simple
  SONAME 'authentication_ldap_simple.so';
INSTALL PLUGIN authentication_ldap_sasl
  SONAME 'authentication_ldap_sasl.so';

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

在运行时安装插件后,它们的系统变量将变为可用,您可以将其设置添加到my.cnf文件中,以配置插件以供后续重启。例如:

[mysqld]
authentication_ldap_simple_server_host=127.0.0.1
authentication_ldap_simple_bind_base_dn="dc=example,dc=com"
authentication_ldap_sasl_server_host=127.0.0.1
authentication_ldap_sasl_bind_base_dn="dc=example,dc=com"

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

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

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
       FROM INFORMATION_SCHEMA.PLUGINS
       WHERE PLUGIN_NAME LIKE '%ldap%';
+----------------------------+---------------+
| PLUGIN_NAME                | PLUGIN_STATUS |
+----------------------------+---------------+
| authentication_ldap_sasl   | ACTIVE        |
| authentication_ldap_simple | ACTIVE        |
+----------------------------+---------------+

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

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

Additional Notes for SELinux

在启用了 SELinux 的运行 EL6 或 EL 的系统上,需要更改 SELinux 策略才能使 MySQL LDAP 插件与 LDAP 服务通信:

  • 创建具有以下内容的文件mysqlldap.te
module mysqlldap 1.0;

require {
type ldap_port_t;
type mysqld_t;
class tcp_socket name_connect;
}

#============= mysqld_t ==============

allow mysqld_t ldap_port_t:tcp_socket name_connect;
  • 将安全策略模块编译为二进制 table 示形式:
checkmodule -M -m mysqlldap.te -o mysqlldap.mod
  • 创建一个 SELinux 策略模块包:
semodule_package -m mysqlldap.mod  -o mysqlldap.pp
  • 安装模块包:
semodule -i mysqlldap.pp
  • 更改 SELinux 策略后,重新启动 MySQL 服务器:
service mysqld restart
卸载 LDAP 可插入身份验证

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

UNINSTALL PLUGIN authentication_ldap_simple;
UNINSTALL PLUGIN authentication_ldap_sasl;

此外,从my.cnf文件中删除所有设置 LDAP 插件相关系统变量的启动选项。

LDAP 可插拔身份验证和 ldap.conf

对于使用 OpenLDAP 的安装,ldap.conf文件为 LDAPClient 端提供全局默认值。可以在此文件中设置选项以影响 LDAPClient 端,包括 LDAP 身份验证插件。 OpenLDAP 按以下优先 Sequences 使用配置选项:

如果库的默认值或ldap.conf值未产生适当的选项值,则 LDAP 认证插件可能能够设置相关变量以直接影响 LDAP 配置。例如,LDAP 插件可以覆盖用于 TLS 配置的ldap.conf参数:系统变量可用于启用 TLS 和控制 CA 配置,例如用于简单 LDAP 认证的authentication_ldap_simple_tlsauthentication_ldap_simple_ca_path以及用于 SASL LDAP 认证的authentication_ldap_sasl_tlsauthentication_ldap_sasl_ca_path

有关ldap.conf的更多信息,请参见ldap.conf(5)手册页。

使用 LDAP 可插入身份验证

本节介绍如何使用 LDAP 可插入身份验证使 MySQL 帐户连接到 MySQL 服务器。如安装 LDAP 可插入身份验证所述,假定服务器正在启用适当的服务器端插件的情况下运行,并且 Client 端主机上提供了适当的 Client 端插件。

本节不介绍 LDAP 配置或 Management。假定您熟悉这些主题。

两个服务器端 LDAP 插件分别与特定的 Client 端插件一起使用:

MySQL 用户的 LDAP 身份验证的总体要求:

这里的说明假定以下情况:

uid=betsy_ldap,ou=People,dc=example,dc=com
uid=boris_ldap,ou=People,dc=example,dc=com

设置使用 LDAP 身份验证的帐户的说明取决于所使用的服务器端 LDAP 插件。以下各节描述了几种使用方案。

简单 LDAP 认证

要为简单的 LDAP 身份验证配置 MySQL 帐户,CREATE USER语句指定authentication_ldap_simple插件,并可以选择命名 LDAP 用户专有名称(DN):

CREATE USER user
  IDENTIFIED WITH authentication_ldap_simple
  [BY 'LDAP user DN'];

假设 MySQL 用户betsy在 LDAP 目录中具有以下条目:

uid=betsy_ldap,ou=People,dc=example,dc=com

然后为betsy创建 MySQL 帐户的语句如下所示:

CREATE USER 'betsy'@'localhost'
  IDENTIFIED WITH authentication_ldap_simple
  AS 'uid=betsy_ldap,ou=People,dc=example,dc=com';

BY子句中指定的认证字符串不包含 LDAP 密码。必须由 Client 端用户在连接时提供。

Client 端通过提供 MySQL 用户名和 LDAP 密码并启用 Client 端mysql_clear_password插件来连接到 MySQL 服务器:

shell> mysql --user=betsy --password --enable-cleartext-plugin
Enter password: betsy_password (betsy_ldap LDAP password)

Note

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

身份验证过程如下所示:

如果匹配的 LDAP 条目包含组属性,则该属性值将是经过身份验证的用户名,并且,如果该值与betsy不同,则将发生代理。有关使用 group 属性的示例,请参见LDAP 身份验证与代理

如果CREATE USER语句不包含BY子句以指定betsy_ldap LDAP 专有名称,则身份验证尝试将使用 Client 端提供的用户名(在本例中为betsy)。在没有betsy的 LDAP 条目的情况下,身份验证将失败。

基于 SASL 的 LDAP 身份验证

要为 MySQL 帐户配置 SASL LDAP 身份验证,CREATE USER语句指定authentication_ldap_sasl插件,并可以选择命名 LDAP 用户专有名称(DN):

CREATE USER user
  IDENTIFIED WITH authentication_ldap_sasl
  [BY 'LDAP user DN'];

假设 MySQL 用户boris在 LDAP 目录中具有以下条目:

uid=boris_ldap,ou=People,dc=example,dc=com

然后为boris创建 MySQL 帐户的语句如下所示:

CREATE USER 'boris'@'localhost'
  IDENTIFIED WITH authentication_ldap_sasl
  AS 'uid=boris_ldap,ou=People,dc=example,dc=com';

BY子句中指定的认证字符串不包含 LDAP 密码。必须由 Client 端用户在连接时提供。

Client 端通过提供 MySQL 用户名和 LDAP 密码连接到 MySQL 服务器:

shell> mysql --user=boris --password
Enter password: boris_password (boris_ldap LDAP password)

对于服务器端authentication_ldap_sasl插件,Client 端使用 Client 端authentication_ldap_sasl_client插件。如果 Client 端程序找不到 Client 端插件,请指定--plugin-dir选项,该选项将命名插件库文件的安装目录。

boris的身份验证过程与先前针对betsy的简单 LDAP 身份验证过程类似,不同之处在于 Client 端和服务器端 SASL LDAP 插件使用 SASL 消息在 LDAP 协议内安全传输凭据,以避免发送明文密码在 MySQLClient 端和服务器之间。

LDAP 身份验证与代理

LDAP 身份验证插件支持代理,使用户可以以一个用户身份连接到 MySQL 服务器,但可以承担其他用户的特权。本节介绍基本的 LDAP 插件代理支持。 LDAP 插件还支持组首选项和代理用户 Map 的规范。参见LDAP 身份验证组首选项和 Map 规范

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

这里的说明假定以下情况:

uid=basha,ou=People,dc=example,dc=com,cn=accounting
uid=basil,ou=People,dc=example,dc=com,cn=front_office

在连接时,组属性值成为经过身份验证的用户名,因此它们将命名为accountingfront_office代理帐户。

创建默认的代理 MySQL 帐户:

CREATE USER ''@'%'
  IDENTIFIED WITH authentication_ldap_sasl;

代理帐户定义没有用于命名 LDAP 用户 DN 的AS 'auth_string'子句。从而:

Note

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

创建代理帐户,并向每个帐户授予应具有的特权:

CREATE USER 'accounting'@'localhost'
  IDENTIFIED WITH mysql_no_login;
CREATE USER 'front_office'@'localhost'
  IDENTIFIED WITH mysql_no_login;

GRANT ALL PRIVILEGES
  ON accountingdb.*
  TO 'accounting'@'localhost';
GRANT ALL PRIVILEGES
  ON frontdb.*
  TO 'front_office'@'localhost';

代理帐户使用mysql_no_login身份验证插件来防止 Client 端使用帐户直接登录到 MySQL 服务器。相反,期望使用 LDAP 进行身份验证的用户将使用默认的''@'%'代理帐户。 (这假定已安装mysql_no_login插件.有关说明,请参阅第 6.4.1.10 节“无登录可插入身份验证”。)有关防止代理帐户直接使用的替代方法,请参阅防止直接登录到代理帐户

为代理帐户授予每个代理帐户的PROXY特权:

GRANT PROXY
  ON 'accounting'@'localhost'
  TO ''@'%';
GRANT PROXY
  ON 'front_office'@'localhost'
  TO ''@'%';

使用mysql命令行 Client 端以basha连接到 MySQL 服务器。

shell> mysql --user=basha --password
Enter password: basha_password (basha LDAP password)

身份验证如下:

uid=basha,ou=People,dc=example,dc=com,cn=accounting
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-----------------+----------------------+--------------+
| USER()          | CURRENT_USER()       | @@proxy_user |
+-----------------+----------------------+--------------+
| basha@localhost | accounting@localhost | ''@'%'       |
+-----------------+----------------------+--------------+

这 table 明basha使用授予代理accounting MySQL 帐户的特权,并且代理通过默认的代理用户帐户进行。

现在改为以basil的身份连接:

shell> mysql --user=basil --password
Enter password: basil_password (basil LDAP password)

basil的身份验证过程与先前针对basha所述的过程类似:

uid=basil,ou=People,dc=example,dc=com,cn=front_office
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-----------------+------------------------+--------------+
| USER()          | CURRENT_USER()         | @@proxy_user |
+-----------------+------------------------+--------------+
| basil@localhost | front_office@localhost | ''@'%'       |
+-----------------+------------------------+--------------+

这 table 明basil使用授予代理front_office MySQL 帐户的特权,并且代理通过默认的代理用户帐户进行。

LDAP 身份验证组首选项和 Map 规范

LDAP 身份验证与代理中所述,基本 LDAP 身份验证代理的工作原理是:插件使用 LDAP 服务器返回的第一个组名作为 MySQL 代理的用户帐户名。如果 LDAP 服务器返回多个组名,则此简单功能无法指定关于使用哪个组名的任何首选项,也不能指定除组名以外的任何名称作为代理用户名。

从 MySQL 5.7.25 开始,对于使用 LDAP 身份验证的 MySQL 帐户,身份验证字符串可以指定以下信息以实现更大的代理灵 Active:

考虑以下 MySQL 代理帐户定义:

CREATE USER ''@'%'
  IDENTIFIED WITH authentication_ldap_sasl
  AS '+ou=People,dc=example,dc=com#grp1=usera,grp2,grp3=userc';

验证字符串具有以+字符为前缀的用户 DN 后缀ou=People,dc=example,dc=com。因此,如LDAP 认证用户 DN 后缀中所述,完整的用户 DN 由指定的用户 DN 后缀加上 Client 端用户名作为uid属性构成。

认证字符串的其余部分以#开头,这 table 示组首选项和 Map 信息的开始。验证字符串的此部分按grp1grp2grp3的 Sequences 列出组名。 LDAP 插件将该列 table 与 LDAP 服务器返回的组名称集进行比较,并按列 tableSequences 查找与返回名称的匹配项。插件使用第一个匹配项,或者如果没有匹配项,则认证失败。

假设 LDAP 服务器返回组grp3grp2grp7。 LDAP 插件使用grp2,因为它是身份验证字符串中匹配的第一组,即使它不是 LDAP 服务器返回的第一组。如果 LDAP 服务器返回grp4grp2grp1,则即使grp2也匹配,插件也会使用grp1grp1的优先级高于grp2,因为它在身份验证字符串中列在较早的位置。

假设插件找到一个匹配的组名,它将执行从该组名到 MySQL 代理用户名的 Map。对于示例代理帐户,Map 如下所示:

如果 LDAP 服务器返回 DN 格式的组,则 LDAP 插件将解析组 DN,以从中提取组名。

要指定 LDAP 组首选项和 Map 信息,请遵循以下原则:

"my group name"="my user name"

如果某项的组名和用户名分别为my_group_namemy_user_name(不包含特殊字符),则可能但不必使用引号将其写入。以下任何一项均有效:

my_group_name=my_user_name
my_group_name="my_user_name"
"my_group_name"=my_user_name
"my_group_name"="my_user_name"
LDAP 认证用户 DN 后缀

从 MySQL 5.7.21 开始,LDAP 认证插件允许提供用户 DN 信息的认证字符串以+前缀字符开头:

此帐户身份验证字符串开头没有+,因此将其作为完整的用户 DN:

CREATE USER 'baldwin'
  IDENTIFIED WITH authentication_ldap_simple
  AS 'uid=admin,ou=People,dc=example,dc=com';

Client 端使用帐户(baldwin)中指定的用户名进行连接。在这种情况下,不使用该名称,因为身份验证字符串没有前缀,因此可以完全指定用户 DN。

此帐户身份验证字符串的开头确实有+,因此它被视为用户 DN 的一部分:

CREATE USER 'accounting'
  IDENTIFIED WITH authentication_ldap_simple
  AS '+ou=People,dc=example,dc=com';

Client 端使用帐户(accounting)中指定的用户名进行连接,在这种情况下,该用户名与验证字符串一起用作uid属性,以构造用户 DN:uid=accounting,ou=People,dc=example,dc=com

前面示例中的帐户具有非空用户名,因此 Client 端始终使用与帐户定义中指定的名称相同的名称连接到 MySQL 服务器。如果一个帐户具有空用户名,例如LDAP 身份验证与代理中描述的默认匿名''@'%'代理帐户,则 Client 端可能会使用不同的用户名连接到 MySQL 服务器。但是原理是相同的:如果认证字符串以+开头,则插件将使用 Client 端发送的用户名和认证字符串来构造用户 DN。

LDAP 身份验证方法

LDAP 认证插件使用可配置的认证方法。适当的系统变量和可用的方法选择是特定于插件的:

有关每个允许的方法的信息,请参见系统变量描述。

首页