如何在 NGINX 入口后面的 Keycloak 中更改前端 URL?

问题描述

我可以在互联网上找到很多这样的问题,但提供的解决方案都没有奏效。

我正在使用 jboss/keycloak:14.0.0 泊坞窗图像。在我的 ConfigMap 中设置了以下属性

KEYCLOAK_FRONTEND_URL: /mycontext/access-management
PROXY_ADDRESS_FORWARDING: "true"

请注意,将 KEYCLOAK_FRONTEND_URL 更改为这样的绝对网址 https://mycompany.com/mycontext/access-managemen 没有任何区别。

现在入口定义如下:

Path: /mycontext/access-management(/|$)(.*)
Rewrite To: /$2
Annotations:
    ingress.kubernetes.io/ssl-redirect: "False"
    kubernetes.io/ingress.class: Nginx
    Nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header X-Request-ID $request_id;
      proxy_set_header X-Trace-ID $request_id;
      gzip off;
    Nginx.ingress.kubernetes.io/proxy-connect-timeout: "180"
    Nginx.ingress.kubernetes.io/proxy-read-timeout: "180"
    Nginx.ingress.kubernetes.io/proxy-send-timeout: "180"
    Nginx.ingress.kubernetes.io/rewrite-target: /$2
    Nginx.ingress.kubernetes.io/server-snippet: |
      add_header X-Request-ID $request_id;
      add_header X-Trace-ID $request_id;
    Nginx.org/redirect-to-https: "True"

发生的事情很奇怪。见下文,它显示了当我点击 URL 时我会带我去哪里:

Go to [server]/mycontext/access-management =takes you to=> [server]/auth
Go to [server]/mycontext/access-management/auth =takes you to=> [server]/mycontext/access-management/auth (works fine)

如您所见,第二个链接工作正常,您可以看到 Keycloak 欢迎页面,其中包含许多链接。其中一个链接是已损坏的 Administration Console。如果您将鼠标悬停,链接[server]/mycontext/access-management/admin 而不是 [server]/mycontext/access-management/auth/admin(与我本地的 Keycloak 服务器相比)。现在,如果我们忽略该链接并将正确的路径放在地址栏中作为 [server]/mycontext/access-management/auth/admin 另一件奇怪的事情发生,这将 URL 更改为 [server]/auth/mycontext/access-management/admin/master/console/

我真的不明白这里发生了什么。在我的本地设置 KEYCLOAK_FRONTEND_URL 也会破坏链接

我已尝试将入口的 rewrite 注释更改为 /mycontext/access-management/$2,但此配置根本不起作用。

在 Keycloak 文档 here 中,它谈到了一个名为 adminUrl属性,但是,设置 -DadminUrl-Dkeycloak.adminUrl 似乎在使用 { {1}} 根据 JBoss 文档页面

在这里错过了什么?我的配置中是否有遗漏的地方?

请注意,我们别无选择,只能将其暴露在后跟名称的上下文路径下(即 JAVA_OPTS_APPEND)。这是因为我们的客户要求以及我们在 /mycontext/access-management 下部署了许多微服务,每个微服务都有自己的入口配置。

感谢任何帮助。

解决方法

好的,我通过收集那里提到的所有解决方案设法让它发挥作用。

所以基本上,web-context 需要设置,除了口耳相传之外,任何文档中都没有提到这一点。

要设置它,您可以编写一个 cli 脚本:

set CONTEXT=${env.KEYCLOAK_WEB_CONTEXT}
echo $CONTEXT
embed-server --server-config=standalone-ha.xml --std-out=echo
/subsystem=keycloak-server/:write-attribute(name=web-context,value=$CONTEXT)
stop-embedded-server

embed-server --server-config=standalone.xml --std-out=echo
/subsystem=keycloak-server/:write-attribute(name=web-context,value=$CONTEXT)
stop-embedded-server

这被提到了 here 但重要的是 1. 你需要启动嵌入服务器否则没有服务器可以连接到第二个你应该同时更改 standalone.xmlstandalone-ha.xml 除非你知道你正在运行哪一个。

请参阅此答案 here,了解如何将自定义脚本复制到您的 docker 映像。

但是,这里有一点很重要!尽管 Keycloak 文档说您可以将前端 URL 更改为您想要的任何内容,但实际上您必须在新 URL 的末尾添加 /auth。 Keycloak 中的许多页面似乎都硬编码到该路径

现在您需要在 ConfigMap 中设置这两个属性:

#ConfigMap
# Has to end with /auth and has to be absolute URL
KEYCLOAK_FRONTEND_URL: https://your.website.address/mycontext/access-management/auth
PROXY_ADDRESS_FORWARDING: "true"
# The following is our own env var that will be used by the above cli
# Note that it SHOULD NOT start with / and it must END with /auth
KEYCLOAK_WEB_CONTEXT: mycontext/access-management/auth

这有点烦人,因为 KEYCLOAK_FRONTEND_URL 不能是相对路径,必须是完整的绝对 URL。问题是你的构建使事情变得不美好和优雅。幸运的是,我们在 host 中有一个 global 属性并且在 Helm 的子图表之间共享,所以我可以使用它,但实际上这使得设计有点讨厌。

但不仅如此,由于所有这些垃圾设置,现在您必须将 livenessreadiness 探针更改为 GET /mycontext/access-management 更糟糕的是,如果您有微服务(对我们来说将近 20 个),您需要将所有以前像 http://access-management:8080/auth 一样简单的身份验证服务器 URL 更改为 http://access-management:8080/mycontext/access-management/auth

现在确保您的入口还包含此新路径以及另一个重要属性 proxy-buffer-size。如果您没有大的缓冲区大小,Keycloak 请求可能无法工作,您将收到 Bad Gateway 错误:

Path: /mycontext/access-management(/|$)(.*)
Rewrite To: /mycontext/access-management/$2
nginx.ingress.kubernetes.io/proxy-buffer-size: 8k 

我真的希望我们可以通过 ingress 来管理它,而不必触及所有这些东西,但这似乎是不可能的。我希望 Keycloak.X 能解决所有这些糟糕的编码问题。