使用Docker镜像设置Keycloak SSL

15

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

根据文档:

Keycloak镜像允许您指定用于提供HTTPS的私钥和证书。在这种情况下,您需要提供两个文件:

tls.crt - 证书 tls.key - 私钥 这些文件需要挂载到 /etc/x509/https 目录中。该镜像将自动将它们转换为Java密钥库并重新配置Wildfly以使用它。

我按照给定的步骤提供了卷绑定设置及包含必要文件 (tls.crt 和 tls.key) 的文件夹,但是在 SSL 握手时出现问题,浏览器阻止 keycloak 加载并显示

ERR_SSL_VERSION_OR_CIPHER_MISMATCH

错误信息。

我使用 letsencrypt 生成 pem 文件,并使用 openssl 创建了 .crt 和 .key 文件。也尝试仅使用 openssl 创建这些文件来缩小问题范围,但行为相同(一些额外信息,如果有必要)

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

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


在docker-compose中使用ports: - 8443:8443但不挂载/etc/x509/https卷对我起作用了。Keycloak创建了自己的证书... - Doctor
1
是的,但我们希望我们的证书(例如:LetsEncrypt证书)能够就位。 - Vsoma
是的 :-) ... 但我需要一些简单的 HTTPS 可用性,你的解决方案让 Keycloak 自动生成它们,非常适合初学者!顺便问一下,您知道证书是在哪里生成的吗?现在 Kubernetes 需要公钥来与 Keycloak 通信... - Doctor
当然,您可以使用exec命令来找到它,但更简单的方法是通过浏览器下载并将其导入到信任存储中。 - Vsoma
3个回答

32

我曾遇到使用jboss/keycloak Docker镜像letsencrypt免费证书时出现ERR_SSL_VERSION_OR_CIPHER_MISMATCH错误的问题。即使考虑了其他评论中给出的建议,问题仍未得到解决。现在,我有一个可用且易于设置的环境,这可能也能帮到你。

1)生成letsencrypt证书

首先,我使用certbot为域名sub.example.com生成了我的letsencrypt证书。你可以在https://certbot.eff.org/找到详细的说明和获取证书的其他方法,以及用户指南在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-compose 在 Docker 中运行 keycloak。配置和数据文件存储在路径 /srv/docker/keycloak/ 中。

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

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

当我第一次使用原始的 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

根据docker-compose.yml的设置,keycloak现在可以在https://sub.example.com:8443访问。


是的,我后来弄清楚了,需要进行相当多的研究!最终,当我的目标是将所有内容部署到GKP上时,我最终使用了ManagedCertificate,它可以干净地处理证书和更新!! - Vsoma
使用此答案中描述的已挂载的 data/certs 文件夹,我成功地将 tls.* 权限设置为 655,运行 Docker,然后将权限更改回 600,从而使其正常工作。这是基于 此问题 的答案。 - shaqb4
1
就像@shaqb4所说的那样,我也不得不执行chmod 655 /srv/docker/keycloak/data/certs/*,否则“通过OpenShift的服务提供x509证书密钥库”创建HTTPS密钥库将失败。 - Rocco
给予“chmod 655”已经解决了我的“HTTPS密钥库未创建于:/opt/jboss/keycloak/standalone/configuration/keystores/https-keystore.jks(检查权限?)”问题。谢谢@Rocco,shaqb4的帮助。 - srt
这对我很有效。chmod 655 /srv/docker/keycloak/data/certs/* 很重要。 - sohammondal

12

经过一些研究,以下方法起作用了(对于自签名证书,我仍然需要弄清楚如何处理letsencrypt CA才能在生产环境中使用)

使用keytool生成自签名证书

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

将.jks文件转换为.p12文件

keytool -importkeystore -srckeystore keycloak.jks -destkeystore keycloak.p12 -deststoretype PKCS12
从 .p12 keystore 生成 .crt。
openssl pkcs12 -in keycloak.p12 -nokeys -out tls.crt

从 .p12 密钥库生成 .key 文件

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>",

我已经成功地使用letsencrypt证书运行了它,只需要将.pem文件转换为.crt和.key文件,并通过中间转换生成.pk12文件。 - Vsoma
嗨,你是怎么做到的?我也遇到了同样的问题,但是使用中间的.p12创建.crt和.key没有起作用,我仍然收到ERR_SSL_VERSION_OR_CIPHER_MISMATCH错误。谢谢。 - lbaggi
尝试以下操作:
  1. openssl pkcs12 -export -out pkcskeystore.pkcs12 -in cert.pem -inkey privkey.pem
  2. keytool -importkeystore -destkeystore keystore.jks -srckeystore pkcskeystore.pkcs12 -srcstoretype PKCS12
  3. 然后按照答案中的“将 .jks 转换为 .p12”部分进行操作。
- Vsoma
我也遇到了这个问题。不幸的是,你提供的所有答案对我都没有用。你还有其他的想法吗?我也遇到了ERR_SSL_VERSION_OR_CIPHER_MISMATCH。如果你能帮忙解决,我将非常感激!另外,keycloak.json文件在哪里? - Bloodlex

7

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

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

遗憾的是,此脚本不考虑密码。但是,通过在Docker构建时进行一些修改,您可以自己解决这个问题: 在您的Dockerfile中添加以下内容:

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版本中经过测试。

1
如果仍然无法正常工作,而且您不知道原因,请使用“RUN sed -i -e 's|>& /dev/null||g' /opt/jboss/tools/x509.sh”来启用x509.h的诊断输出。 - Battlefury

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