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
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}’)
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
““
I prefer the more native way of doing this, which doesn’t need jq installed and I consider cleaner:
https://www.adyxax.org/blog/2020/08/06/get-tls-certificate-and-key-from-a-kubernetes-secret/#the-solution
kubectl get secret mysecret -o json -o=jsonpath=”{.data.tls\.crt}” | base64 -d > certchain.pem
kubectl get secret mysecret -o json -o=jsonpath=”{.data.tls\.key}” | base64 -d > cert.key