MySQL8认证插件—LDAP Pluggable Authentication

MySQL8认证插件—LDAP Pluggable Authentication

原创2023-05-05 19:00·贺浦力特

MySQL Enterprise Edition支持一种身份验证方法,使MySQL Server能够使用LDAP(轻量级目录访问协议)通过访问X.500等目录服务来对MySQL用户进行身份验证。MySQL使用LDAP来获取用户、凭据和组信息。

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

● 外部身份验证:LDAP身份验证使MySQL Server能够接受来自LDAP目录中MySQL授权表之外定义的用户的连接。

● 代理用户支持:LDAP身份验证可以根据外部用户所属的LDAP组,向MySQL返回与客户端程序传递的外部用户名不同的用户名。这意味着LDAP插件可以返回MySQL用户,该用户定义了经过LDAP身份验证的外部用户应该拥有的权限。例如,如果joe的LDAP组是developer,那么名为joe的LDAP用户可以连接并拥有名为developer的MySQL用户的权限。

● 安全性:使用TLS,到LDAP服务器的连接可以是安全的。

服务器和客户端插件可用于简单的基于SASL的LDAP身份验证。在Microsoft Windows上,不支持基于SASL的LDAP身份验证的服务器插件,但支持客户端插件。

插件和库名称(用于简单LDAP身份验证的插件和库名称)

插件或文件

插件或文件名称

Server-side plugin

扫描二维码关注公众号,回复: 15499210 查看本文章

authentication_ldap_simple

Client-side plugin

mysql_clear_password

Library file

authentication_ldap_simple.so

插件和库名称(用于基于SASL的LDAP身份验证的插件和库名称)

插件或文件

插件或文件名称

Server-side plugin

authentication_ldap_sasl

Client-side plugin

authentication_ldap_sasl_client

Library file

authentication_ldap_sasl.so, authentication_ldap_sasl_client.so

库文件仅包括authentication_ldap_XXX身份验证插件。客户端mysql_clear_password插件内置于libmysqlclient客户端库中。

每个服务器端LDAP插件都与特定的客户端插件配合使用:

● 服务器端
authentication_ldap_simple 插件执行简单的ldap身份验证。对于使用此插件的帐户的连接,客户端程序使用客户端 mysql_clear_password 插件,该插件将密码作为明文发送到服务器。不使用密码哈希或加密,因此建议在MySQL客户端和服务器之间建立安全连接,以防止密码泄露。

● 服务器端 authentication_ldap_sasl 插件执行基于sasl的ldap身份验证。对于使用此插件的帐户的连接,客户端程序使用客户端
authentication_ldap_sasl_client 插件。客户端和服务器端SASL LDAP插件使用SASL消息在LDAP协议内安全传输凭据,以避免在MySQL客户端和服务器之间发送明文密码。

服务器端LDAP身份验证插件仅包含在MySQL Enterprise Edition中。MySQL社区发行版中没有包含它们。客户端SASL LDAP插件包含在所有发行版中,包括社区发行版。如前所述,客户端mysql_clear_password插件内置在libmysqlclient客户端库中,该库也包含在所有分发版中。这使得来自任何分发版的客户端都可以连接到加载了适当服务器端插件的服务器。

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

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

● LDAP服务器必须可用于LDAP身份验证插件进行通信。

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

● LDAP客户端库必须在使用服务器端aauthentication_ldap_sasl 或
authentication_ldap_simple 插件的系统上可用。目前,支持的库是Windows本机LDAP库,或非Windows系统上的OpenLDAP库。

● 要使用基于SASL的LDAP身份验证:

■ LDAP服务器必须配置为与SASL服务器通信。

■ SASL客户端库必须在使用客户端
authentication_ldap_sasl_client 插件的系统上可用。目前,唯一受支持的库是Cyrus SASL库。

■ 要使用特定的SASL身份验证方法,该方法所需的任何其他服务都必须可用。例如,要使用GSSAPI/Kerberos,GSSAPI库和Kerberos服务必须可用。

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

客户端连接到MySQL服务器,提供MySQL客户端用户名和密码:

● 对于简单的LDAP身份验证,客户端和服务器端插件将密码作为明文进行通信。建议在MySQL客户端和服务器之间建立安全连接,以防止密码泄露。

● 对于基于SASL的LDAP身份验证,客户端和服务器端插件避免在MySQL客户端和服务器之间发送明文密码。例如,插件可能使用SASL消息在LDAP协议中安全传输凭据。对于GSSAPI身份验证方法,客户端和服务器端插件使用Kerberos进行安全通信,而不直接使用LDAP消息。

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

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

● 如果MySQL帐户命名LDAP用户 DN,则LDAP身份验证将使用该值和客户端提供的LDAP密码。(要将LDAP用户DN与MySQL帐户关联,请在创建帐户的CREATE user语句中包含一个BY子句,该子句指定身份验证字符串。)

