Keycloak SSL续订certbot证书

时间:2020-10-04 18:24:15

标签: docker ssl keycloak keycloak-services

我有一个与certbot创建的证书一起使用的密钥库(docker)SSL系统,但是在续订证书后,密钥库实例仍显示无效的过期证书。 我已经使用openssl检查过我创建的证书是有效的并且位于/ etc / x509 / https文件夹中。对文件的权限很好。 我什至尝试了以下方法,但没有任何强制要求它领取新证书

  1. 重新启动密钥斗篷
  2. 登录keycloak docker实例并运行/opt/jboss/tools/x509.sh-它说它重新生成了一组新文件,但日期戳似乎暗示它仍然是旧的.jks和.pk12
  3. 将这些文件从/ opt / jboss / keycloak / standalone / configuration / keystores中移到新的临时文件夹中,然后再次运行x509.sh,并创建了两个新文件。我重新启动了Docker实例-但再次它仍然显示旧的证书日期

任何人都知道为什么不刷新旧证书?我相信这是一个关键问题而不是certbot。 任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

最简单的解决方案是删除容器,但这并不总是可取的。但是,还有另一种方法。

AFAIK, x509.sh 应该在每个容器寿命内仅运行一次。您可以查看存储库上的docker-entrypoint.sh,以验证 x509.sh 是否仅在容器初始化时运行,而不再运行。在以前的 docker-entrypoint.sh 版本中, x509.sh 在每次启动时都运行,但是尽管有打印消息,但它却什么也不做。

当前的x509.sh版本正在实现以下步骤:

  • 生成随机密码:

    local PASSWORD=$(openssl rand -base64 32 2>/dev/null)
    
  • 使用openssl创建PKCS12密钥库:

    openssl pkcs12 -export \
    -name "${NAME}" \
    -inkey "${X509_KEYSTORE_DIR}/${X509_KEY}" \
    -in "${X509_KEYSTORE_DIR}/${X509_CRT}" \
    -out "${KEYSTORES_STORAGE}/${PKCS12_KEYSTORE_FILE}" \
    -password pass:"${PASSWORD}" >& /dev/null
    
  • 使用keytool从PKCS12创建一个JKS密钥库:

    keytool -importkeystore -noprompt \
    -srcalias "${NAME}" -destalias "${NAME}" \
    -srckeystore "${KEYSTORES_STORAGE}/${PKCS12_KEYSTORE_FILE}" \
    -srcstoretype pkcs12 \
    -destkeystore "${KEYSTORES_STORAGE}/${JKS_KEYSTORE_FILE}" \
    -storepass "${PASSWORD}" -srcstorepass "${PASSWORD}" >& /dev/null
    
  • 为Keycloak配置JKS密钥库:

    $JBOSS_HOME/bin/jboss-cli.sh --file=/opt/jboss/tools/cli/x509-keystore.cli >& /dev/null
    

如果您修改 x509.sh 并删除所有对 / dev / null 的重定向,您应该会看到类似以下内容:

