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
注意
如果将 Kerberos 与 ssh
连接插件一起使用,则可以忽略 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 库将执行 SRV 查找 _kerberos._udp.my.domain.com
和 _kerberos._tcp.my.domain.com
来查找 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)使用另一种名为 Heimdal 的 GSSAPI 实现,其行为方式与 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
在上面的示例中,我们在 krbtgt
服务主体下存储了 TGT,并在其自己的服务主体下存储了 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,请将 -f
标志添加到 kinit
命令,或者在 krb5.conf
文件的 [libdefaults]
部分设置 forwardable = true
选项。 如果您使用 psrp
或 winrm
连接插件从 inventory 中用户的密码检索 TGT,如果连接插件配置为使用委派,它将自动请求一个可转发的 TGT。
要让连接插件委派凭据,它需要在 inventory 中设置以下主机变量
# 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 域控制器未同步
KDC realm 在
krb5.conf
文件中未正确设置或无法通过 DNS 解析
如果使用 MIT Kerberos 实现,您可以设置环境变量 KRB5_TRACE=/dev/stdout
以获取有关 Kerberos 库正在执行的操作的更多详细信息。 这对于调试 Kerberos 库的问题(例如 KDC 查找行为、时间同步问题和服务器名称查找失败)非常有用。