了解 Linux 和容器上的 SQL Server 的 Active Directory 身份验证

适用于:SQL Server - Linux

本文详细介绍了对 Linux 或容器上部署的 SQL Server 进行 Active Directory 身份验证的工作原理。

概念

轻型目录访问协议 (LDAP)

LDAP 是一种用于处理各种目录服务的应用程序协议,包括 Active Directory。 目录服务用于存储用户和帐户信息,以及密码等安全信息。 该信息经过加密,然后与网络上的其他设备共享。

若要详细了解如何保护 LDAP,请参阅如何在 Windows Server 中启用 LDAP 登录

Kerberos

Kerberos 是一种身份验证协议,用于验证用户或主机的标识。 可以将其视为一种验证客户端和服务器的方法。

在具有 Windows 和非 Windows 服务器和客户端的异质(混合)环境中,需要将两种类型的文件与基于 Active Directory 的目录服务一起使用:

  • 密钥表文件
  • Kerberos 配置文件(krb5.confkrb5.ini

什么是密钥表文件?

Linux 或 Unix 系统上的服务器进程无法配置为使用 Windows 服务帐户运行进程。 如果你希望 Linux 或 Unix 系统在启动时自动登录到 Active Directory,必须使用密钥表文件。

密钥表是一个加密文件,其中包含受 Kerberos 保护的服务的表示形式及其在密钥分发中心 (KDC) 中关联的服务主体名称的长期密钥。 密钥不是密码本身。

密钥表用于以下任一用途:

  • 向网络上另一个服务验证服务本身,或者
  • 将入站目录用户的 Kerberos 服务票证解密到服务。

什么是 krb5.conf 文件?

/etc/krb5.conf 文件(也称 krb5.ini)为 Kerberos v5 (KRB5) 和 GNU 简单身份验证和安全层 API (GSSAPI) 库提供配置输入。

此信息包括默认域、每个域的属性(如密钥分发中心)以及默认的 Kerberos 票证生存期。

要进行 Active Directory 身份验证,此文件是必需的。 krb5.conf 是一个 INI 文件,但键值对中的每个值可以是由 {} 括住的一个子组。

有关 krb5.conf 文件的详细信息,请参阅 MIT Kerberos 联盟文档

为 Linux 上的 SQL Server 配置 Kerberos

这些是在运行 Linux 上的 SQL Server 的主机服务器上所需的值。 如果你还在同一主机上运行其他(非 SQL Server)服务,则 krb5.conf 文件可能还需要几个条目。

下面一个供你参考的 krb5.conf 文件示例:

[libdefaults]
default_realm = CONTOSO.COM

[realms]
CONTOSO.COM = {
  kdc = adVM.contoso.com
  admin_server = adVM.contoso.com
  default_domain = contoso.com
}

[domain_realm]
.contoso.com = CONTOSO.COM
contoso.com = CONTOSO.COM
  • libdefaults - default_realm 值必须存在。 此值用于指定主机计算机所属的域。

  • realms(可选)- 对于每个领域,可以设置 kdc 值以指定计算机在查找 Active Directory 帐户时应联系的密钥分发中心。 如果已设置多个 KDC,将根据轮循机制选择每个连接的 KDC。

  • domain_realm(可选)- 可以针对每个领域提供映射。 如果没有,Linux 上的 SQL Server 假定域 contoso.com 映射到领域 CONTOSO.COM

Kerberos 身份验证过程

与 Windows 上的 Kerberos 身份验证一样,获取票证授予票证 (TGT) 的前两步是相同的:

  • 客户端通过向域控制器 (DC) 发送其用户名和密码(已加密)来开始登录过程。

  • 对照内部存储检查用户名和密码后,DC 会将给用户的 TGT 返回到客户端。

Linux 上的 SQL Server 使用密钥表文件读取服务主体名称 (SPN),然后解密用于授权连接的已加密的 Blob。 以下步骤概述了此过程。

  • 用户有了 TGT 后,客户端会通过指定 SQL Server 实例的主机名和端口启动与 SQL Server 的连接。

  • SQL 客户端以 MSSQLSvc/<host>:<port> 格式在内部创建服务主体名称。 这是大多数 SQL Server 客户端中的硬编码格式。

  • 客户端通过从该 SPN 的 DC 请求会话密钥来启动 Kerberos 握手。 TGT 和 SPN 都发送到 DC。

Diagram showing Active Directory authentication for SQL Server on Linux - Ticket-Granting Ticket and Service Principal Name sent to Domain Controller.

  • DC 在验证 TGT 和 SPN 后,会向客户端发送会话密钥,以便连接到 SQL Server SPN。

Diagram showing Active Directory authentication for SQL Server on Linux - session key returned to client by DC.

  • 会话密钥中的加密 blob 将发送到服务器。

Diagram showing Active Directory authentication for SQL Server on Linux - session key sent to server.

  • SQL Server 从其密钥表 (mssql.keytab) 中读取 SPN 的密码,该密钥表是磁盘上包含加密(SPN、密码)元组的文件。

  • SQL Server 使用刚刚查找的密码从客户端解密已加密的 Blob,以获取客户端的用户名。

  • SQL Server 在 sys.syslogins 表中查找客户端,以检查客户端是否已获得连接授权。

  • 连接将被接受或拒绝。

Diagram showing Active Directory authentication for SQL Server on Linux - connection accepted or denied.

为 SQL Server 容器配置 Kerberos

容器中 SQL Server 的 Active Directory 身份验证实质上与 Linux 上的 SQL Server 相同。 唯一的区别是 SQL Server 主机 SPN。 在上一个场景中,SPN 是 MSSQLSvc/<host>:<port>,因为我们是通过 SQL Server 主机的名称进行连接的。 但是,现在需要连接到容器。

对于 SQL Server 容器,可以在容器内创建 krb5.conf 文件。 运行容器的主机节点不需要是域的一部分,但应该能够访问容器将尝试连接到的域控制器。

由于我们要连接到容器,因此客户端连接中的服务器名称可能不同于主机名。 它可以是主机名、容器名称或其他别名。 此外,SQL Server 的公开端口很有可能不是默认的 1433。

必须使用存储在 mssql.keytab 中的 SPN 连接到 SQL Server 容器。 例如,如果 mssql.keytab 中的 SPN 为 MSSQLSvc/sqlcontainer.domain.com:8000,则你将使用 sqlcontainer.domain.com,8000 作为客户端中的连接字符串(包括 sqlcmd、SQL Server Management Studio 和 Azure Data Studio)。

Diagram showing Active Directory authentication for SQL Server Containers.

SQL Server 组刷新

如果只需要服务主体名称进行身份验证,你可能想知道为什么密钥表中存在用户帐户。

假设你有一个用户 adUser,它是组 adGroup 的成员。 如果将 adGroup 添加为 SQL Server 的登录名,这意味着 adUser 也有权登录到 SQL Server 实例。 虽然 adUser 仍连接到 SQL Server,但域管理员可能会将 adUser 从 adGroup 中删除。 现在 adUser 不应再具有登录到 SQL Server 的权限,但他们已通过 Kerberos 身份验证过程并已连接。

我们会定期运行名为“组刷新”的进程,以防连接的用户不再被允许执行特权操作(例如创建登录名或更改数据库)。

SQL Server 具有用于组刷新的特权 Active Directory 帐户。 此帐户使用具有 network.privilegedadaccount 设置的 mssql-conf 进行配置,或者默认为主机计算机的计算机账户 <hostname>$

mssql.keytab 中特权帐户的凭据用于模拟客户端(在本例中为 adUser)。 SQL Server 与自身进行 Kerberos 握手以标识组成员身份信息,并将其与 sys.syslogins 进行比较,以检查 adUser 是否仍具有连接和执行请求的 Transact-SQL 命令所需的权限。 如果 adUser 已从 adGroup 中删除,则连接会被 SQL Server 终止。

组刷新需要以下两个条件:

  • SQL Server 实例与本地 Active Directory 域之间的网络连接。
  • SQL Server 连接到的域与本地 Active Directory 域之间的双向信任。 有关详细信息,请参阅了解 Active Directory