使用 docker 图片的 Keycloak SSL 设置

Keycloak SSL setup using docker image

我正在尝试使用 docker 映像(https://hub.docker.com/r/jboss/keycloak/ 版本 4.5.0-Final)部署 keycloak,但遇到了设置 SSL 的问题。

根据文档

Keycloak image allows you to specify both a private key and a certificate for serving HTTPS. In that case you need to provide two files:

tls.crt - a certificate tls.key - a private key Those files need to be mounted in /etc/x509/https directory. The image will automatically convert them into a Java keystore and reconfigure Wildfly to use it.

我按照给定的步骤提供了卷安装设置,其中包含一个包含必要文件的文件夹(tls.crt 和 tls.key),但我遇到了 SSL 握手问题,得到

ERR_SSL_VERSION_OR_CIPHER_MISMATCH

错误,尝试访问时在浏览器中阻止 keycloak 加载。

我已经使用 letsencrypt 生成 pem 文件并使用 openssl 创建 .crt 和 .key 文件。 还尝试只用 openssl 来创建这些文件以缩小问题范围并且行为是相同的(如果这很重要,还有一些附加信息)

默认情况下,当我仅指定端口绑定时 -p 8443:8443 而未指定证书卷挂载 /etc/x509/https keycloak 服务器生成一个自签名证书,我在浏览器中查看应用程序时没有看到问题

我想这可能更多的是证书创建问题,而不是特定于 keycloak 的任何问题,但是,不确定如何让它工作。 感谢任何帮助

经过一番研究,以下方法奏效了(对于自签名证书,我仍然需要弄清楚如何使用 letsencrypt CA for prod)

generate a self-signed cert using the keytool

keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950

convert .jks to .p12

keytool -importkeystore -srckeystore keycloak.jks -destkeystore keycloak.p12 -deststoretype PKCS12

generate .crt from .p12 keystore

openssl pkcs12 -in keycloak.p12 -nokeys -out tls.crt

generate .key from .p12 keystore

openssl pkcs12 -in keycloak.p12 -nocerts -nodes -out tls.key

然后使用tls.crt和tls.key进行卷挂载/etc/x509/https

此外,在安全应用程序中,在 keycloak.json 文件中指定以下属性

"truststore" : "path/to/keycloak.jks",
"truststore-password" : "<jks-pwd>",

我还遇到了使用 jboss/keycloak Docker image and free certificates from letsencrypt 出现 ERR_SSL_VERSION_OR_CIPHER_MISMATCH 错误的问题。即使在考虑了其他评论的建议之后。现在,我有一个工作(而且非常简单)的设置,它也可以帮助你。

1) 生成 letsencrypt 证书

首先,我使用 certbot 为域 sub.example.com 生成了我的 letsencrypt 证书。您可以在 https://certbot.eff.org/ and the user guide at https://certbot.eff.org/docs/using.html.

找到详细说明和获得证书的替代方法
$ sudo certbot certonly --standalone
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c' to cancel): sub.example.com
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for sub.example.com
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/sub.example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/sub.example.com/privkey.pem
   Your cert will expire on 2020-01-27. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"

2) 准备docker-compose环境

我通过 docker 使用 docker-compose 到 运行 keycloak。配置和数据文件存储在路径 /srv/docker/keycloak/ 中。

  • 文件夹 config 包含 docker-compose.yml
  • 文件夹data/certs包含我通过letsencrypt
  • 生成的证书
  • 文件夹 data/keycloack_db 映射到数据库容器以使其数据持久化。

将证书文件放到正确的路径

当我第一次使用 keycloak 的原始 letscrypt 证书时遇到问题,我尝试了将证书转换为另一种格式的解决方法,如前一个答案的评论中所述,但也失败了。最终,我意识到我的问题是由映射证书文件的权限设置引起的。

所以,对我有用的是复制并重命名 letsencrypt 提供的文件,然后将它们挂载到容器中。

