Retrieve TLS certificates from Kubernetes

I use some internal services not exposed to the internet. I generate those certificates in my kubernetes cluster using Cert-Manager but then I need to get the out of the cluster to the appropriate applications.

First we get a list of certificates in the cluster with a --field-selector seleting only the kubernetes.io/tls type:

$ kubectl get secrets --field-selector type=kubernetes.io/tls --all-namespaces

To retrieve a concrete certificate:

$ kubectl get secret -n ${NAMESPACE} ${SECRET_NAME} -o json | jq -r '.data."tls.crt"' | base64 -d

You need to provide NAMESPACE and SECRET_NAME variables. To retrieve the private key change '.data."tls.crt"' to '.data."tls.key"'.

To retrieve the certificates primary domain:

$ kubectl get secret -n ${NAMESPACE} ${SECRET_NAME} -o json | jq -r '.data."tls.crt"' | base64 -d | openssl x509 -noout -text | grep "Subject: CN = " | sed -E 's/\s+Subject: CN = ([^ ]*)/\1/g'

To put it all together:

#!/usr/bin/env bash

KUBECTL="kubectl"
OUTPUT=${1:-"$(pwd)/certificates"}

for secret in $(${KUBECTL} get secrets --field-selector type=kubernetes.io/tls --all-namespaces -o=custom-columns='NAMESPACE:metadata.namespace','NAME:metadata.name' | tail +2 | sed -E 's/\s+/\//g'); do
        NAMESPACE=$(echo ${secret} | cut -d"/" -f1)
        NAME=$(echo ${secret} | cut -d"/" -f2)
        echo -n "${NAMESPACE}: ${NAME}>"

        if [ -n "$(${KUBECTL} get secret -n ${NAMESPACE} ${NAME} -o json | jq -r '.data."tls.crt"' | base64 -d)" ]; then

                DOMAIN=$(${KUBECTL} get secret -n ${NAMESPACE} ${NAME} -o json | jq -r '.data."tls.crt"' | base64 -d | openssl x509 -noout -text | grep "Subject: CN = " | sed -E 's/\s+Subject: CN = ([^ ]*)/\1/g')
                echo -n " ${DOMAIN}"

                mkdir -p "${OUTPUT}/${DOMAIN}"

                ${KUBECTL} get secret -n ${NAMESPACE} ${NAME} -o json | jq -r '.data."tls.key"' | base64 -d > "${OUTPUT}/${DOMAIN}/privkey.pem"
                ${KUBECTL} get secret -n ${NAMESPACE} ${NAME} -o json | jq -r '.data."tls.crt"' | base64 -d > "${OUTPUT}/${DOMAIN}/fullchain.pem"

                echo " DONE"
        else
                echo " FAILED"
        fi
done

3 Comments

  1. Here is my script to get all tls keys from a k8s namespace:

    ##Get all tls keys from a k8s namespace
    #!/bin/bash

    NAMESPACE=”external-tls”

    while IFS= read -r SECRET_NAME
    do
    # Export TLS Cert
    kubectl get secret -n “${NAMESPACE}” “${SECRET_NAME}” -o json | jq -r ‘.data.”tls.crt”‘ | base64 -d > “${SECRET_NAME}.crt”

    # Export Private Key
    kubectl get secret -n “${NAMESPACE}” “${SECRET_NAME}” -o json | jq -r ‘.data.”tls.key”‘ | base64 -d > “${SECRET_NAME}.key”

    done < 1 {print $1}’)

  2. I have a little improvement, so that it works also with MacOS…

    ““
    if [[ “$OSTYPE” == “linux-gnu”* ]]; then
    SED=”sed”
    elif [[ “$OSTYPE” == “darwin”* ]]; then
    # Mac OSX: brew install gnu-sed
    SED=”gsed”
    fi
    “`

    —-

    “`
    #!/usr/bin/env bash

    KUBECTL=”kubectl”
    OUTPUT=${1:-“$(pwd)/certificates”}
    SED=”sed”

    if [[ “$OSTYPE” == “linux-gnu”* ]]; then
    SED=”sed”
    elif [[ “$OSTYPE” == “darwin”* ]]; then
    # Mac OSX: brew install gnu-sed
    SED=”gsed”
    fi

    for secret in $(${KUBECTL} get secrets –field-selector type=kubernetes.io/tls –all-namespaces -o=custom-columns=’NAMESPACE:metadata.namespace’,’NAME:metadata.name’ | tail +2 | ${SED} -E ‘s/\s+/\//g’); do
    NAMESPACE=$(echo ${secret} | cut -d”/” -f1)
    NAME=$(echo ${secret} | cut -d”/” -f2)
    echo -n “${NAMESPACE}: ${NAME}>”

    if [ -n “$(${KUBECTL} get secret -n ${NAMESPACE} ${NAME} -o json | jq -r ‘.data.”tls.crt”‘ | base64 -d)” ]; then

    DOMAIN=$(${KUBECTL} get secret -n ${NAMESPACE} ${NAME} -o json | jq -r ‘.data.”tls.crt”‘ | base64 -d | openssl x509 -noout -text | grep “Subject: CN = ” | ${SED} -E ‘s/\s+Subject: CN = ([^ ]*)/\1/g’)
    echo -n ” ${DOMAIN}”

    mkdir -p “${OUTPUT}/${DOMAIN}”

    ${KUBECTL} get secret -n ${NAMESPACE} ${NAME} -o json | jq -r ‘.data.”tls.key”‘ | base64 -d > “${OUTPUT}/${DOMAIN}/privkey.pem”
    ${KUBECTL} get secret -n ${NAMESPACE} ${NAME} -o json | jq -r ‘.data.”tls.crt”‘ | base64 -d > “${OUTPUT}/${DOMAIN}/fullchain.pem”

    echo ” DONE”
    else
    echo ” FAILED”
    fi
    done
    ““

Leave a Reply to John R Cancel reply

Your email address will not be published. Required fields are marked *