● 如果MySQL帐户没有命名LDAP用户DN,则LDAP身份验证将使用客户端提供的用户名和LDAP密码。在这种情况下,身份验证插件首先使用 root DN和密码作为凭据绑定到LDAP服务器,以根据客户端用户名查找用户DN,然后根据LDAP密码验证该用户DN。如果 root DN和密码设置为不正确的值,或者为空(未设置),并且LDAP服务器不允许匿名连接,则使用 root 凭据的绑定将失败。

如果LDAP服务器没有找到匹配项或多个匹配项,则身份验证失败,客户端连接被拒绝。

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

● 如果LDAP条目具有group属性(默认情况下为cn属性),则插件会将其值作为经过身份验证的用户名返回。

● 如果LDAP条目没有组属性,则身份验证插件将客户端用户名作为已验证的用户名返回。

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

● 如果名称相同,则不会发生代理:与客户端用户名匹配的MySQL帐户用于权限检查。

● 如果名称不同,就会发生代理:MySQL会查找与经过身份验证的用户名匹配的帐户。该帐户成为代理用户,用于权限检查。与客户端用户名匹配的MySQL帐户将被视为外部代理用户。

安装LDAP可插拔身份验证

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

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

说明: 在Microsoft Windows上,不支持基于SASL的LDAP身份验证的服务器插件,但支持客户端插件。在其他平台上,同时支持服务器和客户端插件。

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

每个服务器端LDAP插件都公开了一组系统变量,这些变量可以配置其操作。设置其中大部分是可选的,但必须设置指定LDAP服务器主机(以便插件知道连接位置)和LDAP绑定操作的基本DN的变量(以限制搜索范围并获得更快的搜索)。

要加载插件并为LDAP绑定操作设置LDAP服务器主机和基本DN,请在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系统表中,以使服务器在每次后续正常启动时加载它,而不需要 --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后,重新启动服务器以使新设置生效。

要在运行时而不是启动时设置并保持每个值,请使用以下语句:

SET PERSIST authentication_ldap_simple_server_host='127.0.0.1';
SET PERSIST authentication_ldap_simple_bind_base_dn='dc=example,dc=com';
SET PERSIST authentication_ldap_sasl_server_host='127.0.0.1';
SET PERSIST authentication_ldap_sasl_bind_base_dn='dc=example,dc=com';

SET PERSIST为正在运行的MySQL实例设置一个值。它还保存了该值,从而将其转移到随后的服务器重新启动中。要更改正在运行的MySQL实例的值而不将其转移到后续的重新启动,请使用GLOBAL关键字而不是PERSIST。

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

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 |
+----------------------------+---------------+

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

SELinux的附加说明

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

1. 创建一个包含以下内容的文件 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;

2. 将安全策略模块编译为二进制表示形式:

checkmodule -M -m mysqlldap.te -o mysqlldap.mod

3. 创建SELinux策略模块包:

semodule_package -m mysqlldap.mod -o mysqlldap.pp

4. 安装模块包:

semodule -i mysqlldap.pp

5. 当SELinux策略发生更改后,重新启动MySQL服务器:

service mysqld restart

卸载LDAP可插入身份验证

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

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

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

UNINSTALL PLUGIN authentication_ldap_simple;
UNINSTALL PLUGIN authentication_ldap_sasl;

此外,从my.cnf文件中删除任何设置LDAP插件相关系统变量的启动选项。如果使用SET PERSIST保留LDAP系统变量,请使用RESET PERSIST删除设置。

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

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

● LDAP客户端指定的配置。

● ldap.conf文件中指定的配置。要禁用此文件的使用,请设置 LDAPNOINIT 环境变量。

● OpenLDAP库内置默认值。

如果库默认值或ldap.conf值没有产生适当的选项值,ldap身份验证插件可能能够设置相关变量以直接影响ldap配置。例如,LDAP插件可以为以下参数重写 ldap.conf:

● TLS配置:系统变量可用于启用TLS和控制CA配置,例如用于简单ldap身份验证的
authentication_ldap_simple_tls 和 authentication_ldap_simple_ca_path,以及用于 SASL LDAP 身份验证的 authentication_ldap_sasl_tls 和authentication_ldap_sasl_ca_path

● LDAP引用。

使用LDAP可插拔身份验证

两个服务器端LDAP插件分别与一个特定的客户端插件配合使用:

● 服务器端
authentication_ldap_simple 插件执行简单的ldap身份验证。对于使用此插件的帐户的连接,客户端程序使用客户端mysql_clear_password插件,该插件将密码作为明文发送到服务器。不使用密码哈希或加密,因此建议在MySQL客户端和服务器之间建立安全连接,以防止密码泄露。

