如何在生产模式下配置仅使用http运行的Keycloak 18?

3
我有一个这样的情况,我运行 Keycloak 18.0.0 在一个反向代理后面,反向代理终止了安全(https)连接。因此,我想构建一个 Docker 镜像,将 Keycloak 配置为仅监听 http(例如端口8080)。
我已经调整了Keycloak文档中的Dockerfile配置。它使用:
  • MariaDB作为数据库
  • 启用健康和指标终端点
  • 由于我在反向代理中终止了TLS连接,所以在启动 Keycloak 时我还使用了--proxy=edge选项(请参见代理模式)。
FROM quay.io/keycloak/keycloak:18.0.0 as builder

ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true
ENV KC_DB=mariadb
# Install custom providers
RUN curl -sL https://github.com/aerogear/keycloak-metrics-spi/releases/download/2.5.3/keycloak-metrics-spi-2.5.3.jar -o /opt/keycloak/providers/keycloak-metrics-spi-2.5.3.jar
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:18.0.0
COPY --from=builder /opt/keycloak/ /opt/keycloak/
WORKDIR /opt/keycloak
ENTRYPOINT ["/opt/keycloak/bin/kc.sh", "start"]

我随后使用以下命令构建我的Docker镜像:
docker build --no-cache . -t ghcr.io/saw303/zscsupporter-be/keycloak-18.0.0:0.0.1

并在我的Docker组合中启动图像。
version: "3.9"
services:
  proxy:
    image: caddy:2.5.1-alpine
    ports:
      - "${PROXY_IP}:80:80"
      - "${PROXY_IP}:443:443"
    volumes:
      - ${BASE_PATH:-.}/docker-volume/caddy/Caddyfile:/etc/caddy/Caddyfile:Z
      - ${BASE_PATH:-.}/docker-volume/caddy/caddy_data:/data:Z
      - ${BASE_PATH:-.}/docker-volume/caddy/caddy_config:/config:Z
  
  keycloak:
    image: ghcr.io/saw303/zscsupporter-be/keycloak-18.0.0:0.0.1
    ports:
      - "127.0.0.1:9001:8080"
      - "127.0.0.1:9443:8443"
    environment:
      KC_HOSTNAME: localhost
      KC_HOSTNAME_PORT: 80
      KC_HOSTNAME_STRICT_BACKCHANNEL: true
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
      KC_DB_URL: jdbc:mariadb://keycloakdb:3306/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: secret
      KC_LOG_LEVEL: info
      KC_PROXY: edge

  keycloakdb:
    image: mariadb:10.7.3-focal
    environment:
      MYSQL_ROOT_PASSWORD: root_secret
      MYSQL_DATABASE: keycloak
      MYSQL_USER: keycloak
      MYSQL_PASSWORD: secret
      TZ: "Europe/Zurich"
    tmpfs:
      - /var/lib/mysql:rw
    ports:
      - "127.0.0.1:3307:3306"

当我使用以下命令启动Docker组合时:
docker compose up -d && docker compose logs -f keycloak