Creating HTTPS keystore via OpenShift's service serving x509 certificate secrets..
Importing keystore /opt/jboss/keycloak/standalone/configuration/keystores/https-keystore.pk12 to /opt/jboss/keycloak/standalone/configuration/keystores/https-keystore.jks...
keytool error: java.io.IOException: keystore password was incorrect
HTTPS keystore successfully created at: /opt/jboss/keycloak/standalone/configuration/keystores/https-keystore.jks
{
    "outcome" => "failed",
    "failure-description" => "WFLYCTL0212: Duplicate resource [
    (\"subsystem\" => \"elytron\"),
    (\"key-store\" => \"kcKeyStore\")
]",
    "rolled-back" => true
}
{
    "outcome" => "failed",
    "failure-description" => "WFLYCTL0212: Duplicate resource [
    (\"subsystem\" => \"elytron\"),
    (\"key-store\" => \"kcKeyStore\")
]",
    "rolled-back" => true
}

它无法使用 jboss-cli.sh 修改Keycloak配置。如果仅删除密钥库,然后运行 x509.sh ,则新随机生成的密码将与Keycloak配置文件中的密码不同。由于 x509-keystore.cli 试图添加参数,而不是对其进行更新,因此密钥库中的密码和配置中的密码不匹配。

这里是 x509.sh 的替代版本,仅当其关键点在下面公开时才可以续订:

  • 从Keycloak配置中提取当前使用的密码:

    local PASSWORD=$(/opt/jboss/keycloak/bin/jboss-cli.sh --connect --output-json '/subsystem=elytron/key-store=kcKeyStore:read-attribute(name="credential-reference")' |sed -rn 's;.+"result" *: *\{"clear-text" *: *"([^"]+)".*;\1;p')
    
  • 从Keycloak配置中提取JKS密钥库路径:

    local JKS_KEYSTORE_PATH=$(/opt/jboss/keycloak/bin/jboss-cli.sh --connect --output-json '/subsystem=elytron/key-store=kcKeyStore:read-attribute(name="path")' |sed -rn 's;.+"result" *: *"([^"]+https[^"]+)".*;\1;p')
    
  • 假定PKCS12密钥库的扩展名有所不同:

    local PKCS12_KEYSTORE_PATH=${JKS_KEYSTORE_PATH%.*}.pk12
    
  • 现在您知道密码和密钥库路径,请更新PKCS12密钥库:

    openssl pkcs12 -export \
    -name "${NAME}" \
    -inkey "${X509_KEYSTORE_DIR}/${X509_KEY}" \
    -in "${X509_KEYSTORE_DIR}/${X509_CRT}" \
    -out "${PKCS12_KEYSTORE_PATH}" \
    -password pass:"${PASSWORD}"
    
  • 最终更新JKS:

    keytool -importkeystore -noprompt \
    -srcalias "${NAME}" -destalias "${NAME}" \
    -srckeystore "${PKCS12_KEYSTORE_PATH}" \
    -srcstoretype pkcs12 \
    -destkeystore "${JKS_KEYSTORE_PATH}" \
    -storepass "${PASSWORD}" -srcstorepass "${PASSWORD}"
    

完整脚本:

  function check_var() {
    local name=$1
    local value=$2
  
    if [ -z "$value" ]; then
      echo "$name is not defined."
      exit 1
    fi
  }
  
  function autoregenerate_keystore() {
    # Keystore infix notation as used in templates to keystore name mapping
    declare -A KEYSTORES=( ["https"]="HTTPS" )
  
    local KEYSTORE_TYPE=$1
    check_var "KEYSTORE_TYPE" $KEYSTORE_TYPE
  
    # reading password from configuration
    local PASSWORD=$(/opt/jboss/keycloak/bin/jboss-cli.sh --connect --output-json '/subsystem=elytron/key-store=kcKeyStore:read-attribute(name="credential-reference")' |sed -rn 's;.+"result" *: *\{"clear-text" *: *"([^"]+)".*;\1;p')
    check_var "PASSWORD" $PASSWORD
  
    # reading jks keystore path from configuration
    local JKS_KEYSTORE_PATH=$(/opt/jboss/keycloak/bin/jboss-cli.sh --connect --output-json '/subsystem=elytron/key-store=kcKeyStore:read-attribute(name="path")' |sed -rn 's;.+"result" *: *"([^"]+'$KEYSTORE_TYPE'[^"]+)".*;\1;p')
    check_var "JKS_KEYSTORE_PATH" $JKS_KEYSTORE_PATH
  
    if [ ! -f "${JKS_KEYSTORE_PATH}" ]; then
      echo "JKS keystore file does not exist!"
      exit 1
    fi
  
    # supposing that keystores were generated by x509.sh, hence pk12 keystore is in the same location.
    local PKCS12_KEYSTORE_PATH=${JKS_KEYSTORE_PATH%.*}.pk12
  
    if [ ! -f "${PKCS12_KEYSTORE_PATH}" ]; then
      echo "PKCS12 keystore file does not exist!"
      exit 1
    fi
  
    local X509_KEYSTORE_DIR="/etc/x509/${KEYSTORE_TYPE}"
    local X509_CRT="tls.crt"
    local X509_KEY="tls.key"
  
    local NAME="keycloak-${KEYSTORE_TYPE}-key"
  
    if [ ! -f "${X509_KEYSTORE_DIR}/${X509_KEY}" ] || [ ! -f "${X509_KEYSTORE_DIR}/${X509_CRT}" ]; then
      echo "X509 files does not exist!"
      exit 1
    fi
  
    echo "Renewing ${KEYSTORES[$KEYSTORE_TYPE]} keystore via OpenShift's service serving x509 certificate secrets.."
  
    openssl pkcs12 -export \
    -name "${NAME}" \
    -inkey "${X509_KEYSTORE_DIR}/${X509_KEY}" \
    -in "${X509_KEYSTORE_DIR}/${X509_CRT}" \
    -out "${PKCS12_KEYSTORE_PATH}" \
    -password pass:"${PASSWORD}"
  
    keytool -importkeystore -noprompt \
    -srcalias "${NAME}" -destalias "${NAME}" \
    -srckeystore "${PKCS12_KEYSTORE_PATH}" \
    -srcstoretype pkcs12 \
    -destkeystore "${JKS_KEYSTORE_PATH}" \
    -storepass "${PASSWORD}" -srcstorepass "${PASSWORD}"
  }
  
  autoregenerate_keystore "https" 

例如,将其命名为 x509-renewal.sh 并将其复制到您的容器中:

$ docker cp x509-renewal.sh my-keycloak-container:/opt/jboss/tools/

然后运行它:

$ docker exec my-keycloak-container /opt/jboss/tools/x509-renewal.sh

Renewing HTTPS keystore via OpenShift's service serving x509 certificate secrets..
Importing keystore /opt/jboss/keycloak/standalone/configuration/keystores/https-keystore.pk12 to /opt/jboss/keycloak/standalone/configuration/keystores/https-keystore.jks...
Warning: Overwriting existing alias keycloak-https-key in destination keystore