Web 服务获取 kerberos/Windows AD 登录的问题
Issues getting kerberos/Windows AD login work for a web service
我已经为此苦苦挣扎了一段时间,但我无法让它工作。
设置如下:
我有一个 nginx 网络服务器在 mywebapp.k8s.dal1.mycompany.io
为 django 应用程序提供服务
它编译了 SPNEGO 插件,我的配置中有以下端点:
location /ad-login {
uwsgi_pass django;
include /usr/lib/mycompany/lib/wsgi/uwsgi_params;
auth_gss on;
auth_gss_realm BURNERDEV1.DAL1.MYCOMPANY.IO;
auth_gss_service_name HTTP/mywebapp.k8s.dal1.mycompany.io;
auth_gss_allow_basic_fallback off;
}
我的 AD 域控制器位于 burnerdev1。dal1.mycompany.io 我配置了以下用户:
rep_movsd
portal
我 运行 在管理员提示符下在 DC 服务器上执行以下命令:
ktpass -out krb5.keytab -mapUser portal@BURNERDEV1.DAL1.MYCOMPANY.IO +rndPass -mapOp set +DumpSalt -crypto AES256-SHA1 -ptype KRB5_NT_PRINCIPAL -princ HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
setspn -A HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO portal
C:\Users\myself\Documents\keytab>ktpass -out krb5.keytab -mapUser portal@BURNERDEV1.DAL1.MYCOMPANY.IO +rndPass -mapOp set +DumpSalt -crypto AES256-SHA1 -ptype KRB5_NT_PRINCIPAL -princ HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
Targeting domain controller: dal1devdc1.burnerdev1.dal1.mycompany.io
Using legacy password setting method
Failed to set property 'servicePrincipalName' to 'HTTP/mywebapp.k8s.dal1.mycompany.io' on Dn 'CN=portal,CN=Users,DC=burnerdev1,DC=dal1,
DC=mycompany,DC=io': 0x13.
WARNING: Unable to set SPN mapping data.
If portal already has an SPN mapping installed for HTTP/mywebapp.k8s.dal1.mycompany.io, this is no cause for concern.
Building salt with principalname HTTP/mywebapp.k8s.dal1.mycompany.io and domain BURNERDEV1.DAL1.MYCOMPANY.IO (encryption type 18)...
Hashing password with salt "BURNERDEV1.DAL1.MYCOMPANY.IOHTTPmywebapp.k8s.dal1.mycompany.io".
Key created.
Output keytab to krb5.keytab:
Keytab version: 0x502
keysize 110 HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) k
eylength 32 (0x632d9ca3356374e9de490ec2f7718f9fb652b20da40bd212a808db4c46a72bc5)
C:\Users\myself\Documents\keytab>setspn -A HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO portal
Checking domain DC=burnerdev1,DC=dal1,DC=mycompany,DC=io
Registering ServicePrincipalNames for CN=portal,CN=Users,DC=burnerdev1,DC=dal1,DC=mycompany,DC=io
HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
Updated object
C:\Users\myself\Documents\keytab>
现在在“Active Directory 用户和计算机”部分,我右键单击用户并选择“属性”
然后在“委派”选项卡上,我设置“信任此用户以委派任何服务(仅限 Kerberos)”
接下来我将 krb5.keytab 文件复制到我的网络服务器并重新启动 nginx 容器
在属于域的 Windows 工作站上,我以 rep_movsd 身份登录 - 当我 运行 klist:
C:\Users\rep_movsd>klist
Current LogonId is 0:0x208d7
Cached Tickets: (2)
#0> Client: rep_movsd @ BURNERDEV1.DAL1.MYCOMPANY.IO
Server: krbtgt/BURNERDEV1.DAL1.MYCOMPANY.IO @ BURNERDEV1.DAL1.MYCOMPANY.IO
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
Start Time: 7/16/2020 2:05:51 (local)
End Time: 7/16/2020 12:05:51 (local)
Renew Time: 7/23/2020 2:05:51 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
#1> Client: rep_movsd @ BURNERDEV1.DAL1.MYCOMPANY.IO
Server: HTTP/mywebapp.k8s.dal1.mycompany.io @ BURNERDEV1.DAL1.MYCOMPANY.IO
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
Start Time: 7/16/2020 2:06:01 (local)
End Time: 7/16/2020 12:05:51 (local)
Renew Time: 7/23/2020 2:05:51 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
我将 Firefox 设置为进行 SPENGO 身份验证
然后我点击 mywebapp.k8s.dal1.mycompany.io/ad-login 并得到一个 403 Forbidden
错误
nginx服务器调试日志显示:
[debug] 16#16: *195 Client sent a reasonable Negotiate header
[debug] 16#16: *195 GSSAPI authorizing
[debug] 16#16: *195 Use keytab /etc/krb5.keytab
[debug] 16#16: *195 Using service principal: HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
[debug] 16#16: *195 my_gss_name HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
[debug] 16#16: *195 gss_accept_sec_context() failed: Cannot decrypt ticket for HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO using keytab key for HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO:
[debug] 16#16: *195 GSSAPI failed
[debug] 16#16: *195 http finalize request: 403, "/ad-login?" a:1, c:1
[debug] 16#16: *195 http special response: 403, "/ad-login?"
[debug] 16#16: *195 http set discard body
[debug] 16#16: *195 charset: "" > "utf-8"
[debug] 16#16: *195 HTTP/1.1 403 Forbidden
顺便说一句,在早些时候闲逛时 - 我发现如果我使用 ktpass 为“门户”用户设置了固定密码并在工作站上以该帐户登录,登录就会成功。
我误以为我需要为每个用户创建一个新的密钥表并将它们组合在一起。
非常感谢任何帮助 - 我读了这么多相互矛盾的文档,这只会让我更加困惑,我为此一直失眠。
提前致谢!
我仔细阅读了你的问题陈述,我认为如果你按照我在下面写的步骤操作,问题就会得到解决。
- 在您创建密钥表的 DC 服务器上,(1) 必须暂时禁用 UAC。 (2) 创建密钥表的用户必须是 Domain Admins 组的成员。
- 确保 SPN 不重复,然后从 Active Directory 用户帐户 portal 中删除 SPN。这 必须 在使用相同的 SPN 针对相同的帐户创建新的密钥表之前完成。下面的命令是单行的,自动换行使它看起来像两行。
setspn -d HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO 传送门
- 完全按照之前的方式重新创建密钥表。
- 您不需要 运行 命令
setspn -A HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO portal
因为 SPN 已经在步骤 3 中通过 ktpass 命令设置在 Active Directory 用户帐户上。
- 用新的密钥表替换旧的密钥表。
- 重新启动 nginx 网络服务器服务。
- 清除浏览器缓存并清除 Kerberos 大小写(klist 清除)。
- 再试一次。
您必须执行所有这些步骤,包括最后的步骤 7。不要跳过任何一个。
您的服务帐户名为 portal。此密码的哈希存储在 Active Directory 和密钥表中。相同的散列在两个位置。 nginix 服务器上的 keytab 用于解密入站 Kerberos 服务票证以确定用户正在尝试访问 Web 应用程序。更具体地说,GSS 身份验证完成所有工作,它 使用密钥表对加密的服务票证进行解密。用户 rep_movsd 没有 具有服务帐户凭据。它是 Active Directory 域的一部分,当访问 nginix Web 服务器时,它会获得自己的 Kerberos 服务票证,并且通过简单地拥有由 keytab 解密的服务票证来向 Web 服务器证明其身份。如果它不是 BURNERDEV1.DAL1.MYCOMPANY.IO 域的一部分,或者密码已过期,或者是禁用的帐户,它将无法获得服务票证,因此无法证明其身份并无法通过身份验证。
如果您有时间,请参阅我的 TechNet Wiki article,了解密钥表的创建及其背后的逻辑,以帮助您更好地理解这个复杂的主题。
我已经为此苦苦挣扎了一段时间,但我无法让它工作。
设置如下:
我有一个 nginx 网络服务器在 mywebapp.k8s.dal1.mycompany.io
它编译了 SPNEGO 插件,我的配置中有以下端点:
location /ad-login {
uwsgi_pass django;
include /usr/lib/mycompany/lib/wsgi/uwsgi_params;
auth_gss on;
auth_gss_realm BURNERDEV1.DAL1.MYCOMPANY.IO;
auth_gss_service_name HTTP/mywebapp.k8s.dal1.mycompany.io;
auth_gss_allow_basic_fallback off;
}
我的 AD 域控制器位于 burnerdev1。dal1.mycompany.io 我配置了以下用户:
rep_movsd
portal
我 运行 在管理员提示符下在 DC 服务器上执行以下命令:
ktpass -out krb5.keytab -mapUser portal@BURNERDEV1.DAL1.MYCOMPANY.IO +rndPass -mapOp set +DumpSalt -crypto AES256-SHA1 -ptype KRB5_NT_PRINCIPAL -princ HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
setspn -A HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO portal
C:\Users\myself\Documents\keytab>ktpass -out krb5.keytab -mapUser portal@BURNERDEV1.DAL1.MYCOMPANY.IO +rndPass -mapOp set +DumpSalt -crypto AES256-SHA1 -ptype KRB5_NT_PRINCIPAL -princ HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
Targeting domain controller: dal1devdc1.burnerdev1.dal1.mycompany.io
Using legacy password setting method
Failed to set property 'servicePrincipalName' to 'HTTP/mywebapp.k8s.dal1.mycompany.io' on Dn 'CN=portal,CN=Users,DC=burnerdev1,DC=dal1,
DC=mycompany,DC=io': 0x13.
WARNING: Unable to set SPN mapping data.
If portal already has an SPN mapping installed for HTTP/mywebapp.k8s.dal1.mycompany.io, this is no cause for concern.
Building salt with principalname HTTP/mywebapp.k8s.dal1.mycompany.io and domain BURNERDEV1.DAL1.MYCOMPANY.IO (encryption type 18)...
Hashing password with salt "BURNERDEV1.DAL1.MYCOMPANY.IOHTTPmywebapp.k8s.dal1.mycompany.io".
Key created.
Output keytab to krb5.keytab:
Keytab version: 0x502
keysize 110 HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype 0x12 (AES256-SHA1) k
eylength 32 (0x632d9ca3356374e9de490ec2f7718f9fb652b20da40bd212a808db4c46a72bc5)
C:\Users\myself\Documents\keytab>setspn -A HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO portal
Checking domain DC=burnerdev1,DC=dal1,DC=mycompany,DC=io
Registering ServicePrincipalNames for CN=portal,CN=Users,DC=burnerdev1,DC=dal1,DC=mycompany,DC=io
HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
Updated object
C:\Users\myself\Documents\keytab>
现在在“Active Directory 用户和计算机”部分,我右键单击用户并选择“属性” 然后在“委派”选项卡上,我设置“信任此用户以委派任何服务(仅限 Kerberos)”
接下来我将 krb5.keytab 文件复制到我的网络服务器并重新启动 nginx 容器
在属于域的 Windows 工作站上,我以 rep_movsd 身份登录 - 当我 运行 klist:
C:\Users\rep_movsd>klist
Current LogonId is 0:0x208d7
Cached Tickets: (2)
#0> Client: rep_movsd @ BURNERDEV1.DAL1.MYCOMPANY.IO
Server: krbtgt/BURNERDEV1.DAL1.MYCOMPANY.IO @ BURNERDEV1.DAL1.MYCOMPANY.IO
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
Start Time: 7/16/2020 2:05:51 (local)
End Time: 7/16/2020 12:05:51 (local)
Renew Time: 7/23/2020 2:05:51 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
#1> Client: rep_movsd @ BURNERDEV1.DAL1.MYCOMPANY.IO
Server: HTTP/mywebapp.k8s.dal1.mycompany.io @ BURNERDEV1.DAL1.MYCOMPANY.IO
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
Start Time: 7/16/2020 2:06:01 (local)
End Time: 7/16/2020 12:05:51 (local)
Renew Time: 7/23/2020 2:05:51 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
我将 Firefox 设置为进行 SPENGO 身份验证
然后我点击 mywebapp.k8s.dal1.mycompany.io/ad-login 并得到一个 403 Forbidden
错误
nginx服务器调试日志显示:
[debug] 16#16: *195 Client sent a reasonable Negotiate header
[debug] 16#16: *195 GSSAPI authorizing
[debug] 16#16: *195 Use keytab /etc/krb5.keytab
[debug] 16#16: *195 Using service principal: HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
[debug] 16#16: *195 my_gss_name HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO
[debug] 16#16: *195 gss_accept_sec_context() failed: Cannot decrypt ticket for HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO using keytab key for HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO:
[debug] 16#16: *195 GSSAPI failed
[debug] 16#16: *195 http finalize request: 403, "/ad-login?" a:1, c:1
[debug] 16#16: *195 http special response: 403, "/ad-login?"
[debug] 16#16: *195 http set discard body
[debug] 16#16: *195 charset: "" > "utf-8"
[debug] 16#16: *195 HTTP/1.1 403 Forbidden
顺便说一句,在早些时候闲逛时 - 我发现如果我使用 ktpass 为“门户”用户设置了固定密码并在工作站上以该帐户登录,登录就会成功。 我误以为我需要为每个用户创建一个新的密钥表并将它们组合在一起。
非常感谢任何帮助 - 我读了这么多相互矛盾的文档,这只会让我更加困惑,我为此一直失眠。
提前致谢!
我仔细阅读了你的问题陈述,我认为如果你按照我在下面写的步骤操作,问题就会得到解决。
- 在您创建密钥表的 DC 服务器上,(1) 必须暂时禁用 UAC。 (2) 创建密钥表的用户必须是 Domain Admins 组的成员。
- 确保 SPN 不重复,然后从 Active Directory 用户帐户 portal 中删除 SPN。这 必须 在使用相同的 SPN 针对相同的帐户创建新的密钥表之前完成。下面的命令是单行的,自动换行使它看起来像两行。
setspn -d HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO 传送门
- 完全按照之前的方式重新创建密钥表。
- 您不需要 运行 命令
setspn -A HTTP/mywebapp.k8s.dal1.mycompany.io@BURNERDEV1.DAL1.MYCOMPANY.IO portal
因为 SPN 已经在步骤 3 中通过 ktpass 命令设置在 Active Directory 用户帐户上。 - 用新的密钥表替换旧的密钥表。
- 重新启动 nginx 网络服务器服务。
- 清除浏览器缓存并清除 Kerberos 大小写(klist 清除)。
- 再试一次。
您必须执行所有这些步骤,包括最后的步骤 7。不要跳过任何一个。
您的服务帐户名为 portal。此密码的哈希存储在 Active Directory 和密钥表中。相同的散列在两个位置。 nginix 服务器上的 keytab 用于解密入站 Kerberos 服务票证以确定用户正在尝试访问 Web 应用程序。更具体地说,GSS 身份验证完成所有工作,它 使用密钥表对加密的服务票证进行解密。用户 rep_movsd 没有 具有服务帐户凭据。它是 Active Directory 域的一部分,当访问 nginix Web 服务器时,它会获得自己的 Kerberos 服务票证,并且通过简单地拥有由 keytab 解密的服务票证来向 Web 服务器证明其身份。如果它不是 BURNERDEV1.DAL1.MYCOMPANY.IO 域的一部分,或者密码已过期,或者是禁用的帐户,它将无法获得服务票证,因此无法证明其身份并无法通过身份验证。
如果您有时间,请参阅我的 TechNet Wiki article,了解密钥表的创建及其背后的逻辑,以帮助您更好地理解这个复杂的主题。