● 服务器端 authentication_ldap_sasl 插件执行基于sasl的ldap身份验证。对于使用此插件的帐户的连接,客户端程序使用客户端
authentication_ldap_sasl_client 插件。客户端和服务器端SASL LDAP插件使用SASL消息在LDAP协议内安全传输凭据,以避免在MySQL客户端和服务器之间发送明文密码。

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

● 每个要进行身份验证的用户都必须有一个LDAP目录条目。

● 必须有一个MySQL用户帐户,该帐户指定服务器端LDAP身份验证插件,并可以选择命名关联的LDAP用户DN。(要将LDAP用户DN与MySQL帐户关联,请在创建帐户的CREATE user语句中包含BY子句。)如果帐户没有命名LDAP字符串,则LDAP身份验证将使用客户端指定的用户名来查找LDAP条目。

● 客户端程序使用适用于MySQL帐户使用的服务器端身份验证插件的连接方法进行连接。对于LDAP身份验证,连接需要MySQL用户名和LDAP密码。此外,对于使用服务器端
authentication_ldap_simple 插件的帐户,使用 --enable-cleartext-plugin 选项调用客户端程序,以启用客户端 mysql_clear_password 插件。

此处的说明假设出现以下情况:

● MySQL用户 betsy 和 boris 分别对 betsy_LDAP 和 boris_LDAP 的LDAP条目进行身份验证。(MySQL和LDAP用户名没有必要不同。在本讨论中使用不同的名称有助于澄清操作上下文是MySQL还是LDAP)

● LDAP条目使用uid属性来指定用户名。这可能因LDAP服务器而异。有些LDAP服务器使用cn属性作为用户名,而不是uid。要更改属性,请适当修改
authentication_ldap_simple_user_search_attr 或 authentication_ldap_sasl_user_search_attr 系统变量。

● 这些LDAP条目在LDAP服务器管理的目录中可用,以提供唯一标识每个用户的可分辨名称值:

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

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

● 创建MySQL帐户的CREATE USER语句在BY子句中命名LDAP用户,以指示MySQL帐户要针对哪个LDAP条目进行身份验证。

设置使用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密码。必须由客户端用户在连接时提供。

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

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

为了减少意外使用mysql_clear_password插件的可能性,mysql客户端必须显式启用它。这可以通过以下几种方式实现:

● 将
LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN 环境变量设置为以1、Y或Y开头的值。这将为所有客户端连接启用插件。

● mysql、mysqladmin、mysqlcheck、mysqldump、mysqlshow和mysqlslap客户端程序支持 --enable-cleartext-plugin 插件选项,该选项在每次调用的基础上启用插件。

● mysql_options() C API函数支持一个
MYSQL_ENABLE_CLEARTEXT_PLUGIN 选项,该选项在每个连接的基础上启用插件。此外,任何使用 libmysqlclient 并读取选项文件的程序都可以通过在客户端库读取的选项组中包含 enable-cleartext-plugin 插件选项来启用插件。

身份验证过程如下所示:

1. 客户端插件将 betsy 和 betsy_password 作为客户端用户名和LDAP密码发送到MySQL服务器。

2. 连接尝试与 'betsy'@'localhost' 帐户匹配。服务器端LDAP插件发现此帐户有一个身份验证字符串 'uid=betsy_ldap,ou=People,dc=example,dc=com' 来命名LDAP用户DN。插件将此字符串和LDAP密码发送到LDAP服务器。

3. LDAP服务器找到 betsy_ldap 的LDAP条目,并且密码匹配,因此LDAP身份验证成功。

4. LDAP条目没有group属性,因此服务器端插件返回客户端用户名(betsy)作为经过身份验证的用户。这与客户端提供的用户名相同,因此不会发生代理,并且客户端会话使用 'betsy'@'localhost' 帐户进行权限检查。

如果匹配的LDAP条目包含一个组属性,则该属性值将是经过身份验证的用户名,如果该值与betsy不同,则会发生代理。

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

基于SASL的LDAP身份验证

要为SASL LDAP身份验证配置MySQL帐户,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密码。必须由客户端用户在连接时提供。

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

mysql --user=boris --password

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

boris 的身份验证过程与之前描述的 betsy 的简单LDAP身份验证过程类似,只是客户端和服务器端 SASL LDAP 插件使用SASL消息在LDAP协议内安全传输凭据,以避免在MySQL客户端和服务器之间发送明文密码。

带代理的LDAP身份验证

此处的说明假设出现以下情况:

● LDAP条目使用uid和cn属性分别指定用户名和组值。要使用不同的用户和组属性名称,请设置相应的插件特定系统变量:

