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 以了解更多详细信息。一个简单的 krb5.conf
文件,它使用 DNS 查找 KDC 将是
[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,请验证您的 Kerberos 配置,确保 DNS 可以使用 SRV 记录定位 KDC,或者 KDC 已在 krb5.conf
中手动映射。
在基于 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,请将 -f
标志添加到 kinit
命令中,或在 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
注意
还可以设置 GSSAPIDelegateCredentials yes
在 ~/.ssh/config
文件中,以允许所有 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 域未在
krb5.conf
文件中正确设置,或者无法通过 DNS 解析
如果使用 MIT Kerberos 实现,您可以设置环境变量 KRB5_TRACE=/dev/stdout
以获取有关 Kerberos 库正在执行的操作的更详细的信息。这对于调试 Kerberos 库的问题(如 KDC 查找行为、时间同步问题和服务器名称查找失败)非常有用。