Kerberos 认证
Kerberos 认证是 Windows 环境中用于身份验证的现代方法。它允许客户端和服务器相互验证其身份,并支持 AES 等现代加密方法。
安装 Kerberos
Kerberos 通过 GSSAPI 库提供,该库是系统软件包的一部分。某些发行版默认安装 Kerberos 软件包,但其他发行版可能需要手动安装。
要在基于 RHEL/Fedora 的系统上安装 Kerberos 库
$ sudo dnf install krb5-devel krb5-libs krb5-workstation python3-devel
对于基于 Debian/Ubuntu 的系统
$ sudo apt-get install krb5-user libkrb5-dev python3-dev
对于基于 Arch Linux 的系统
$ sudo pacman -S krb5
对于基于 FreeBSD 的系统
$ sudo pkg install heimdal
注意
如果使用 ssh
连接插件与 Kerberos 配合使用,则可以忽略 python3-devel
/ python3-dev
软件包。仅当使用基于 WinRM 的连接以及 Kerberos 身份验证时,才需要它们。
安装完成后,kinit
、klist
和 krb5-config
软件包将可用。您可以使用以下命令测试它们
$ krb5-config --version
Kerberos 5 release 1.21.3
psrp
和 winrm
连接插件需要额外的 Python 库才能进行 Kerberos 身份验证。如果使用 Kerberos 与 ssh
连接,则可以跳过以下步骤。
如果您为 Ansible 选择了 pipx
安装说明,则可以通过运行以下命令安装这些要求
pipx inject "pypsrp[kerberos]<=1.0.0" # for psrp
pipx inject "pywinrm[kerberos]>=0.4.0" # for winrm
或者,如果您选择了 pip
安装说明
pip3 install "pypsrp[kerberos]<=1.0.0" # for psrp
pip3 install "pywinrm[kerberos]>=0.4.0" # for winrm
配置主机 Kerberos
安装完依赖项后,需要配置 Kerberos 以便它可以与域通信。大多数 Kerberos 实现可以使用 DNS 或通过 /etc/krb5.conf
文件中的手动配置找到域。有关可以在 /etc/krb5.conf
文件中设置的内容的详细信息,请参阅 krb5.conf 以获取更多详细信息。一个使用 DNS 查找 KDC 的简单 krb5.conf
文件将是
[libdefaults]
# Not required but helpful if the realm cannot be determined from
# the hostname
default_realm = MY.DOMAIN.COM
# Enabled KDC lookups from DNS SRV records
dns_lookup_kdc = true
使用上述配置,当为服务器 server.my.domain.com
请求 Kerberos 票证时,Kerberos 库将对 _kerberos._udp.my.domain.com
和 _kerberos._tcp.my.domain.com
进行 SRV 查找以找到 KDC。如果您希望手动设置 KDC 域,则可以使用以下配置
[libdefaults]
default_realm = MY.DOMAIN.COM
dns_lookup_kdc = false
[realms]
MY.DOMAIN.COM = {
kdc = domain-controller1.my.domain.com
kdc = domain-controller2.my.domain.com
}
[domain_realm]
.my.domain.com = MY.DOMAIN.COM
my.domain.com = MY.DOMAIN.COM
使用此配置,任何具有 DNS 后缀 .my.domain.com
和 my.domain.com
本身的票证请求都将发送到 KDC domain-controller1.my.domain.com
,并回退到 domain-controller2.my.domain.com
。
有关 Kerberos 库如何尝试查找 KDC 的更多信息,请参阅 MIT Kerberos 文档。
注意
本节中的信息假设您使用的是 MIT Kerberos 实现,这通常是大多数 Linux 发行版上的默认实现。某些平台(如 FreeBSD 或 macOS)使用不同的 GSSAPI 实现(称为 Heimdal),其作用方式类似于 MIT Kerberos,但某些行为可能有所不同。
验证 Kerberos 配置
要验证 Kerberos 是否正常工作,可以使用 kinit
命令获取域中用户的票证。以下命令将请求域 MY.DOMAIN.COM
中用户 username
的票证
$ kinit [email protected]
Password for [email protected]
如果密码正确,则命令将返回而没有任何输出。要验证是否已获取票证,可以使用 klist
命令
> klist
Ticket cache: KCM:1000
Default principal: [email protected]
Valid starting Expires Service principal
29/08/24 13:54:51 29/08/24 23:54:51 krbtgt/[email protected]
renew until 05/09/24 13:54:48
如果成功,则验证 Kerberos 配置正确并且用户可以从 KDC 获取票证授予票证(TGT
)。如果 kinit
无法找到请求域的 KDC,请通过确保 DNS 可以使用 SRV 记录找到 KDC 或 KDC 在 krb5.conf
中手动映射来验证您的 Kerberos 配置。
在基于 MIT Kerberos 的系统上,您可以使用 kvno
命令验证您是否能够为特定服务检索服务票证。例如,如果您使用基于 WinRM 的连接来使用 server.my.domain.com
进行身份验证,则可以使用以下命令验证您的 TGT 是否能够为目标服务器获取服务票证
$ kvno http/server.my.domain.com
http/[email protected]: kvno = 2
klist
命令也可用于验证票证是否已存储在 Kerberos 缓存中
$ klist
Ticket cache: KCM:1000
Default principal: [email protected]
Valid starting Expires Service principal
29/08/24 13:54:51 29/08/24 23:54:51 krbtgt/[email protected]
renew until 05/09/24 13:54:48
29/08/24 13:55:30 29/08/24 23:55:30 http/[email protected]
renew until 05/09/24 13:55:30
在上面的示例中,我们将 TGT 存储在 krbtgt
服务主体下,并将我们的 http/server.my.domain.com
存储在其自己的服务主体下。
kdestroy
命令可用于删除票证缓存。
票证管理
为了使 Kerberos 身份验证与 Ansible 配合使用,必须存在用户的 Kerberos TGT,以便 Ansible 可以为目标服务器请求服务票证。某些连接插件(如 ssh
)要求 TGT 已经存在并且 Ansible 控制进程可以访问它。其他连接插件(如 psrp
和 winrm
)如果在清单中提供了用户的密码,则可以自动获取用户的 TGT。
要手动为用户检索 TGT,请使用用户的用户名和域运行 kinit
命令,如 验证 Kerberos 配置 中所示。当 Ansible 中的连接插件请求 Kerberos 身份验证时,此 TGT 将被自动使用。
如果您使用的是 psrp
或 winrm
连接插件,并且在清单中提供了用户的密码,则连接插件将自动为用户获取 TGT。这是通过使用用户的用户名和密码运行 kinit
命令来完成的。TGT 将存储在临时凭据缓存中,并将用于该任务。
委托
Kerberos 委托允许凭据遍历多个跳数。当您需要对服务器进行身份验证,然后让该服务器代表您对另一台服务器进行身份验证时,这很有用。要启用委托,您必须
使用
kinit
获取票证时请求可转发的 TGT请求连接插件允许委托到服务器
AD 用户未标记为敏感用户,无法进行委托,并且不是
Protected Users
组的成员。根据
krb5.conf
的配置,目标服务器可能需要通过其 AD 对象委托设置允许不受约束的委托。
要请求可转发 TGT,请在 kinit
命令中添加 -f
标志,或在 krb5.conf
文件的 [libdefaults]
部分设置 forwardable = true
选项。如果您正在使用 psrp
或 winrm
连接插件从清单中的用户密码检索 TGT,则如果连接插件配置为使用委托,它将自动请求可转发 TGT。
要使连接插件委托凭据,它需要在清单中设置以下主机变量。
# psrp
ansible_psrp_negotiate_delegate: true
# winrm
ansible_winrm_kerberos_delegation: true
# ssh
ansible_ssh_common_args: -o GSSAPIDelegateCredentials=yes
注意
也可以在 ~/.ssh/config
文件中设置 GSSAPIDelegateCredentials yes
,以允许所有 SSH 连接的委托。
要验证用户是否允许委托其凭据,可以在同一域中的 Windows 主机上运行以下 PowerShell 脚本。
Function Test-IsDelegatable {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string]
$UserName
)
$NOT_DELEGATED = 0x00100000
$searcher = [ADSISearcher]"(&(objectClass=user)(objectCategory=person)(sAMAccountName=$UserName))"
$res = $searcher.FindOne()
if (-not $res) {
Write-Error -Message "Failed to find user '$UserName'"
}
else {
$uac = $res.Properties.useraccountcontrol[0]
$memberOf = @($res.Properties.memberof)
$isSensitive = [bool]($uac -band $NOT_DELEGATED)
$isProtectedUser = [bool]($memberOf -like 'CN=Protected Users,*').Count
-not ($isSensitive -or $isProtectedUser)
}
}
Test-IsDelegatable -UserName username
较新版本的 MIT Kerberos 在 krb5.conf
文件的 [libdefaults]
部分添加了一个配置选项 enforce_ok_as_delegate
。如果此选项设置为 true
,则只有当目标服务器帐户允许不受约束的委托时,委托才能工作。要检查或设置 Windows 计算机主机上的不受约束的委托,可以使用以下 PowerShell 脚本。
# Check if the server allows unconstrained delegation
(Get-ADComputer -Identity WINHOST -Properties TrustedForDelegation).TrustedForDelegation
# Enable unconstrained delegation
Set-ADComputer -Identity WINHOST -TrustedForDelegation $true
要验证委托是否有效,可以在 Windows 节点上使用 klist.exe
命令来验证票证是否已转发。输出应显示票证服务器为 krbtgt/MY.DOMAIN.COM @ MY.CDOMAIN.COM
,并且票证标志包含 forwarded
。
$ ansible WINHOST -m ansible.windows.win_command -a klist.exe
WINHOST | CHANGED | rc=0 >>
Current LogonId is 0:0x82b6977
Cached Tickets: (1)
#0> Client: username @ MY.DOMAIN.COM
Server: krbtgt/MY.DOMAIN.COM @ MY.DOMAIN.COM
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x60a10000 -> forwardable forwarded renewable pre_authent name_canonicalize
Start Time: 8/30/2024 14:15:18 (local)
End Time: 8/31/2024 0:12:49 (local)
Renew Time: 9/6/2024 14:12:49 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x1 -> PRIMARY
Kdc Called:
如果出现任何错误,klist.exe
的输出将不包含 forwarded
标志,并且服务器将针对目标服务器主体而不是 krbtgt
。
$ ansible WINHOST -m ansible.windows.win_command -a klist.exe
WINHOST | CHANGED | rc=0 >>
Current LogonId is 0:0x82c312c
Cached Tickets: (1)
#0> Client: username @ MY.DOMAIN.COM
Server: http/winhost.my.domain.com @ MY.DOMAIN.COM
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
Start Time: 8/30/2024 14:16:24 (local)
End Time: 8/31/2024 0:16:12 (local)
Renew Time: 0
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x8 -> ASC
Kdc Called:
Kerberos 故障排除
Kerberos 依赖于正确配置的环境才能工作。一些可能导致 Kerberos 身份验证失败的常见问题包括:
为 Windows 主机设置的主机名是别名或 IP 地址。
Ansible 控制节点上的时间与 AD 域控制器不同步。
krb5.conf
文件中 KDC 域未正确设置或无法通过 DNS 解析。
如果使用 MIT Kerberos 实现,您可以设置环境变量 KRB5_TRACE=/dev/stdout
以获取有关 Kerberos 库正在执行的操作的详细信息。这对于调试 Kerberos 库(例如 KDC 查找行为、时间同步问题和服务器名称查找失败)的问题很有用。