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,请验证您的 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,请向 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 查找行为、时间同步问题和服务器名称查找失败)非常有用。