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

How to configure Keycloak 18 running http only in production mode?

我的情况是 运行 Keycloak 18.0.0 在终止安全 (https) 连接的反向代理后面。因此,我想构建一个 Docker 图像,将 Keycloak 配置为仅侦听 http(例如端口 8080)。

我已经将 Keycloak documentation 调整为 Dockerfile。它使用

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

哪些 returns 错误的 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 访问 Keycloak 管理控制台,行为都是一样的。通过代理访问的时候当然要改端口值KC_HOSTNAME_PORT: 80.

更新2:在docker-compose.yml

中设置KC_PROXY

KC_PROXY env 变量现在设置在 docker-compose.yml 中,但行为是相同的。当我跳入 运行ning 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])

您的 Keycloak 实例似乎没有使用 --proxy=edge 配置。

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

我通过将反向代理配置为使用 self-signed 证书,设法在 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 管理控制台了。似乎无法使用非安全连接访问管理控制台。