MySQL8 中文参考(二十六)(3)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL8 中文参考(二十六)

MySQL8 中文参考(二十六)(2)https://developer.aliyun.com/article/1566128


使用 LDAP 可插拔认证

本节描述了如何启用 MySQL 帐户使用 LDAP 可插拔认证连接到 MySQL 服务器。假设服务器正在运行,并启用了适当的服务器端插件,如安装 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 用户betsyboris分别对betsy_ldapboris_ldap的 LDAP 条目进行身份验证。(MySQL 和 LDAP 用户名不必不同。 在本讨论中使用不同名称有助于澄清操作上下文是 MySQL 还是 LDAP。)
  • LDAP 条目使用uid属性来指定用户名。 这可能会根据 LDAP 服务器而变化。 一些 LDAP 服务器使用cn属性而不是uid来表示用户名。 要更改属性,请适当修改authentication_ldap_simple_user_search_attrauthentication_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
  • CREATE USER 语句创建 MySQL 账户时,在 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 服务器,并启用客户端端 mysql_clear_password 插件:

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

注意

客户端端 mysql_clear_password 认证插件不会更改密码,因此客户端程序将其作为明文发送到 MySQL 服务器。 这使得密码可以原样传递到 LDAP 服务器。 在没有 SASL 的情况下使用服务器端 LDAP 库需要明文密码,但在某些配置中可能存在安全问题。 这些措施最小化了风险:

  • 为了减少意外使用 mysql_clear_password 插件的可能性,MySQL 客户端必须显式启用它(例如,使用 --enable-cleartext-plugin 选项)。 请参见 Section 8.4.1.4, “Client-Side Cleartext Pluggable Authentication”。
  • 为了避免启用 mysql_clear_password 插件时密码暴露,MySQL 客户端应该使用加密连接连接到 MySQL 服务器。 请参见 Section 8.3.1, “Configuring MySQL to Use Encrypted Connections”。

认证过程如下进行:

  1. 客户端插件将 betsybetsy_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 条目没有组属性,因此服务器端插件将客户端用户名(betsy)作为经过身份验证的用户返回。这与客户端提供的相同用户名,因此不会发生代理,并且客户端会话使用'betsy'@'localhost'账户进行权限检查。

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

