-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update/rename certs.sh; add default cert rotation script
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
- Loading branch information
Showing
4 changed files
with
300 additions
and
128 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Example K3s CA certificate generation script. | ||
# | ||
# This script will generate files sufficient to bootstrap K3s cluster certificate | ||
# authorities. By default, the script will create the required files under | ||
# /var/lib/rancher/k3s/server/tls, where they will be found and used by K3s during initial | ||
# cluster startup. Note that these files MUST be present before K3s is started the first | ||
# time; certificate data SHOULD NOT be changed once the cluster has been initialized. | ||
# | ||
# The output path may be overridden with the DATA_DIR environment variable. | ||
# | ||
# This script will also auto-generate certificates and keys for both root and intermediate | ||
# certificate authorities if none are found. | ||
# If you have only an existing root CA, provide: | ||
# root-ca.pem | ||
# root-ca.key. | ||
# If you have an existing root and intermediate CA, provide: | ||
# root-ca.pem | ||
# intermediate-ca.pem | ||
# intermediate-ca.key. | ||
|
||
set -e | ||
umask 027 | ||
|
||
TIMESTAMP=$(date +%s) | ||
PRODUCT="${PRODUCT:-k3s}" | ||
DATA_DIR="${DATA_DIR:-/var/lib/rancher/${PRODUCT}}" | ||
|
||
if type -t openssl-3 &>/dev/null; then | ||
OPENSSL=openssl-3 | ||
else | ||
OPENSSL=openssl | ||
fi | ||
|
||
echo "Using $(type -p ${OPENSSL}): $(${OPENSSL} version)" | ||
|
||
if ! ${OPENSSL} ecparam -name prime256v1 -genkey -noout -out /dev/null &>/dev/null; then | ||
echo "openssl not found or missing Elliptic Curve (ecparam) support." | ||
exit 1 | ||
fi | ||
|
||
${OPENSSL} version | grep -qF 'OpenSSL 3' && OPENSSL_GENRSA_FLAGS=-traditional | ||
|
||
mkdir -p "${DATA_DIR}/server/tls/etcd" | ||
cd "${DATA_DIR}/server/tls" | ||
|
||
# Set up temporary openssl configuration | ||
mkdir -p ".ca/certs" | ||
trap "rm -rf .ca" EXIT | ||
touch .ca/index | ||
openssl rand -hex 8 > .ca/serial | ||
cat >.ca/config <<'EOF' | ||
[ca] | ||
default_ca = ca_default | ||
[ca_default] | ||
dir = ./.ca | ||
database = $dir/index | ||
serial = $dir/serial | ||
new_certs_dir = $dir/certs | ||
default_md = sha256 | ||
policy = policy_anything | ||
[policy_anything] | ||
commonName = supplied | ||
#countryName = optional | ||
#localityName = optional | ||
#emailAddress = optional | ||
#organizationName = optional | ||
#stateOrProvinceName = optional | ||
#organizationalUnitName = optional | ||
[req] | ||
distinguished_name = req_distinguished_name | ||
[req_distinguished_name] | ||
[v3_ca] | ||
subjectKeyIdentifier = hash | ||
authorityKeyIdentifier = keyid:always | ||
basicConstraints=CA:true | ||
EOF | ||
|
||
# Don't overwrite the service account issuer key; we pass the key into both the controller-manager | ||
# and the apiserver instead of passing a cert list into the apiserver, so there's no facility for | ||
# rotation and things will get very angry if all the SA keys are invalidated. | ||
if [[ -e service.key ]]; then | ||
echo "Generating additional Kubernetes service account issuer RSA key" | ||
OLD_SERVICE_KEY="$(cat service.key)" | ||
else | ||
echo "Generating Kubernetes service account issuer RSA key" | ||
fi | ||
${OPENSSL} genrsa ${OPENSSL_GENRSA_FLAGS:-} -out service.key 2048 | ||
echo "${OLD_SERVICE_KEY}" >> service.key | ||
|
||
# Use existing root CA if present | ||
if [[ -e root-ca.pem ]]; then | ||
echo "Using existing root certificate" | ||
else | ||
echo "Generating root certificate authority RSA key and certificate" | ||
${OPENSSL} genrsa ${OPENSSL_GENRSA_FLAGS:-} -out root-ca.key 4096 | ||
${OPENSSL} req -x509 -new -nodes -sha256 -days 7300 \ | ||
-subj "/CN=${PRODUCT}-root-ca@${TIMESTAMP}" \ | ||
-key root-ca.key \ | ||
-out root-ca.pem \ | ||
-config .ca/config \ | ||
-extensions v3_ca | ||
fi | ||
cat root-ca.pem > root-ca.crt | ||
|
||
# Use existing intermediate CA if present | ||
if [[ -e intermediate-ca.pem ]]; then | ||
echo "Using existing intermediate certificate" | ||
else | ||
if [[ ! -e root-ca.key ]]; then | ||
echo "Cannot generate intermediate certificate without root certificate private key" | ||
exit 1 | ||
fi | ||
|
||
echo "Generating intermediate certificate authority RSA key and certificate" | ||
${OPENSSL} genrsa ${OPENSSL_GENRSA_FLAGS:-} -out intermediate-ca.key 4096 | ||
${OPENSSL} req -new -nodes \ | ||
-subj "/CN=${PRODUCT}-intermediate-ca@${TIMESTAMP}" \ | ||
-key intermediate-ca.key | | ||
${OPENSSL} ca -batch -days 3700 \ | ||
-in /dev/stdin \ | ||
-out intermediate-ca.pem \ | ||
-keyfile root-ca.key \ | ||
-cert root-ca.pem \ | ||
-config .ca/config \ | ||
-extensions v3_ca | ||
fi | ||
cat intermediate-ca.pem root-ca.pem > intermediate-ca.crt | ||
|
||
if [[ ! -e intermediate-ca.key ]]; then | ||
echo "Cannot generate leaf certificates without intermediate certificate private key" | ||
exit 1 | ||
fi | ||
|
||
# Generate new leaf CAs for all the control-plane and etcd components | ||
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 -noout -out ${TYPE}-ca.key | ||
${OPENSSL} req -new -nodes \ | ||
-subj "/CN=${CERT_NAME}@${TIMESTAMP}" \ | ||
-key ${TYPE}-ca.key | | ||
${OPENSSL} ca -batch -days 3700 \ | ||
-in /dev/stdin \ | ||
-out ${TYPE}-ca.pem \ | ||
-keyfile intermediate-ca.key \ | ||
-cert intermediate-ca.pem \ | ||
-config .ca/config \ | ||
-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" | ||
echo "For security purposes, you should make a secure copy of the following files and remove them from cluster members:" | ||
ls ${DATA_DIR}/server/tls/root-ca.* ${DATA_DIR}/server/tls/intermediate-ca.* | xargs -n1 echo -e "\t" | ||
|
||
if [ "${DATA_DIR}" != "/var/lib/rancher/${PRODUCT}" ]; then | ||
echo | ||
echo "To update certificates on an existing cluster, you may now run:" | ||
echo " k3s certificate rotate-ca --path=${DATA_DIR}/server" | ||
fi |
Oops, something went wrong.