$ cp /etc/letsencrypt/live/sub.example.com/fullchain.pem /srv/docker/keycloak/data/certs/tls.crt
$ cp /etc/letsencrypt/live/sub.example.com/privkey.pem /srv/docker/keycloak/data/certs/tls.key
$ chmod 755 /srv/docker/keycloak/data/certs/
$ chmod 604 /srv/docker/keycloak/data/certs/*

docker-compose.yml

就我而言,我需要使用 docker 主机的主机网络。这不是最佳做法,您的情况不需要这样做。请在 hub.docker.com/r/jboss/keycloak/.

的文档中查找有关配置参数的信息
version: '3.7'

networks:
  default:
    external:
      name: host

services:
  keycloak:
    container_name: keycloak_app
    image: jboss/keycloak
    depends_on:
      - mariadb
    restart: always
    ports:
      - "8080:8080"
      - "8443:8443"
    volumes:
      - "/srv/docker/keycloak/data/certs/:/etc/x509/https"   # map certificates to container
    environment:
      KEYCLOAK_USER: <user>
      KEYCLOAK_PASSWORD: <pw>
      KEYCLOAK_HTTP_PORT: 8080
      KEYCLOAK_HTTPS_PORT: 8443
      KEYCLOAK_HOSTNAME: sub.example.ocm
      DB_VENDOR: mariadb
      DB_ADDR: localhost
      DB_USER: keycloak
      DB_PASSWORD: <pw>
    network_mode: host

  mariadb:
    container_name: keycloak_db
    image: mariadb
    volumes:
      - "/srv/docker/keycloak/data/keycloak_db:/var/lib/mysql"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: <pw>
      MYSQL_DATABASE: keycloak
      MYSQL_USER: keycloak
      MYSQL_PASSWORD: <pw>
    network_mode: host

最终目录设置

这是我最终的文件和文件夹设置的样子。

$ cd /srv/docker/keycloak/
$ tree
.
├── config
│   └── docker-compose.yml
└── data
    ├── certs
    │   ├── tls.crt
    │   └── tls.key
    └── keycloak_db

启动容器

最后,我可以使用 docker-compose 启动我的软件了。

$ cd /srv/docker/keycloak/config/
$ sudo docker-compose up -d

我们可以在容器中看到挂载的证书。

$ cd /srv/docker/keycloak/config/
$ sudo docker-compose up -d

我们可以仔细检查容器中安装的证书。

## open internal shell of keycloack container
$ sudo docker exec -it keycloak_app /bin/bash

## open directory of certificates
$ cd /etc/x509/https/
$ ll
-rw----r-- 1 root root 3586 Oct 30 14:21 tls.crt
-rw----r-- 1 root root 1708 Oct 30 14:20 tls.key

考虑运行g 来自 docker-compose.yml 的设置,keycloak 现在可在 https://sub.example.com:8443

对于任何试图 运行 使用 密码保护私钥文件 Keycloak 的人:

Keycloak 运行s 脚本 /opt/jboss/tools/x509.sh 根据 /etc/x509/https 中提供的文件生成密钥库,如 https://hub.docker.com/r/jboss/keycloak - 设置 TLS(SSL) 中所述。

不幸的是,这个脚本没有考虑密码。但是在 Docker 构建时稍作修改,您可以自己修复它: 在您的 Docker 文件中添加:

RUN sed -i -e 's/-out "${KEYSTORES_STORAGE}\/${PKCS12_KEYSTORE_FILE}" \/-out "${KEYSTORES_STORAGE}\/${PKCS12_KEYSTORE_FILE}" \\n      -passin pass:"${SERVER_KEYSTORE_PASSWORD}" \/' /opt/jboss/tools/x509.sh

此命令修改脚本并附加参数以传入密码 -passin pass:"${SERVER_KEYSTORE_PASSWORD}"

参数的值是一个环境变量,您可以随意设置:SERVER_KEYSTORE_PASSWORD

使用 Keycloak 9.0.0 测试