如果CREATE USER语句中没有包含BY子句来指定betsy_ldap LDAP 专有名称,认证尝试将使用客户端提供的用户名(在本例中为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
Enter password: *boris_password* *(boris_ldap LDAP password)*

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

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

具有代理功能的 LDAP 认证

LDAP 认证插件支持代理,使用户可以以一个用户连接到 MySQL 服务器,但假定另一个用户的权限。本节描述了基本的 LDAP 插件代理支持。LDAP 插件还支持指定组偏好和代理用户映射;请参阅 LDAP 认证组偏好和映射规范。

此处描述的代理实现基于使用 LDAP 组属性值将通过 LDAP 进行身份验证的连接 MySQL 用户映射到定义不同权限集的其他 MySQL  账户。用户不会直接通过定义权限的账户连接。相反,他们通过使用 LDAP 进行身份验证的默认代理账户连接,以便将所有外部登录映射到持有权限的代理  MySQL 账户。通过代理账户连接的任何用户都将映射到其中一个代理 MySQL 账户,其权限确定了允许外部用户执行的数据库操作。

此处的说明假定以下场景:

  • LDAP 条目使用uidcn属性分别指定用户名和组值。要使用不同的用户和组属性名称,请设置适当的插件特定系统变量:
  • 对于authentication_ldap_simple插件:设置authentication_ldap_simple_user_search_attrauthentication_ldap_simple_group_search_attr
  • 对于authentication_ldap_sasl插件:设置authentication_ldap_sasl_user_search_attrauthentication_ldap_sasl_group_search_attr
  • 这些 LDAP 条目可在由 LDAP 服务器管理的目录中找到,以提供唯一标识每个用户的可区分名称值:
uid=basha,ou=People,dc=example,dc=com,cn=accounting
uid=basil,ou=People,dc=example,dc=com,cn=front_office
  • 在连接时,组属性值成为经过身份验证的用户名称,因此它们命名了accountingfront_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;
GRANT ALL PRIVILEGES
  ON accountingdb.*
  TO 'accounting'@'localhost';
GRANT ALL PRIVILEGES
  ON frontdb.*
  TO 'front_office'@'localhost';

代理帐户使用mysql_no_login身份验证插件防止客户端直接使用帐户登录到 MySQL 服务器。相反,使用 LDAP 进行身份验证的用户应该使用默认的''@'%'代理帐户。(这假定安装了mysql_no_login插件。有关说明,请参见  Section 8.4.1.9, “No-Login Pluggable  Authentication”。)有关保护代理帐户免受直接使用的替代方法,请参见 Preventing Direct Login to  Proxied Accounts。

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

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

使用mysql命令行客户端连接到 MySQL 服务器作为basha

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

认证过程如下:

  1. 服务器使用默认的''@'%'代理帐户对客户端用户basha进行连接认证。
  2. 匹配的 LDAP 条目是:
uid=basha,ou=People,dc=example,dc=com,cn=accounting
  1. 匹配的 LDAP 条目具有组属性cn=accounting,因此accounting成为认证的代理用户。
  2. 认证用户与客户端用户名basha不同,导致basha被视为accounting的代理,并且basha承担了代理accounting帐户的权限。以下查询返回如下输出:
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+-----------------+----------------------+--------------+
| USER()          | CURRENT_USER()       | @@proxy_user |
+-----------------+----------------------+--------------+
| basha@localhost | accounting@localhost | ''@'%'       |
+-----------------+----------------------+--------------+

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

现在改为连接为basil

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

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

  1. 服务器使用默认的''@'%'代理帐户对客户端用户basil进行连接认证。
  2. 匹配的 LDAP 条目是:
uid=basil,ou=People,dc=example,dc=com,cn=front_office
  1. 匹配的 LDAP 条目具有组属性cn=front_office,因此front_office成为认证的代理用户。
  2. 认证用户与客户端用户名basil不同,导致basil被视为front_office的代理,并且basil承担了代理front_office帐户的权限。以下查询返回如下输出:
mysql> 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属性构建而成。

认证字符串的剩余部分以#开头,表示组偏好和映射信息的开始。认证字符串的这部分按照grp1grp2grp3的顺序列出组名。LDAP 插件将该列表与 LDAP 服务器返回的组名集合进行比较,按照列表顺序查找与返回的名称匹配的组。插件使用第一个匹配项,如果没有匹配项,则认证失败。

假设 LDAP 服务器返回组grp3grp2grp7。LDAP 插件使用grp2,因为它是认证字符串中第一个匹配的组,即使它不是 LDAP 服务器返回的第一个组。如果 LDAP 服务器返回grp4grp2grp1,插件使用grp1,即使grp2也匹配。grp1的优先级高于grp2,因为它在认证字符串中较早列出。

假设插件找到组名匹配,它将从该组名映射到 MySQL 代理用户名称,如果有的话。对于示例代理账户,映射如下进行:

  • 如果匹配的组名是grp1grp3,它们在认证字符串中与用户名称userauserc相关联。插件使用相应的关联用户名称作为代理用户名称。
  • 如果匹配的组名是 grp2,认证字符串中没有关联的用户名。插件使用 grp2 作为代理用户名称。

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

要指定 LDAP 组偏好和映射信息,应遵循以下原则:

  • # 前缀字符开始认证字符串的组偏好和映射部分。
  • 组偏好和映射规范是由逗号分隔的一个或多个项目的列表。每个项目的形式为 *group_name*=*user_name*group_name。项目应按组名偏好顺序列出。对于插件从 LDAP 服务器返回的组名集合中选择的组名,两种语法在效果上有所不同:
  • 对于指定为 *group_name*=*user_name*(带有用户名)的项目,组名映射到用户名,该用户名用作 MySQL 代理用户名称。
  • 对于指定为 group_name(没有用户名)的项目,组名用作 MySQL 代理用户名称。
  • 要引用包含特殊字符(如空格)的组或用户名,用双引号 (") 括起来。例如,如果一个项目的组名和用户名分别为 my group namemy user name,则必须在组映射中使用引号:
"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"
  • 要转义字符,请在其前面加上反斜杠 (\)。这对于包含文字双引号或反斜杠(否则不会被字面包含)特别有用。
  • 用户 DN 不一定要出现在认证字符串中,但如果出现,必须在组偏好和映射部分之前。用户 DN 可以作为完整用户 DN 给出,也可以作为带有 + 前缀字符的用户 DN 后缀给出。(参见 LDAP 认证用户 DN 后缀.)
LDAP 认证用户 DN 后缀

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

  • 在没有 + 字符的情况下,认证字符串值将按原样处理,不做修改。
  • 如果认证字符串以+开头,插件将从客户端发送的用户名和认证字符串中指定的 DN(去除+)构造完整的用户 DN 值。在构造的 DN 中,客户端用户名成为指定 LDAP 用户名的属性值。默认情况下为uid;要更改属性,请修改相应的系统变量(authentication_ldap_simple_user_search_attrauthentication_ldap_sasl_user_search_attr)。认证字符串存储在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)连接,该用户名与认证字符串一起用作构造用户 DN 的uid属性:uid=accounting,ou=People,dc=example,dc=com

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

LDAP 认证方法

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

  • 对于authentication_ldap_simple插件:设置authentication_ldap_simple_auth_method_name系统变量以配置方法。允许的选择是SIMPLEAD-FOREST
  • 对于 authentication_ldap_sasl 插件:设置 authentication_ldap_sasl_auth_method_name 系统变量以配置方法。允许的选择是 SCRAM-SHA-1SCRAM-SHA-256GSSAPI。(要确定主机系统上实际可用的 SASL LDAP 方法,请检查 Authentication_ldap_sasl_supported_methods 状态变量的值。)

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

GSSAPI/Kerberos 认证方法

通用安全服务应用程序接口(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  环境中,当应用程序通过默认启用 Kerberos 的 Microsoft Active Directory 访问 LDAP 时,这是非常有用的。

以下讨论提供了使用 GSSAPI 方法的配置要求信息。假定熟悉 Kerberos 概念和操作。以下列表简要定义了几个常见的 Kerberos 术语。您还可以在 RFC 4120 的术语表部分找到有用的信息。

  • 主体:一个命名实体,比如用户或服务器。
  • KDC:密钥分发中心,包括 AS 和 TGS:
  • AS:认证服务器;提供获取额外票证所需的初始票证授予票证。
  • TGS:票证授予服务器;为拥有有效 TGT 的 Kerberos 客户端提供额外票证。
  • TGT:票据授予票据;提交给 TGS 以获取用于服务访问的服务票据。

使用 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 的可用性
  • 为 GSSAPI/Kerberos 配置服务器端 SASL LDAP 身份验证插件
  • 创建一个使用 GSSAPI/Kerberos 进行 LDAP 身份验证的 MySQL 帐户
  • 使用 MySQL 帐户连接到 MySQL 服务器
  • LDAP 身份验证的客户端配置参数
验证 Kerberos 和 LDAP 的可用性

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

  • Active Directory 运行在名为ldap_auth.example.com的主机上,IP 地址为198.51.100.10
  • 与 MySQL 相关的 Kerberos 身份验证和 LDAP 查找使用MYSQL.LOCAL域。
  • 名为bredon@MYSQL.LOCAL的主体已在 KDC 中注册。(在后续讨论中,此主体名称还与使用 GSSAPI/Kerberos 对 MySQL 服务器进行身份验证的 MySQL 帐户相关联。)

在满足这些假设的情况下,按照以下步骤操作:

  1. 验证操作系统中 Kerberos 库是否已安装和配置正确。例如,要为 MySQL 身份验证期间使用MYSQL.LOCAL域,/etc/krb5.conf Kerberos 配置文件应包含类似于以下内容:
[realms]
 MYSQL.LOCAL = {
 kdc = ldap_auth.example.com
 admin_server = ldap_auth.example.com
 default_domain = MYSQL.LOCAL
  }
  1. 您可能需要为服务器主机在/etc/hosts中添加一个条目:
198.51.100.10 ldap_auth ldap_auth.example.com
  1. 检查 Kerberos 身份验证是否正常工作:
  1. 使用kinit进行 Kerberos 身份验证:
$> kinit bredon@MYSQL.LOCAL
Password for bredon@MYSQL.LOCAL: *(enter password here)*
  1. 该命令用于验证名为bredon@MYSQL.LOCAL的 Kerberos 主体。当命令提示时,请输入主体的密码。KDC 返回一个 TGT,该 TGT 在客户端缓存中供其他支持 Kerberos 的应用程序使用。
  2. 使用klist检查 TGT 是否正确获取。输出应类似于以下内容:
$> klist
Ticket cache: FILE:/tmp/krb5cc_244306
Default principal: bredon@MYSQL.LOCAL
Valid starting       Expires              Service principal
03/23/2021 08:18:33  03/23/2021 18:18:33  krbtgt/MYSQL.LOCAL@MYSQL.LOCAL
  1. 使用此命令检查ldapsearch是否与 Kerberos TGT 一起工作,该命令在MYSQL.LOCAL域中搜索用户:
ldapsearch -h 198.51.100.10 -Y GSSAPI -b "dc=MYSQL,dc=LOCAL"
配置服务器端 SASL LDAP 认证插件以使用 GSSAPI/Kerberos

假设 LDAP 服务器可以通过上述方式访问 Kerberos,配置服务器端 SASL LDAP 认证插件以使用 GSSAPI/Kerberos 认证方法。(有关一般 LDAP 插件安装信息,请参阅安装 LDAP 可插入认证。)以下是服务器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_hostauthentication_ldap_sasl_server_port指示用于身份验证的 Active Directory 服务器主机的 IP 地址和端口号。
  • authentication_ldap_sasl_bind_root_dnauthentication_ldap_sasl_bind_root_pwd配置了用于组搜索功能的根 DN 和密码。此功能是必需的,但用户可能没有搜索权限。在这种情况下,有必要提供根 DN 信息:
  • 在 DN 选项值中,admin应该是具有执行用户搜索权限的管理 LDAP 帐户的名称。
  • 在密码选项值中,*password*应该是admin帐户的密码。
  • authentication_ldap_sasl_bind_base_dn指示用户 DN 基本路径,以便搜索在MYSQL.LOCAL域中的用户。
  • authentication_ldap_sasl_user_search_attr 指定了一个标准的 Active Directory 搜索属性,sAMAccountName。此属性用于搜索以匹配登录名;属性值与用户 DN 值不同。
创建一个使用 GSSAPI/Kerberos 进行 LDAP 认证的 MySQL 账户

使用 GSSAPI/Kerberos 方法的 SASL LDAP 认证插件进行 MySQL 认证是基于一个作为 Kerberos 主体的用户。以下讨论使用一个名为 bredon@MYSQL.LOCAL 的主体作为此用户,必须在多个地方注册:

  • Kerberos 管理员应该将用户名称注册为 Kerberos 主体。此名称应包括域名。客户端使用主体名称和密码进行 Kerberos 认证并获取 TGT。
  • LDAP 管理员应在 LDAP 条目中注册用户名称。例如:
uid=bredon,dc=MYSQL,dc=LOCAL
  • 注意
    在 Active Directory(默认使用 Kerberos 作为认证方法),创建用户会同时创建 Kerberos 主体和 LDAP 条目。
  • MySQL DBA 应创建一个账户,其用户名称为 Kerberos 主体名称,并使用 SASL LDAP 插件进行认证。

假设适当的服务管理员已经注册了 Kerberos 主体和 LDAP 条目,并且,如前面在 Installing LDAP  Pluggable Authentication 和 Configure the Server-Side SASL LDAP  Authentication Plugin for GSSAPI/Kerberos 中描述的那样,MySQL  服务器已经以适当的配置设置启动了服务器端 SASL LDAP 插件。然后 MySQL DBA 创建一个对应于 Kerberos 主体名称的  MySQL 账户,包括域名。

注意

SASL LDAP 插件对于 Kerberos 认证使用一个固定的用户 DN,并忽略从 MySQL 配置的任何用户 DN。这有一定的影响:

  • 对于使用 GSSAPI/Kerberos 认证的任何 MySQL 账户,在 CREATE USERALTER USER 语句中的认证字符串不应包含用户 DN,因为它没有任何效果。
  • 因为认证字符串不包含用户 DN,所以应包含组映射信息,以使用户能够作为映射到所需代理用户的代理用户进行处理。有关使用 LDAP 认证插件进行代理的信息,请参阅 LDAP Authentication with Proxying。

以下语句创建一个名为bredon@MYSQL.LOCAL的代理用户,该用户假定了被代理用户proxied_krb_usr的权限。其他应具有相同权限的 GSSAPI/Kerberos 用户可以类似地为同一被代理用户创建代理用户。

-- create proxy account
CREATE USER 'bredon@MYSQL.LOCAL'
  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 'bredon@MYSQL.LOCAL';

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

  • 对于大多数 MySQL 账户,用户和主机是账户名称的独立部分,因此分别引用为'*user_name*'@'*host_name*'
  • 对于 LDAP Kerberos 认证,账户名称的用户部分包括主体域,因此'bredon@MYSQL.LOCAL'被引用为单个值。因为没有给出主机部分,所以完整的 MySQL 账户名称使用默认的'%'作为主机部分:'bredon@MYSQL.LOCAL'@'%'

注意

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

被代理账户使用mysql_no_login认证插件防止客户端直接使用该账户登录到 MySQL 服务器。相反,预期使用 LDAP 进行身份验证的用户使用bredon@MYSQL.LOCAL代理账户。(这假设已安装mysql_no_login插件。有关说明,请参见第 8.4.1.9 节,“无登录可插入认证”。)有关保护被代理账户免受直接使用的替代方法,请参见防止直接登录到被代理账户。

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

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

  • 在调用 MySQL 客户端程序之前,客户端用户可以独立于 MySQL 从 KDC 获取 TGT。例如,客户端用户可以使用kinit通过提供 Kerberos 主体名称和主体密码来对 Kerberos 进行身份验证:
$> kinit bredon@MYSQL.LOCAL
Password for bredon@MYSQL.LOCAL: *(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
  --user=bredon@MYSQL.LOCAL
  --password
  • 如果 Kerberos 缓存中不包含 TGT,并且客户端命令未指定主体名称作为用户名,则认证失败。

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

认证过程如下:

  1. 客户端使用 TGT 使用 Kerberos 进行认证。
  2. 服务器找到主体的 LDAP 条目并用它来认证连接到 bredon@MYSQL.LOCAL MySQL 代理账户。
  3. 代理账户认证字符串中的组映射信息('#krb_grp=proxied_krb_user')表示认证的被代理用户应该是 proxied_krb_user
  4. bredon@MYSQL.LOCAL 被视为 proxied_krb_user 的代理,并且以下查询返回如下输出:
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
+------------------------------+--------------------+--------------------------+
| USER()                       | CURRENT_USER()     | @@proxy_user             |
+------------------------------+--------------------+--------------------------+
| bredon@MYSQL.LOCAL@localhost | proxied_krb_user@% | 'bredon@MYSQL.LOCAL'@'%' |
+------------------------------+--------------------+--------------------------+
  1. USER() 值表示用于客户端命令的用户名(bredon@MYSQL.LOCAL)和客户端连接的主机(localhost)。
    CURRENT_USER() 值是被代理用户账户的全名,由 proxied_krb_user 用户部分和 % 主机部分组成。
    @@proxy_user 值表示用于连接到 MySQL 服务器的账户的全名,由 bredon@MYSQL.LOCAL 用户部分和 % 主机部分组成。
    这表明代理是通过 bredon@MYSQL.LOCAL 代理用户账户进行的,并且 bredon@MYSQL.LOCAL 承担了授予 proxied_krb_user 被代理用户账户的权限。

一旦获得 TGT,客户端会将其缓存在本地,并且在不再需要重新输入密码的情况下可以一直使用直到过期。无论如何获取 TGT,客户端插件都会使用它来获取服务票据并与服务器端插件通信。

注意

当客户端身份验证插件本身获取 TGT 时,客户端用户可能不希望 TGT 被重复使用。如 LDAP 身份验证的客户端配置参数所述,本地的/etc/krb5.conf文件可用于使客户端插件在完成后销毁 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_tgtfalse,但可以设置为true以避免 TGT 重复使用。(此设置仅适用于由客户端插件创建的 TGT,不适用于由 MySQL 的其他插件或外部创建的 TGT。)


MySQL8 中文参考(二十六)(4)https://developer.aliyun.com/article/1566130

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5月前
|
关系型数据库 MySQL Unix
MySQL8 中文参考(二十三)(3)
MySQL8 中文参考(二十三)
54 4
|
5月前
|
存储 缓存 关系型数据库
MySQL8 中文参考(二十一)(5)
MySQL8 中文参考(二十一)
82 3
|
5月前
|
存储 监控 Java
MySQL8 中文参考(二十一)(4)
MySQL8 中文参考(二十一)
139 3
|
5月前
|
存储 安全 关系型数据库
MySQL8 中文参考(二十一)(1)
MySQL8 中文参考(二十一)
49 3
|
5月前
|
存储 关系型数据库 MySQL
MySQL8 中文参考(二十一)(3)
MySQL8 中文参考(二十一)
72 2
|
5月前
|
关系型数据库 MySQL Unix
MySQL8 中文参考(二十一)(2)
MySQL8 中文参考(二十一)
75 2
|
5月前
|
关系型数据库 MySQL 数据安全/隐私保护
MySQL8 中文参考(二十五)(5)
MySQL8 中文参考(二十五)
47 2
|
5月前
|
存储 关系型数据库 MySQL
MySQL8 中文参考(二十四)(1)
MySQL8 中文参考(二十四)
56 2
|
5月前
|
NoSQL 关系型数据库 MySQL
MySQL8 中文参考(二十三)(2)
MySQL8 中文参考(二十三)
61 2
|
5月前
|
存储 关系型数据库 MySQL
MySQL8 中文参考(二十三)(1)
MySQL8 中文参考(二十三)
37 2