How to add encoded key- and truststore to K8s secret

Posted on September 9, 2021 by Adrian Wyssmann ‐ 2 min read

Working with java applications in kubernetes, you might come use

In this article I explain what Java keystore and truststore are.

Create Secret containing keystore.jks

Ensure that the type of your keystore is actually jks and not PKCS#12 or anything else

You can add a java keystore as a secret, directly using the file:

$namespace=xxx
$context=xxx
$secretname=xxxx
kubectl create secret generic "${secretname}" \
   --namespace=$namespace \
   --context=$context
   --from-file=keystore.jks=keystore.jks \
   --context $context

keystore.jks is the name of the field, used in the resulting json/yaml format of the secret. For cacerts this would look as follows

kubectl create secret generic "${secretname}" \
   --namespace=$namespace \
   --context=$context
   --from-file=cacerts=cacerts \
   --context $context

If you want to create the secret and store it in source control you could do this as follows:

  1. Convert keystore to base64:

    cat cacerts | base64 > secret.yaml
  2. Open secret.yaml in Editor, modify the content as follows:

    apiVersion: v1
    kind: Secret
    metadata:
      name: custom-keystore
      namespace: spinnaker
    data:
      cacerts: |
        /u3+7QAAAAIAAACHAAAAAgAXZGlnaWNlcnRhc3N1cmVkaWRyb290Y2EAAAFj+WMrQAAFWC41MDkA
        AAO7MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYD
        VQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcn
        ...    
  3. Add the secret to k8s:

    kubectl apply -f secret.yaml

Retrieve keystore.jks from the Secret

You can get the keystore.jks from the secret as follows:

kubectl get secret "${secretname}" \
   --namespace=$namespace \
   --context=$context
   -o jsonpath="{['data']['keystore.jks']}" | \
base64 -d > keystore.jks

Update secret

You can the keystore.jks file directly as follows:

kubectl get secret "${secretname}" \
    --namespace=$namespace \
    --context=$context -o json | \
jq --arg enc "$(cat keystore.jks | base64 -w 0)" '.data["keystore.jks"]=$enc' | \
kubectl apply -f -

Mounting cacerts in a pod

When using java applications an you have self-signed certificates which you added to your cacerts you also have to mount it inside the pod, so the java application running there can use it. There are two ways:

  1. mount keeping the files in the java directory intact.

    ...
    # This will mount the secret item from key { cacerts } as
    # file cacerts keeping the files in the java directory intact.
    volumeMounts:
    - mountPath: /etc/ssl/certs/java/cacerts
        subPath: cacerts
        name: custom-keystore
    volumes:
    - name: custom-keystore
        secret:
          secretName: custom-keystore
          items:
          - key: cacerts
            path: cacerts
    ...
  2. mount not keeping the existing files

    ...
    # This will mount the secret item from key { cacerts } as
    # file java/subPath/cacerts (or only java/cacerts), using
    # java folder as mountpoint thus not keeping the existing files.
    volumeMounts:
    - mountPath: /etc/ssl/certs/java
      name: custom-keystore
    volumes:
    - name: custom-keystore
        secret:
          secretName: custom-keystore
          items:
          - key: cacerts
          path: subPath/cacerts
          #path: cacerts