我收到了以下日志记录语句,明确表示它使用了严格的HTTPS
backend-keycloak-1  | 2022-05-29 17:37:46,922 INFO  [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: FrontEnd: localhost, Strict HTTPS: true, Path: <request>, Strict BackChannel: false, Admin: localhost, Port: 8,080, Proxied: true

当我访问管理控制台时
http://localhost:9001/admin/master/console/

我得到了一个空白页面,管理控制台只发送了一个请求。
http://localhost:9001/admin/master/console/config

这句话的意思是:返回错误的URL地址,其中包含了“https:”这个部分。
{
  "realm": "master",
  "auth-server-url": "https://localhost:8080/",
  "ssl-required": "external",
  "resource": "security-admin-console",
  "public-client": true,
  "confidential-port": 0
}

有没有办法将字段值auth-server-url中的协议从https更改为http
更新1:代理配置
我使用Caddy Server 2.0作为反向代理。在这个测试设置中,Caddy是Docker组合的一部分,并简单地将端口80上的所有请求重定向到端口8080上的keycloak容器。
{
  admin off
}

localhost:80

reverse_proxy /* keycloak:8080

log

请注意,无论我是通过反向代理 localhost:80 还是直接访问 localhost:9001,行为都是相同的。当通过代理访问时,我当然会更改端口值 KC_HOSTNAME_PORT: 80
更新2:在docker-compose.yml中设置KC_PROXY
现在在docker-compose.yml中设置了KC_PROXY环境变量,但行为仍然相同。当我进入运行中的keycloak容器时,我看到以下活动配置。

➜  docker compose exec keycloak bash
WARN[0000] The "PROXY_IP" variable is not set. Defaulting to a blank string. 
WARN[0000] The "PROXY_IP" variable is not set. Defaulting to a blank string. 
bash-4.4$ bin/kc.sh show-config
Current Mode: none
Runtime Configuration:
        kc.cache =  ispn (PersistedConfigSource)
        kc.config.args =  show-config (SysPropConfigSource)
        kc.db =  mariadb (PersistedConfigSource)
        kc.db.password =  secret (EnvConfigSource)
        kc.db.url =  jdbc:mariadb://keycloakdb:3306/keycloak (EnvConfigSource)
        kc.db.username =  keycloak (EnvConfigSource)
        kc.health-enabled =  true (PersistedConfigSource)
        kc.home.dir =  /opt/keycloak/bin/../ (SysPropConfigSource)
        kc.hostname =  localhost (EnvConfigSource)
        kc.hostname.port =  80 (EnvConfigSource)
        kc.hostname.strict.backchannel =  true (EnvConfigSource)
        kc.http-enabled =  false (PropertiesConfigSource[source=jar:file:///opt/keycloak/lib/lib/main/org.keycloak.keycloak-quarkus-server-18.0.0.jar!/META-INF/keycloak.conf])
        kc.http-relative-path =  / (PersistedConfigSource)
        kc.log-console-output =  default (PropertiesConfigSource[source=jar:file:///opt/keycloak/lib/lib/main/org.keycloak.keycloak-quarkus-server-18.0.0.jar!/META-INF/keycloak.conf])
        kc.log-file =  /opt/keycloak/bin/../data/log/keycloak.log (PropertiesConfigSource[source=jar:file:///opt/keycloak/lib/lib/main/org.keycloak.keycloak-quarkus-server-18.0.0.jar!/META-INF/keycloak.conf])
        kc.log.level =  info (EnvConfigSource)
        kc.metrics-enabled =  true (PersistedConfigSource)
        kc.provider.file.keycloak-metrics-spi-2.5.3.jar.last-modified =  1653899384311 (PersistedConfigSource)
        kc.proxy =  edge (EnvConfigSource)
        kc.quarkus-properties-enabled =  false (PersistedConfigSource)
        kc.show.config =  none (SysPropConfigSource)
        kc.version =  18.0.0 (SysPropConfigSource)

有趣的是,它表明HTTP被禁用了。
kc.http-enabled =  false (PropertiesConfigSource[source=jar:file:///opt/keycloak/lib/lib/main/org.keycloak.keycloak-quarkus-server-18.0.0.jar!/META-INF/keycloak.conf])

请展示您的代理配置。 - Jan Garaj
@JanGaraj 代理配置已添加。 - saw303
2个回答

2

我通过配置反向代理使用自签名证书,成功地在localhost上运行了它。

{
  admin off
}

localhost:443 {
        reverse_proxy keycloak:8080
        tls internal
}

log

Caddy 的神奇之处在于声明 tls internal

然后我将我的 Dockerfile 改为了这样:

FROM quay.io/keycloak/keycloak:18.0.0 as builder

ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true
ENV KC_FEATURES=token-exchange
ENV KC_DB=mariadb
RUN curl -sL https://github.com/aerogear/keycloak-metrics-spi/releases/download/2.5.3/keycloak-metrics-spi-2.5.3.jar -o /opt/keycloak/providers/keycloak-metrics-spi-2.5.3.jar
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:18.0.0
COPY --from=builder /opt/keycloak/ /opt/keycloak/
WORKDIR /opt/keycloak
ENTRYPOINT ["/opt/keycloak/bin/kc.sh", "start"]

并相应地修改我的docker-compose.yml文件。

version: "3.9"
services:
  proxy:
    image: caddy:2.5.1-alpine
    ports:
      - "${PROXY_IP}:80:80"
      - "${PROXY_IP}:443:443"
    volumes:
      - ${BASE_PATH:-.}/docker-volume/caddy/Caddyfile:/etc/caddy/Caddyfile:Z
      - ${BASE_PATH:-.}/docker-volume/caddy/caddy_data:/data:Z
      - ${BASE_PATH:-.}/docker-volume/caddy/caddy_config:/config:Z

  keycloak:
    image: ghcr.io/saw303/zscsupporter-be/keycloak-18.0.0:0.0.1
    ports:
      - "127.0.0.1:9443:8443"
    restart: unless-stopped
    environment:
      KC_DB_URL: jdbc:mariadb://keycloakdb:3306/keycloak
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
      KC_HOSTNAME: localhost
      KC_HOSTNAME_STRICT: false
      KC_HTTP_ENABLED: true
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: secret
      KC_LOG_LEVEL: debug
      KC_PROXY: edge

  keycloakdb:
    image: mariadb:10.7.3-focal
    environment:
      MYSQL_ROOT_PASSWORD: root_secret
      MYSQL_DATABASE: keycloak
      MYSQL_USER: keycloak
      MYSQL_PASSWORD: secret
      TZ: "Europe/Zurich"
    tmpfs:
      - /var/lib/mysql:rw
    ports:
      - "127.0.0.1:3307:3306"
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 200M

在进行这个配置后,可以成功访问Keycloak管理控制台。似乎不能通过非安全连接访问管理控制台。


4
嗨,@saw303,我刚看到你自己回答了......但是我上面的评论仍然有效;) 我是KC团队成员。我们知道我们有些失误,所以解释一下:是的,在生产模式下,我们希望实现“安全设计”,因此即使您使用proxy=edge或http-enabled=true,您也必须将hostname-strict-https=false设置为false。如果您不这样做,唯一的另一种方式就是像您在这里做的那样,基本上是将http重定向到https或添加另一个内部证书。Github存储库中正在进行讨论,我希望在下一个主要版本中我们能提供更好的体验。 :) - Dominik
你也可以查看这个链接:https://keycloak.discourse.group/t/kc-17-x-x-how-to-access-admin-ui-from-port-forwarded-internal-url-prevent-redirect-from-internal-url-to-kc-hostname/14917/9 - Edwin

0

看起来你的Keycloak实例没有使用--proxy=edge配置。

尝试官方文档语法:--proxy edge(当然要翻译成Dockerfile语法),或者更简单的选项是设置Keycloak容器环境变量KC_PROXY: edge


通过��境变量设置代理具有相同的效果。我在运行时将Keycloak配置添加到了我的问题中(请参见更新2)。 - saw303
@saw303 所以 KC_HTTP_ENABLED: "true" - Jan Garaj
另一个有趣的事情是,我无法使用conf/keycloak.conf中的kc.spi-hostname-default-strict-https=false覆盖该值。它一直返回true - saw303
KC_HTTP_ENABLED: "true"也没有改变行为。我有点迷失了。 - saw303
1
@saw303,设置KC_PROXY=edgeKC_HOSTNAME_STRICT_HTTPS=false应该可以解决问题。 - Dominik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接