■ 对于
authentication_ldap_simple 插件:设置 authentication_ldap_simple_user_search_attr 和 authentication_ldap_simple_group_search_attr

■ 对于 authentication_ldap_sasl 插件:设置
authentication_ldap_sasl_user_search_attr 和 authentication_ldap_sasl_group_search_attr.

● 这些LDAP条目在LDAP服务器管理的目录中可用,以提供唯一标识每个用户的DN值:

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

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

● 这些示例假设使用SASL LDAP身份验证。如果是简单的LDAP身份验证需要进行适当的调整。

创建默认的代理MySQL帐户:

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

代理帐户定义没有AS“'auth_string'子句来命名LDAP用户DN。因此:

● 当客户端连接时,客户端用户名将成为要搜索的LDAP用户名。

● 匹配的LDAP条目应包括一个组属性,该属性命名代理的MySQL帐户,定义客户端应具有的权限。

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

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

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

代理帐户使用mysql_no_login身份验证插件来防止客户端使用这些帐户直接登录mysql服务器。相反,使用LDAP进行身份验证的用户应该使用默认的 ''@'%' 代理帐户。

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

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

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

mysql --user=basha --password

身份验证如下所示:

1. 服务器使用客户端用户 basha 的默认 ''@'%' 代理帐户对连接进行身份验证。

2. 匹配的LDAP条目为:

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

3. 匹配的LDAP条目具有组属性 cn=accounting,因此 accounting 成为经过身份验证的代理用户。

4. 经过身份验证的用户与客户端用户名 basha 不同,因此 basha 被视为记帐的代理,并且 basha 拥有代理记帐帐户的权限。以下查询返回输出,如图所示:

SELECT USER(), CURRENT_USER(), @@proxy_user;
+-----------------+----------------------+--------------+
| USER() | CURRENT_USER() | @@proxy_user |
+-----------------+----------------------+--------------+
| basha@localhost | accounting@localhost | ''@'%' |
+-----------------+----------------------+--------------+

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

现在使用 basil 连接:

mysql --user=basil --password

basil 的身份验证过程与前面描述的 basha 类似:

1. 服务器使用客户端用户 basil 的默认 ''@'%'”代理帐户对连接进行身份验证。

2. 匹配的LDAP条目为:

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

3. 匹配的LDAP条目具有组属性 cn=front_office,因此 front_officee 成为经过身份验证的代理用户。

4. 经过身份验证的用户与客户端用户名 basil 不同,因此 basil 被视为 front_office 的代理,并且 basil 拥有被代理的 front_office 帐户的权限。以下查询返回输出,如图所示:

SELECT USER(), CURRENT_USER(), @@proxy_user;
+-----------------+------------------------+--------------+
| USER() | CURRENT_USER() | @@proxy_user |
+-----------------+------------------------+--------------+
| basil@localhost | front_office@localhost | ''@'%' |
+-----------------+------------------------+--------------+

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

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

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

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

● 按首选项顺序排列的组列表,以便插件使用列表中与LDAP服务器返回的组匹配的第一个组名。

● 从组名到代理用户名的映射,这样匹配的组名可以提供指定的名称用作代理用户。这提供了将组名用作代理用户的替代方法。

请考虑以下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后缀加上作为uid属性的客户端用户名构成的。

身份验证字符串的其余部分以#开头,这表示组首选项和映射信息的开始。身份验证字符串的这一部分按grp1、grp2、grp3的顺序列出组名。LDAP插件将该列表与LDAP服务器返回的组名集进行比较,按照列表顺序查找与返回名称的匹配项。插件使用第一个匹配项,或者如果没有匹配项,则身份验证失败。

假设LDAP服务器返回组grp3、grp2和grp7。LDAP插件使用grp2,因为它是身份验证字符串中第一个匹配的组,即使它不是LDAP服务器返回的第一个组。如果LDAP服务器返回grp4、grp2和grp1,则即使grp2也匹配,插件也会使用grp1。grp1的优先级高于grp2,因为它在身份验证字符串中较早列出。

假设插件找到一个组名匹配,它会执行从该组名到MySQL代理用户名的映射(如果有)。对于代理帐户示例,映射如下所示:

● 如果匹配的组名是grp1或grp3,则它们在身份验证字符串中分别与用户名usera和userc相关联。插件使用相应的关联用户名作为代理用户名。

● 如果匹配的组名是grp2,则身份验证字符串中没有关联的用户名。该插件使用grp2作为代理用户名。

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

要指定LDAP组首选项和映射信息,请应用以下原则:

● 以#前缀字符开始身份验证字符串的组首选项和映射部分。

● 组首选项和映射规范是一个或多个项目的列表,用逗号分隔。每个项目的形式为group_name=user_name或group_name。项目应按组名称首选项顺序列出。对于插件从LDAP服务器返回的组名集合中选择的组名作为匹配项,这两种语法的效果不同如下:

