Skip to content

Commit

Permalink
Update/rename certs.sh; add default cert rotation script
Browse files Browse the repository at this point in the history
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
  • Loading branch information
brandond committed Mar 7, 2023
1 parent ea094d1 commit cb98b11
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 27 deletions.
56 changes: 30 additions & 26 deletions contrib/util/certs.sh → contrib/util/generate-custom-ca-certs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,12 @@ if [[ -e root-ca.pem ]]; then
else
echo "Generating root certificate authority RSA key and certificate"
${OPENSSL} genrsa -out root-ca.key 4096
${OPENSSL} req -x509 -new -nodes -key root-ca.key -sha256 -days 7300 -out root-ca.pem -subj "/CN=${PRODUCT}-root-ca@${TIMESTAMP}" -config <(echo "${CONFIG}") -extensions v3_ca
${OPENSSL} req -x509 -new -nodes -sha256 -days 7300 \
-subj "/CN=${PRODUCT}-root-ca@${TIMESTAMP}" \
-key root-ca.key \
-out root-ca.pem \
-config <(echo "${CONFIG}") \
-extensions v3_ca
fi
cat root-ca.pem > root-ca.crt

Expand All @@ -86,7 +91,14 @@ else

echo "Generating intermediate certificate authority RSA key and certificate"
${OPENSSL} genrsa -out intermediate-ca.key 4096
${OPENSSL} req -x509 -new -nodes -CAkey root-ca.key -CA root-ca.crt -key intermediate-ca.key -sha256 -days 7300 -out intermediate-ca.pem -subj "/CN=${PRODUCT}-intermediate-ca@${TIMESTAMP}" -config <(echo "${CONFIG}, pathlen:1") -extensions v3_ca
${OPENSSL} req -x509 -new -nodes -sha256 -days 7300 \
-subj "/CN=${PRODUCT}-intermediate-ca@${TIMESTAMP}" \
-key intermediate-ca.key \
-out intermediate-ca.pem \
-CAkey root-ca.key \
-CA root-ca.crt \
-config <(echo "${CONFIG}, pathlen:1") \
-extensions v3_ca
fi
cat intermediate-ca.pem root-ca.pem > intermediate-ca.crt

Expand All @@ -96,30 +108,22 @@ if [[ ! -e intermediate-ca.key ]]; then
fi

# Generate new leaf CAs for all the control-plane and etcd components
echo "Generating Kubernetes server leaf certificate authority EC key and certificate"
${OPENSSL} ecparam -name prime256v1 -genkey -out client-ca.key
${OPENSSL} req -x509 -new -nodes -CAkey intermediate-ca.key -CA intermediate-ca.crt -key client-ca.key -sha256 -days 3650 -out client-ca.pem -subj "/CN=${PRODUCT}-client-ca@${TIMESTAMP}" -config <(echo "${CONFIG}, pathlen:0") -extensions v3_ca
cat client-ca.pem intermediate-ca.pem root-ca.pem > client-ca.crt

echo "Generating Kubernetes client leaf certificate authority EC key and certificate"
${OPENSSL} ecparam -name prime256v1 -genkey -out server-ca.key
${OPENSSL} req -x509 -new -nodes -CAkey intermediate-ca.key -CA intermediate-ca.crt -key server-ca.key -sha256 -days 3650 -out server-ca.pem -subj "/CN=${PRODUCT}-server-ca@${TIMESTAMP}" -config <(echo "${CONFIG}, pathlen:0") -extensions v3_ca
cat server-ca.pem intermediate-ca.pem root-ca.pem > server-ca.crt

echo "Generating Kubernetes request-header leaf certificate authority EC key and certificate"
${OPENSSL} ecparam -name prime256v1 -genkey -out request-header-ca.key
${OPENSSL} req -x509 -new -nodes -CAkey intermediate-ca.key -CA intermediate-ca.crt -key request-header-ca.key -sha256 -days 3560 -out request-header-ca.pem -subj "/CN=${PRODUCT}-request-header-ca@${TIMESTAMP}" -config <(echo "${CONFIG}, pathlen:0") -extensions v3_ca
cat request-header-ca.pem intermediate-ca.pem root-ca.pem > request-header-ca.crt

