Firefox 和 Chromium 不进行 Kerberos 协商,而 cURL 进行?

Firefox 和 Chromium 不进行 Kerberos 协商,而 cURL 进行?

我可以成功运行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.sokrb5 通过 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 等等),都可以在所有浏览器中运行此功能。

计划如下:

  1. 将凭证缓存移至 $HOME 内并对用户隐藏,以免他们无意中删除它;
  2. 为浏览器创建策略以信任我们的公司域;
  3. ...
  4. 利润!

同时,我们也希望能够在企业环境中保证这一点易于管理——无需用户采取任何操作,一切就可以正常运转。

移动凭证缓存

更改存储每个用户凭证缓存的路径。这假设您的用户主目录遵循 /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 包安装的浏览器进行了测试。

相关内容