■ 对于指定为group_name=user_name(带用户名)的项目,组名映射到用户名,该用户名用作MySQL代理的用户名。

■ 对于指定为group_name(没有用户名)的项目,组名将用作MySQL代理的用户名。

● 若要引用包含空格等特殊字符的组或用户名,请用双引号将其括起来。例如,如果项目的组和用户名为 my group name 和 my 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"
"my_group_name"=my_user_name
"my_group_name"="my_user_name"

● 若要对字符进行转义,请在其前面加一个反斜杠(\)。这对于包含字面上的双引号或反斜杠特别有用,否则这些内容就不会包含在字面上。

● 用户DN不需要存在于身份验证字符串中,但如果存在,则必须位于组首选项和映射部分之前。用户DN可以是完整的用户DN,也可以是带有+前缀字符的用户DN后缀。

LDAP身份验证用户DN后缀

LDAP身份验证插件允许提供用户DN信息的身份验证字符串以+前缀字符开头:

● 在没有+字符的情况下,将按原样处理身份验证字符串值,而不进行修改。

● 如果身份验证字符串以+开头,则插件将根据客户端发送的用户名以及身份验证字符串中指定的DN(去掉+)来构造完整的用户DN值。在构造的DN中,客户端用户名成为指定LDAP用户名的属性的值。默认情况下,这是uid;要更改属性,请修改相应的系统变量(
authentication_ldap_simple_user_search_attr 或 authentication_rdap_sasl_user_search_aattr)。身份验证字符串存储在mysql.user系统表中,在身份验证之前动态构建完整的用户DN。

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

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

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

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

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

客户端连接到帐户(accounting)中指定的用户名,在本例中,该用户名与身份验证字符串一起用作uid属性,以构造用户DN: uid=accounting,ou=People,dc=example,dc=com

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

LDAP身份验证方法

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

● 对于
authentication_ldap_simple 插件:设置 authentication_ldap_simple_auth_method_name 系统变量来配置该方法。允许的选择是 SIMPLE 和 AD-FOREST。

● 对于 authentication_ldap_sasl 插件:设置
authentication_rdap_sasl_auth_method_name 系统变量来配置该方法。允许的选择包括 SCRAM-SHA-1、SCRAM-SHA-256和GSSAPI。(要确定主机系统上实际可用的SASL LDAP方法,请检查 Authentication_ldap_sasl_supported_methods 状态变量的值。)

有关每种允许的方法的信息,请参阅系统变量描述。此外,根据方法的不同,可能需要额外的配置,如以下部分所述。

GSSAPI/Kerberos身份验证方法

通用安全服务应用程序接口(Generic Security Service Application Program Interface : GSSAPI)是一个安全抽象接口。Kerberos是可以通过该抽象接口使用的特定安全协议的实例。使用GSSAPI,应用程序通过Kerberos进行身份验证以获得服务凭据,然后依次使用这些凭据来实现对其他服务的安全访问。

其中一种服务是LDAP,它由客户端和服务器端SASL LDAP身份验证插件使用。当
authentication_ldap_sasl_auth_method_name 系统变量设置为GSSAPI时,这些插件使用GSSAPI/Kerberos身份验证方法。在这种情况下,插件使用Kerberos进行安全通信,而不直接使用LDAP消息。然后,服务器端插件与LDAP服务器通信,以解释LDAP身份验证消息并检索LDAP组。

支持GSSAPI/Kerberos作为Linux上MySQL服务器和客户端的LDAP身份验证方法。它在Linux环境中很有用,在Linux环境下,应用程序可以通过默认启用Kerberos的Microsoft Active Directory访问LDAP。

以下讨论提供了有关使用GSSAPI方法的配置要求的信息。假定熟悉Kerberos的概念和操作。以下列表简要定义了几个常见的Kerberos术语。您也可能会发现RFC 4120的术语表部分很有帮助。

● Principal:一个命名的实体,例如用户或服务器。

● KDC:密钥分发中心,包括AS和TGS:

■ AS:身份验证服务器;提供获得额外 tickets 所需的 ticket-granting ticket

■ TGS:The ticket-granting server;为拥有有效TGT的Kerberos客户端提供额外的tickets。

● TGT:The ticket-granting ticket;呈现给TGS以获得用于服务访问的服务tickets

使用Kerberos的LDAP身份验证需要KDC服务器和LDAP服务器。可以通过不同的方式满足这一要求:

● Active Directory包括这两个服务器,默认情况下在Active Directory LDAP服务器中启用Kerberos身份验证。

● OpenLDAP提供了一个LDAP服务器,但可能需要一个单独的KDC服务器,并需要额外的Kerberos设置。

