我可以成功运行kinit
并获得以下klist
输出:
Ticket cache: FILE:/tmp/krb5cc_1001
Default principal: [email protected]
Valid starting Expires Service principal
01.03.2022 17:24:01 02.03.2022 17:23:58 krbtgt/[email protected]
以下 cURL 命令也有效:
curl --negotiate -u: http://test.kerim.io:8081/skin?test=foo
输出如下:
* Connected to test.kerim.io (192.168.1.100) port 8081 (#0)
* Server auth using Negotiate with user '';
> GET /skin?test=foo HTTP/1.1
> Host: test.kerim.io:8081
> Authorization: Negotiate YIICWQYGKwYBBQUCoIIC[redacted]
> User-Agent: curl/7.74.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Tue, 01 Mar 2022 16:29:15 GMT
< Server: Apache
< WWW-Authenticate: Negotiate oYG3MIG0oAMKAQChCwYJKoZIgvcSA[redacted]
< Cache-Control: no-cache, no-store
< Access-Control-Allow-Origin: localhost
< Access-Control-Allow-Methods: GET, POST, OPTIONS
< Access-Control-Max-Age: 1000
< Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Authorization, Accept
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
我尝试在 Firefox 中设置各种浏览器设置(通过 about:config,以下这指南)和 chrome 的命令行参数(--auth-server-whitelist="*.kerim.io"
),但似乎浏览器拒绝协商上述 URL。
客户端操作系统是 Ubuntu。Web 服务器确实响应了WWW-Authenticate: Negotiate
。
使用以下环境变量调用 Firefox:
export NSPR_LOG_MODULES="negotiateauth:5,NTLM:5" KRB5_TRACE="/dev/stderr"
显示此错误:
[Parent 21580: Main Thread]: D/negotiateauth service = test.kerim.io
[Parent 21580: Main Thread]: D/negotiateauth using negotiate-gss
[Parent 21580: Main Thread]: D/negotiateauth entering nsAuthGSSAPI::nsAuthGSSAPI()
[Parent 21580: Main Thread]: D/negotiateauth Attempting to load gss functions
[Parent 21580: Main Thread]: D/negotiateauth entering nsAuthGSSAPI::Init()
[Parent 21580: BgIOThreadPool #1]: D/negotiateauth nsHttpNegotiateAuth::GenerateCredentials() [challenge=Negotiate]
[Parent 21580: BgIOThreadPool #1]: D/negotiateauth entering nsAuthGSSAPI::GetNextToken()
[Parent 21580: BgIOThreadPool #1]: D/negotiateauth gss_init_sec_context() failed: Unspecified GSS failure. Minor code may provide more information
SPNEGO cannot find mechanisms to negotiate
[Parent 21580: BgIOThreadPool #1]: D/negotiateauth leaving nsAuthGSSAPI::GetNextToken [rv=80004005]
这可能是 KDC 的名称解析问题吗?我目前只有主机名,/etc/hosts
尚未在 DNS 中注册。
答案1
您正在使用 Ubuntu,它通过其 Snap 沙盒系统提供 Firefox。它是一种已知问题Kerberos 目前无法在 Firefox 的 Snap 包中使用,最简单的解决方法是将其替换为apt
仍然可用的包。
snap remove firefox
apt install firefox
但更具体地说,当程序认为您没有任何 Kerberos 凭据(并且没有 Kerberos,则只剩下空的 GSSAPI 机制列表)时,就会出现 GSSAPI 错误消息“SPNEGO 找不到要协商的机制”。
发生这种情况的原因是您的默认 Kerberos 票证缓存位置位于 /tmp,而 snapd 为每个应用程序提供了一个独立的 /tmp 实例,从而阻止它们看到相同的文件。您可以通过file:///tmp
在 Firefox 中访问或在 中四处查看来验证这一点snap run --shell firefox
。
(我没有研究过 Chromium,但我预计它会是几乎相同的问题。)
但是 Snapd 允许访问 /home;至少 Firefox snap 特别连接了正确的权限(“插件”),可以自动获得主目录访问权限。因此,您可以通过将票证缓存移动到主目录来解决此问题 - 通过以下方式之一:
export KRB5CCNAME="FILE:$HOME/krb5cc"
或者在系统范围内,通过编辑/etc/krb5.conf
说:
[libdefaults]
default_ccache_name = FILE:/home/%{username}/krb5cc
请注意,Snapd 使用 AppArmor 来精确限制应用程序可以访问的路径,并且其生成的 AppArmor 配置文件在授予主访问权限时明确排除“顶层隐藏目录”,因此允许 ~/krb5cc 但不允许 ~/.cache/krb5cc。
(您可能不喜欢特定的“/home/USER”布局在您的 krb5.conf 中被硬编码,因为它不能引用 $HOME 也不能查找类似 %{home}/krb5cc 的内容……但这并不重要,因为 AppArmor 已经存在同样的问题;它的配置文件也硬编码 /home。)
另一种选择是使用“运行时目录” FILE:/run/user/%{uid}/krb5cc
,但不幸的是 AppArmor 也不允许这样做。
(此外,运行dmesg
实际上揭示了一些与 /etc/gss/mech.d 相关的 AppArmor 拒绝,但这对 Kerberos 来说并不是一个真正的问题;该路径只会由 gss-ntlmssp 使用。)
解决此问题后,您可能会遇到另一个问题:Firefox snap 捆绑了自己的 Kerberos 库而不是使用系统库(与 Docker 非常相似,这被视为一项功能,允许 snap 潜在地提供比系统更新的库),但不包括k5tls.so
krb5 通过 HTTPS 访问 KDCs(即使用 MS-KKDCP 协议)所需的插件。
因此,如果您的领域有 DNS URI 记录表明 KKDCP 是唯一选项(而不是明文 TCP 或 UDP),那么如果没有 k5tls 插件,krb5 将无法与 KDC 通信。(当找到 URI 记录时,即使存在明文 TCP/UDP 的 SRV 记录,它也不会回退到使用 SRV 记录。)
如果这成为一个问题,可以通过强制回退到 SRV(或可以设置静态 KDC 主机名)来禁用 URI 记录查找/etc/krb5.conf
,但这只有在该领域的 KDC 确实可以通过明文访问时才有用。似乎没有好的方法可以在 Snap 容器内实际包含其他文件(更不用说这可能导致的版本不匹配),因此如果该领域专门使用 TLS/KKDCP(就像 Azure AD Kerberos 那样),那么直接使用 Snap 会更容易,而apt install firefox krb5-k5tls
不是与 Snap 搏斗。
答案2
无论从哪里安装(Snap、Flatpak、DEB 等等),都可以在所有浏览器中运行此功能。
计划如下:
- 将凭证缓存移至 $HOME 内并对用户隐藏,以免他们无意中删除它;
- 为浏览器创建策略以信任我们的公司域;
- ...
- 利润!
同时,我们也希望能够在企业环境中保证这一点易于管理——无需用户采取任何操作,一切就可以正常运转。
移动凭证缓存
更改存储每个用户凭证缓存的路径。这假设您的用户主目录遵循 /home/<name> 模式:
sudo sed -i '/\[libdefaults\]/a default_ccache_name = FILE:/home/%{username}/krb5cc' /etc/krb5.conf
确保该文件对于任何首次登录的用户都是隐藏的:
echo krb5cc | sudo tee -a /etc/skel/.hidden
也可以将其隐藏在您当前的用户帐户中:
echo krb5cc | tee -a ${HOME}/.hidden
您需要对已登录机器的任何用户重复此操作,因为仅在第一次身份验证时读取 /etc/skel 中的文件。
创建浏览器策略
火狐
创建系统范围配置的目录:
sudo mkdir -p /etc/firefox/policies
将 JSON 策略文档拖放到该路径:
echo '{"policies": {"Authentication": {"SPNEGO": ["internal.example.com"], "AllowProxies": {"SPNEGO": true}, "Locked": true, "PrivateBrowsing": true}}}' \
| sudo tee /etc/firefox/policies/policies.json
将 internal.example.com 替换为您的域名。请勿使用通配符,所有子域均隐式包含在内。如果您不想将整个域列入白名单,请将每个子域添加到列表中:["hr.internal.example.com", "intranet.internal.example.com", ...]
如果您已经在域中部署了 strategies.json,请将上述更改合并到现有文件中,不要覆盖它。
重新启动 Firefox 并检查以下位置的有效策略:关于:政策。
注销或重新启动计算机并重新登录。单点登录现在应该可以在 Firefox 中运行。
Chromium 和 Google Chrome
创建管理策略的目录:
sudo mkdir -p /etc/chromium-browser/policies/{managed,recommended}
sudo mkdir -p /etc/opt/chrome; sudo ln -s /etc/chromium-browser/policies /etc/opt/chrome/
创建策略文档:
echo '{ "AuthServerAllowlist": "*.internal.example.com" }' \
| sudo tee /etc/chromium-browser/policies/managed/auth_server_whitelist.json
将 internal.example.com 替换为您的域名。此处支持星号,因此子域会自动受信任。如果您想明确命名每个子域,请将其替换为列表 - 就像您对 Firefox 所做的那样。
重新启动浏览器并检查有效策略chrome://policy。
退出桌面会话并重新登录。SSO 现在应该可以在所有基于 Chromium 的浏览器中运行。
我已经在 Kubuntu 22.04 上进行了测试,使用从 Snap 商店和 DEB 包安装的浏览器进行了测试。