Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

We have a Java web application that is supposed to be moved from a regular deployment model (install on a server) into an OpenShift environment (deployment as docker container). Currently this application consumes a set of Java key stores (.jks files) for client certificates for communicating with third party web interfaces. We have one key store per interface.

These jks files get manually deployed on production machines and are occasionally updated when third-party certificates need to be updated. Our application has a setting with a path to the key store files and on startup it will read certificates from them and then use them to communicate with the third-party systems.

Now when moving to an OpenShift deployment, we have one docker image with the application that is going to be used for all environments (development, test and production). All configuration is given as environment variables. However we cannot give jks files as environment variables these need to be mounted into the docker container's file system.

As these certificates are a secret we don't want to bake them into the image. I scanned the OpenShift documentation for some clues on how to approach this and basically found two options: using Secrets or mounting a persistent volume claim (PVC).

Secrets don't seem to work for us as they are pretty much just key-value-pairs that you can mount as a file or have handed in as environment variables. They also have a size limit to them. Using a PVC would theoretically work, however we'd need to have some way to get the JKS files into that volume in the first place. A simple way would be to just start a shell container mounting the PVC and copying the files manually into it using the OpenShift command line tools, however I was hoping for a somewhat less manual solution.

Do you have found a clever solution to this or a similar problem where you needed to get files into a container?

like image 883
Jan Thomä Avatar asked Jan 24 '18 13:01

Jan Thomä


People also ask

How do you store secrets in OpenShift?

Secrets in OpenShift OpenShift supports a number of different secret types to securely store sensitive data: kubernetes.io/service-account-token uses a service account token. kubernetes.io/dockercfg uses the dockercfg file for required Docker credentials. kubernetes.io/dockerconfigjson uses the .

Which command can be used to create a secret from a file OpenShift?

You can use the kubectl rolling-update command. The resourceVersion value in a secret is not specified when it is referenced.

What is the difference between keystore and TrustStore?

TrustStore is used to store certificates from Certified Authorities (CA) that verify the certificate presented by the server in an SSL connection. While Keystore is used to store private key and identity certificates that a specific program should present to both parties (server or client) for verification.

What is JKS format?

A Java keystore (JKS) file is a secure file format used to hold certificate information for Java applications.

Can we use JK files in OpenShift deployment?

Now when moving to an OpenShift deployment, we have one docker image with the application that is going to be used for all environments (development, test and production). All configuration is given as environment variables. However we cannot give jks files as environment variables these need to be mounted into the docker container's file system.

What is a secret in OpenShift?

This topic discusses important properties of secrets and provides an overview on how developers can use them. The Secret object type provides a mechanism to hold sensitive information such as passwords, OpenShift Container Platform client configuration files, dockercfg files, private source repository credentials, and so on.

How do I add environment variables to an OpenShift deployment?

In the Openshift Web Console, from the Deployment config, there is a "Environment From" section in the Environment tab. The "Environment From" lets you add all key-value pairs from a config map or secret as environment variables.

Is it time to start using OpenShift for Java?

Looking at Kubernetes (one of the OpenShift upstream projects) it looks like that in the future the ability of openshift to generate certificates will be improved by allowing to plugin external CAs. So, think this is a good time to start leveraging this feature also for Java applications.


Video Answer


3 Answers

It turns out that I misunderstood how secrets work. They are indeed key-values pairs that you can mount as files. The value can however be any base64 encoded binary that will be mapped as the file contents. So the solution is to first encode the contents of the JKS file to base64:

cat keystore.jks| base64

Then you can put this into your secret definition:

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

Finally you can mount this into your docker container by referencing it in the deployment configuration:

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

This will mount the secret volume secrets at /mnt/secrets and makes the entry with the name keystore.jks available as file keystore.jks under /mnt/secrets.

I'm not sure if this is really a good way of doing this, but it is at least working here.

like image 141
Jan Thomä Avatar answered Oct 25 '22 15:10

Jan Thomä


You can add and mount the secrets like stated by Jan Thomä, but it's easier like this, using the oc commandline tool:

./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

This can then be added via UI: Applications->Deployments->-> "Add config files" where you can choose what secret you want to mount where.

Note, that the name=value pairs (e.g. truststore.jks=) will be used like filename=base64decoded-Content.

like image 10
Frischling Avatar answered Oct 25 '22 13:10

Frischling


My generated base64 was multiline and I was getting the same error.

Trick is, use -w0 argument in base64 so that the whole encode is in 1 line!

base64 -w0 ssl_keystore.jks > test

Above will create a file named test and will contain the base64 in one line, copy paste like this in a secret:

apiVersion: v1
kind: Secret
metadata:
  name: staging-ssl-keystore-jks
  namespace: staging-space
type: Opaque
data:
  keystore.jsk: your-base64-in-one-line
like image 4
Junaed Avatar answered Oct 25 '22 15:10

Junaed