Kerberos也必须在客户端主机上可用。客户端使用密码联系AS以获得TGT。然后,客户端使用TGT从TGS获得对其他服务(如LDAP)的访问权限。

以下部分讨论了在MySQL中使用GSSAPI/Kerberos进行SASL LDAP身份验证的配置步骤:

验证Kerberos和LDAP的可用性

以下示例显示了如何在Active Directory中测试Kerberos的可用性。该示例做出了以下假设:

● Active Directory正在名为 ldap_auth.example.com 的主机上运行,IP地址为 198.51.100.10

● MySQL相关的Kerberos身份验证和LDAP查找使用 MySQL.LOCAL 域。

● 一位名叫 [email protected] 已在KDC注册。(在后面的讨论中,此主体名称还与使用GSSAPI/Kerberos对MySQL服务器进行身份验证的MySQL帐户相关联。)

在满足这些假设的情况下,遵循以下程序:

1. 请验证Kerberos库是否已在操作系统中正确安装和配置。例如,要配置 MYSQL.LOCAL 域以在MYSQL身份验证期间使用,/etc/krb5.conf Kerberos配置文件应该包含如下内容:

[realms]
MYSQL.LOCAL = {
kdc = ldap_auth.example.com
admin_server = ldap_auth.example.com
default_domain = MYSQL.LOCAL
}

2. 您可能需要为服务器主机向/etc/hosts添加一个条目:

198.51.100.10 ldap_auth ldap_auth.example.com

3. 检查Kerberos身份验证是否正常工作:

a. 使用 kinit 对Kerberos进行身份验证:

kinit [email protected]

该命令为名为 [email protected] 的Kerberos主体进行身份验证。 当命令提示输入主体的密码时,输入该密码。KDC返回一个缓存在客户端的TGT,供其他支持Kerberos的应用程序使用。

b. 使用klist检查TGT是否正确获得。输出应与此类似:

klist
Ticket cache: FILE:/tmp/krb5cc_244306
Default principal: [email protected]
Valid starting Expires Service principal
03/23/2021 08:18:33 03/23/2021 18:18:33 krbtgt/[email protected]

4. 使用此命令检查 ldapsearch 是否与Kerberos TGT一起工作,该命令用于搜索MYSQL.LOCAL域中的用户:

ldapsearch -h 198.51.100.10 -Y GSSAPI -b "dc=MYSQL,dc=LOCAL"

为GSSAPI/Kerberos配置服务器端SASL LDAP身份验证插件

假设LDAP服务器可以通过Kerberos访问,如前所述,配置服务器端SASL LDAP身份验证插件使用GSSAPI/Kerberos身份验证方法。以下是服务器my.cnf文件可能包含的插件相关设置示例:

[mysqld]
plugin-load-add=authentication_ldap_sasl.so
authentication_ldap_sasl_auth_method_name="GSSAPI"
authentication_ldap_sasl_server_host=198.51.100.10
authentication_ldap_sasl_server_port=389
authentication_ldap_sasl_bind_root_dn="cn=admin,cn=users,dc=MYSQL,dc=LOCAL"
authentication_ldap_sasl_bind_root_pwd="password"
authentication_ldap_sasl_bind_base_dn="cn=users,dc=MYSQL,dc=LOCAL"
authentication_ldap_sasl_user_search_attr="sAMAccountName"

这些选项文件设置按如下方式配置SASL LDAP插件:

● --plugin-load-add 选项加载插件(根据需要调整平台的.so后缀)。如果您以前使用 INSTALL PLUGIN 语句加载插件,则此选项是不必要的。


authentication_ldap_sasl_auth_method_name 必须设置为 GSSAPI才 能使用 GSSAPI/Kerberos 作为sasl ldap身份验证方法。


authentication_ldap_sasl_server_host 和 authentication_ldap_sasl_server_port 表示用于身份验证的Active Directory服务器主机的IP地址和端口号。


authentication_ldap_sasl_bind_root_dn 和 authentication_ldap_sasl_bind_root_pwd 为组搜索功能配置 root dn和密码。此功能是必需的,但用户可能没有搜索权限。在这种情况下,有必要提供根DN信息:

■ 在DN选项值中,admin应该是具有执行用户搜索权限的管理LDAP帐户的名称。

■ 在密码选项值中,密码应为管理员帐户密码。


authentication_ldap_sasl_bind_base_dn 表示用户 dn的基本路径,以便搜索 MYSQL.LOCAL 域中的用户。


authentication_ldap_sasl_user_search_attr 指定标准的 Active Directory搜索属性, sAMAccountName 此属性用于搜索以匹配登录名;属性值与用户DN值不同。

创建一个使用GSSAPI/Kerberos进行LDAP身份验证的MySQL帐户

