在 OpenShift 环境中部署秘密 Java 密钥存储的好方法是什么?

What is a good way to deploy secret Java key stores in an OpenShift environment?

我们有一个 Java Web 应用程序应该从常规部署模型(安装在服务器上)移动到 OpenShift 环境(部署为 docker 容器)。目前,此应用程序使用一组 Java 密钥存储(.jks 文件)作为客户端证书,以便与第三方 Web 界面进行通信。每个接口我们有一个密钥库。

这些 jks 文件在生产机器上手动部署,并且在需要更新第三方证书时偶尔更新。我们的应用程序有一个包含密钥存储文件路径的设置,在启动时它将从中读取证书,然后使用它们与第三方系统通信。

现在,当转向 OpenShift 部署时,我们有一个 docker 图像,其中包含将用于所有环境(开发、测试和生产)的应用程序。所有配置都作为环境变量给出。但是,我们不能将 jks 文件作为环境变量提供,这些文件需要挂载到 docker 容器的文件系统中。

由于这些证书是机密,我们不想将它们烘焙到映像中。我浏览了 OpenShift 文档以寻找有关如何处理此问题的一些线索,并基本上找到了两个选项:使用 Secrets 或安装持久卷声明 (PVC)。

秘密似乎对我们不起作用,因为它们几乎只是键值对,您可以将其作为文件装载或作为环境变量提交。它们也有大小限制。使用 PVC 理论上是可行的,但是我们首先需要有一些方法将 JKS 文件放入该卷中。一种简单的方法是启动一个 shell 容器来安装 PVC 并使用 OpenShift 命令行工具将文件手动复制到其中,但是我希望有一个稍微少一些手动解决方案。

您是否找到了解决此问题或需要将文件放入容器的类似问题的巧妙解决方案?

原来我误解了秘密的工作原理。它们确实是可以作为文件挂载的键值对。但是,该值可以是将映射为文件内容的任何 base64 编码二进制文件。所以解决方法是先将JKS文件的内容编码为base64:

cat keystore.jks| base64

然后你就可以把这个放到你的秘密定义中了:

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
  namespace: my-namespace
data:
  keystore.jks: "<base 64 from previous command here>"

最后,您可以通过在部署配置中引用它来将其安装到您的 docker 容器中:

apiVersion: v1
kind: DeploymentConfig
spec:
  ...
  template:
    spec:
      ...
      container:
       - name: "my-container"
         ...
         volumeMounts:
            - name: secrets
              mountPath: /mnt/secrets
              readOnly: true

     volumes:
        - name: secrets
          secret:
            secretName: "my-secret"
            items:
              - key: keystore.jks
                path: keystore.jks

这将在 /mnt/secrets 上安装秘密卷 secrets 并使名称为 keystore.jks 的条目在 /mnt/secrets 下作为文件 keystore.jks 可用。

我不确定这是否真的是一个好方法,但它至少在这里起作用。

您可以像 Jan Thomä 所说的那样添加和装载机密,但使用 oc 命令行工具这样更容易:

./oc create secret generic crnews-keystore --from-file=keystore.jks=$HOME/git/crnews-service/src/main/resources/keystore.jks --from-file=truststore.jks=$HOME/git/crnews-service/src/main/resources/truststore.jks --type=opaque

然后可以通过 UI 添加:Applications->Deployments->-> "Add config files" 在哪里你可以选择你想挂载的秘密。

请注意,name=value 对(例如 truststore.jks=)将像 filename=base64decoded-Content 一样使用。

建立在@Frischling 和@Jan-Thomä 所说的基础上,并与 Frischling 达成一致,因为他的方式更简单,并且在将密钥库添加为秘密后,在 [=10] 下处理了两个信任证书密钥库=]点击环境link,添加以下系统属性:
姓名: JAVA_OPTS_APPEND 和
-Djavax.net.ssl.keyStorePassword=changeme -Djavax.net.ssl.keyStore=/mnt/keystores/your_cert_key_store.jks -Djavax.net.ssl.trustStorePassword=changeme -Djavax.net.ssl.trustStore=/mnt/keystores/your_ca_key_store.jks

这实际上将如指示的那样,将密钥库文件路径、密码附加到应用程序使用的 java 选项,例如 JBoss/WildFly 或 Tomcat。

我生成的 base64 是多行的,我遇到了同样的错误。

诀窍是,在 base64 中使用 -w0 参数,以便整个编码在 1 行中!

base64 -w0 ssl_keystore.jks > test

上面将创建一个名为 test 的文件,并将 base64 包含在一行中,在秘密中像这样复制粘贴:

apiVersion: v1
kind: Secret
metadata:
  name: staging-ssl-keystore-jks
  namespace: staging-space
type: Opaque
data:
  keystore.jsk: your-base64-in-one-line