echo "Generating etcd peer leaf certificate authority EC key and certificate"
${OPENSSL} ecparam -name prime256v1 -genkey -out etcd/peer-ca.key
${OPENSSL} req -x509 -new -nodes -CAkey intermediate-ca.key -CA intermediate-ca.crt -key etcd/peer-ca.key -sha256 -days 3650 -out etcd/peer-ca.pem -subj "/CN=etcd-peer-ca@${TIMESTAMP}" -config <(echo "${CONFIG}, pathlen:0") -extensions v3_ca
cat etcd/peer-ca.pem intermediate-ca.pem root-ca.pem > etcd/peer-ca.crt

echo "Generating etcd server leaf certificate authority EC key and certificate"
${OPENSSL} ecparam -name prime256v1 -genkey -out etcd/server-ca.key
${OPENSSL} req -x509 -new -nodes -CAkey intermediate-ca.key -CA intermediate-ca.crt -key etcd/server-ca.key -sha256 -days 3650 -out etcd/server-ca.pem -subj "/CN=etcd-server-ca@${TIMESTAMP}" -config <(echo "${CONFIG}, pathlen:0") -extensions v3_ca
cat etcd/server-ca.pem intermediate-ca.pem root-ca.pem > etcd/server-ca.crt
for TYPE in client server request-header etcd/peer etcd/server; do
CERT_NAME="${PRODUCT}-$(echo ${TYPE} | tr / -)-ca"
echo "Generating ${CERT_NAME} leaf certificate authority EC key and certificate"
${OPENSSL} ecparam -name prime256v1 -genkey -out client-ca.key
${OPENSSL} req -x509 -new -nodes -sha256 -days 3650 \
-subj "/CN=${CERT_NAME}@${TIMESTAMP}" \
-key ${TYPE}-ca.key \
-out ${TYPE}-ca.pem \
-CAkey intermediate-ca.key \
-CA intermediate-ca.crt \
-config <(echo "${CONFIG}, pathlen:0") \
-extensions v3_ca
cat ${TYPE}-ca.pem \
intermediate-ca.pem \
root-ca.pem > ${TYPE}-ca.crt
done

echo
echo "CA certificate generation complete. Required files are now present in: ${DATA_DIR}/server/tls"
Expand Down
99 changes: 99 additions & 0 deletions contrib/util/rotate-default-ca-certs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
set -e
umask 027