MySQL身份验证使用SASL LDAP身份验证插件和GSSAPI/Kerberos方法基于作为Kerberos主体的用户。以下讨论使用了一个名为 [email protected] 的主体作为该用户,必须在多个地方注册:

● Kerberos管理员应该将用户名注册为Kerberos主体。此名称应包括域名。客户端使用主体名称和密码通过Kerberos进行身份验证并获得TGT。

● LDAP管理员应该在LDAP条目中注册用户名。例如:

uid=bredon,dc=MYSQL,dc=LOCAL

说明:在Active Directory(使用Kerberos作为默认身份验证方法)中,创建用户将同时创建Kerberos主体和LDAP条目。

● MySQL DBA应该创建一个帐户,该帐户以Kerberos主体名称作为用户名,并使用SASL LDAP插件进行身份验证。

假设Kerberos主体和LDAP条目已由相应的服务管理员注册,并且,MySQL服务器已使用服务器端SASL-LDAP插件的适当配置设置启动。然后,MySQL DBA创建一个MySQL帐户,该帐户对应于Kerberos主体名称,包括域名。

以下语句创建一个名为的代理用户 [email protected] 它假定了名为 proxy_krb_usr 的被代理用户的权限。应该具有相同权限的其他GSSAPI/Kerberos用户可以类似地创建为同一代理用户的代理用户。

-- create proxy account
CREATE USER '[email protected]' IDENTIFIED WITH authentication_ldap_sasl BY '#krb_grp=proxied_krb_user';
-- create proxied account and grant its privileges;
-- use mysql_no_login plugin to prevent direct login
CREATE USER 'proxied_krb_user' IDENTIFIED WITH mysql_no_login;
GRANT ALL ON krb_user_db.* TO 'proxied_krb_user';
-- grant to proxy account the
-- PROXY privilege for proxied account
GRANT PROXY ON 'proxied_krb_user' TO '[email protected]';

仔细观察第一个CREATE USER语句和GRANT proxy语句中对代理帐户名称的引用:

● 对于大多数MySQL帐户,用户和主机是帐户名称的独立部分,因此分别引用为“'user_name'@'host_name'

● 对于LDAP Kerberos身份验证,帐户名的用户部分包括主体域,因此 '[email protected]' 作为单个值引用。由于没有给出主机部分,MySQL帐户全名使用默认的 '%' 作为主机部分:'[email protected]'@'%'

说明:

当创建使用 authentication_ldap_sasl SASL LDAP 身份验证插件和 GSSAPI/Kerberos 身份验证方法进行身份验证的账户时,CREATE USER语句将领域作为用户名的一部分。这与创建使用 authentication_kerberos Kerberos 插件的账户不同。对于这样的账户,CREATE USER语句不将领域作为用户名的一部分。相反,在BY子句中将领域指定为身份验证字符串。

代理账户使用 mysql_no_login 身份验证插件来防止客户端使用该帐户直接登录mysql服务器。相反,使用LDAP进行身份验证的用户应该使用 [email protected] 代理账户。

使用MySQL帐户连接到MySQL服务器

在设置了使用GSSAPI/Kerberos进行身份验证的MySQL帐户后,客户端可以使用它连接到MySQL服务器。Kerberos身份验证可以在MySQL客户端程序调用之前或调用时进行:

● 在调用MySQL客户端程序之前,客户端用户可以独立于MySQL从KDC获得TGT。例如,客户端用户可以通过提供Kerberos主体名称和主体密码,使用kinit对Kerberos进行身份验证:

kinit [email protected]
Password for [email protected]: (enter password here)

生成的TGT被缓存,并可供其他支持Kerberos的应用程序使用,例如使用客户端SASL LDAP身份验证插件的程序。在这种情况下,MySQL客户端程序使用TGT对MySQL服务器进行身份验证,因此在不指定用户名或密码的情况下调用客户端:

mysql --default-auth=authentication_ldap_sasl_client

如前所述,缓存TGT时,客户端命令中不需要用户名和密码选项。如果命令仍然包含它们,则按如下方式处理它们:

■ 如果命令包含用户名,那么如果该名称与TGT中的主体名称不匹配,则身份验证将失败。

■ 如果命令包含密码,客户端插件会忽略它。因为身份验证是基于TGT的,所以即使用户提供的密码不正确,它也可以成功。因此,如果发现导致密码被忽略的有效TGT,插件会产生警告。

● 如果Kerberos缓存不包含TGT,则客户端SASL LDAP身份验证插件本身可以从KDC获取TGT。使用与MySQL帐户关联的Kerberos主体的名称和密码选项调用客户端(在单行中输入命令,然后在提示时输入主体密码):

mysql --default-auth=authentication_ldap_sasl_client [email protected] --password