# Example K3s self-signed CA rotation script.
#
# This script will generate new self-signed root CA certificates, and cross-sign them with the
# current self-signed root CA certificates. It will then generate new leaf CA certificates
# signed by the new self-signed/cross-signed root CAs. The resulting cluster CA bundle will
# allow existing certificates to be trusted up until the original root CAs expire.
#
CONFIG="
[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints=CA:true"
TIMESTAMP=$(date +%s)
PRODUCT="${PRODUCT:-k3s}"
DATA_DIR="${DATA_DIR:-/var/lib/rancher/${PRODUCT}}"
TEMP_DIR=$(mktemp -d)

if type -t openssl-3 &>/dev/null; then
OPENSSL=openssl-3
else
OPENSSL=openssl
fi

echo "Using $(which ${OPENSSL}): $(${OPENSSL} version)"

if ! ${OPENSSL} ecparam -help &>/dev/null; then
echo "openssl not found or missing Elliptic Curve (ecparam) support."
exit 1
fi

if ! ${OPENSSL} req -help 2>&1 | grep -q CAkey; then
echo "openssl req missing -CAkey support; please use OpenSSL 3.0.0 or newer"
exit 1
fi

mkdir -p ${TEMP_DIR}/server/tls/etcd

for TYPE in client server request-header etcd/peer etcd/server; do
if [ ! -f ${DATA_DIR}/server/tls/${TYPE}-ca.crt ]; then
echo "Current ${TYPE} CA cert does not exist; cannot continue"
exit 1
fi
if [ "$(grep -cF BEGIN ${DATA_DIR}/server/tls/${TYPE}-ca.crt)" != "1" ]; then
echo "Current ${TYPE} CA cert is not-self-signed; cannot continue"
exit 1
fi

CERT_NAME="${PRODUCT}-$(echo ${TYPE} | tr / -)-root-ca"
echo "Generating ${CERT_NAME} cross-signed root certificate authority key and certificates"
${OPENSSL} ecparam -name prime256v1 -genkey -out ${TEMP_DIR}/server/tls/${TYPE}-root-ca.key
${OPENSSL} req -x509 -new -nodes -sha256 -days 7300 \
-subj "/CN=${CERT_NAME}@${TIMESTAMP}" \
-key ${TEMP_DIR}/server/tls/${TYPE}-root-ca.key \
-out ${TEMP_DIR}/server/tls/${TYPE}-root-ca-ssigned.pem \
-config <(echo "${CONFIG}") -extensions v3_ca
${OPENSSL} req -x509 -new -nodes -sha256 -days 7300 \
-subj "/CN=${CERT_NAME}@${TIMESTAMP}" \
-key ${TEMP_DIR}/server/tls/${TYPE}-root-ca.key \
-out ${TEMP_DIR}/server/tls/${TYPE}-root-ca-xsigned.pem \
-CAkey ${DATA_DIR}/server/tls/${TYPE}-ca.key \
-CA ${DATA_DIR}/server/tls/${TYPE}-ca.crt \
-config <(echo "${CONFIG}") -extensions v3_ca

CERT_NAME="${PRODUCT}-$(echo ${TYPE} | tr / -)-ca"
echo "Generating ${CERT_NAME} leaf certificate authority EC key and certificate"
${OPENSSL} ecparam -name prime256v1 -genkey -out ${TEMP_DIR}/server/tls/${TYPE}-ca.key
${OPENSSL} req -x509 -new -nodes -sha256 -days 7300 \
-subj "/CN=${CERT_NAME}@${TIMESTAMP}" \
-key ${TEMP_DIR}/server/tls/${TYPE}-ca.key \
-out ${TEMP_DIR}/server/tls/${TYPE}-ca.pem \
-CAkey ${TEMP_DIR}/server/tls/${TYPE}-root-ca.key \
-CA ${TEMP_DIR}/server/tls/${TYPE}-root-ca-ssigned.pem \
-config <(echo "${CONFIG}") \
-extensions v3_ca

cat ${TEMP_DIR}/server/tls/${TYPE}-ca.pem \
${TEMP_DIR}/server/tls/${TYPE}-root-ca-ssigned.pem \
${TEMP_DIR}/server/tls/${TYPE}-root-ca-xsigned.pem \
${DATA_DIR}/server/tls/${TYPE}-ca.crt > ${TEMP_DIR}/server/tls/${TYPE}-ca.crt
done

${OPENSSL} genrsa -traditional -out ${TEMP_DIR}/server/tls/service.key 2048
cat ${DATA_DIR}/server/tls/service.key >> ${TEMP_DIR}/server/tls/service.key

export SERVER_CA_HASH=$(${OPENSSL} x509 -noout -fingerprint -sha256 -in ${TEMP_DIR}/server/tls/server-root-ca-ssigned.pem | awk -F= '{ gsub(/:/, "", $2); print tolower($2) }')
SERVER_TOKEN=$(awk -F:: '{print "K10" ENVIRON["SERVER_CA_HASH"] FS $2}' ${DATA_DIR}/server/token)
AGENT_TOKEN=$(awk -F:: '{print "K10" ENVIRON["SERVER_CA_HASH"] FS $2}' ${DATA_DIR}/server/agent-token)

echo
echo "Cross-signed CA certs and keys now available in ${TEMP_DIR}/server/tls"
echo "Updated server token: ${SERVER_TOKEN}"
echo "Updated agent token: ${AGENT_TOKEN}"
echo
echo "You may now run:"
echo " k3s certificate rotate-ca --path=${TEMP_DIR}/server --force"
2 changes: 1 addition & 1 deletion scripts/test-run-cacerts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ cluster-pre-hook() {
rancher/mirrored-pause:3.6 \
>/dev/null

DATA_DIR="$TEST_DIR/pause/0/k3s" ./contrib/util/certs.sh
DATA_DIR="$TEST_DIR/pause/0/k3s" ./contrib/util/generate-custom-ca-certs.sh
docker cp "$TEST_DIR/pause/0/k3s" $name:/var/lib/rancher
}
export -f cluster-pre-hook
Expand Down

0 comments on commit cb98b11

Please # to comment.