● 如果Kerberos缓存不包含TGT,并且客户端命令没有指定主体名称作为用户名,则身份验证失败。

如果您不确定是否存在TGT,可以使用klist进行检查。

身份验证如下所示:

1. 客户端使用TGT使用Kerberos进行身份验证。

2. 服务器找到主体的LDAP条目,并使用它来验证 [email protected] MySQL代理帐户。

3. 代理帐户身份验证字符串中的组映射信息('#krb_grp=proxied_krb_user') 指示经过身份验证的代理用户应该是 proxyed_krb_user。

4. [email protected] 被视为 proxyed_krb_user 的代理,下面的查询返回输出,如图所示:

SELECT USER(), CURRENT_USER(), @@proxy_user;
+------------------------------+--------------------+--------------------------+
| USER() | CURRENT_USER() | @@proxy_user |
+------------------------------+--------------------+--------------------------+
| [email protected]@localhost | proxied_krb_user@% | '[email protected]'@'%' |
+------------------------------+--------------------+--------------------------+

USER()值指示用于客户端命令的用户名([email protected])以及客户端连接的主机(localhost)。

CURRENT_USER()值是代理的用户帐户的全名,它由 proxied_krb_user 用户部分和 % 主机部分组成。

@@proxy_user值表示用于连接MySQL服务器的帐户的全名,该帐户由 [email protected] 用户部分和 % 主机部分组成组成。

这表明代理通过 [email protected] 代理用户帐户,以及 [email protected] 取得授予 proxyed_krb_user 被代理用户帐户的权限。

一旦获得TGT,它就会被缓存在客户端,并且可以使用直到它过期,而无需再次指定密码。只要获得TGT,客户端插件使用它来获取服务票证并与服务器端插件通信。

说明

当客户端身份验证插件本身获得TGT时,客户端用户可能不希望重用TGT。本地 /etc/krb5.conf 文件可用于使客户端插件在使用TGT时销毁TGT。

服务器端插件无法访问TGT本身或用于获取TGT的Kerberos密码。

LDAP身份验证插件无法控制缓存机制(存储在本地文件、内存等中),但Kerberos实用程序(如kswitch)可能可用于此目的。

LDAP身份验证的客户端配置参数


authentication_ldap_sasl_client 客户端 SASL LDAP插件读取本地 /etc/krb5.conf文件。如果此文件丢失或无法访问,则会发生错误。假设该文件是可访问的,它可以包括一个可选的 [appdefaults] 部分,以提供插件使用的信息。将信息放在该部分的mysql部分中。例如:

[appdefaults]
mysql = {
ldap_server_host = "ldap_host.example.com"
ldap_destroy_tgt = true
}

客户端插件在mysql部分识别这些参数:

● ldap_server_host 值指定 LDAP 服务器主机,当该主机与 [realms] 部分中指定的KDC服务器主机不同时,该值可能很有用。默认情况下,插件使用KDC服务器主机作为LDAP服务器主机。

● ldap_destroy_tgt 值表示客户端插件在获取并使用TGT后是否销毁TGT。默认情况下,ldap_destroy_tgt 为 false,但可以设置为 true 以避免 TGT 重复使用。(此设置仅适用于客户端插件创建的TGT,而不适用于其他插件创建的或外部到MySQL的TGT)

LDAP搜索引用

LDAP服务器可以配置为将LDAP搜索委托给另一个LDAP服务器,这一功能称为LDAP引用。假设服务器 a.example.com 拥有一个 "dc=example,dc=com" 的 root DN,并希望将搜索委托给另一个服务器 b.example.com。要启用此功能,a.example.com将配置一个具有以下属性的命名引用对象:

dn: dc=subtree,dc=example,dc=com
objectClass: referral
objectClass: extensibleObject
dc: subtree
ref: ldap://b.example.com/dc=subtree,dc=example,dc=com

启用LDAP引用的一个问题是,当搜索基本DN是 root DN并且未设置引用对象时,搜索可能会因 LDAP 操作错误而失败。MySQL DBA可能希望避免LDAP身份验证插件出现此类引用错误,即使LDAP引用可能在LDAP.conf配置文件中全局设置。要在特定于插件的基础上配置LDAP服务器在与每个插件通信时是否应使用LDAP引用,请设置
authentication_ldap_simple_referral 和 authentication_ldap_sasl_referral 系统变量。将变量设置为ON或OFF会导致相应的LDAP身份验证插件告诉LDAP服务器在MySQL身份验证期间是否使用引用。每个变量都具有特定于插件的效果,并且不会影响与LDAP服务器通信的其他应用程序。默认情况下,这两个变量都处于关闭状态

猜你喜欢

转载自blog.csdn.net/weixin_44496870/article/details/131380570