-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
Copy pathrotate-default-ca-certs.sh
executable file
·134 lines (120 loc) · 4.89 KB
/
rotate-default-ca-certs.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/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="${DATA_DIR}/server/rotate-ca"
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 -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 ${TEMP_DIR}/tls/etcd
cd ${TEMP_DIR}/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
[req]
distinguished_name = req_distinguished_name
[req_distinguished_name]
[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, keyEncipherment, keyCertSign
EOF
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 'END CERTIFICATE' ${DATA_DIR}/server/tls/${TYPE}-ca.crt)" -gt "1" ]; then
awk 'BEGIN { RS = "-----END CERTIFICATE-----\n" } NR==2 { print $0 RS }' ${DATA_DIR}/server/tls/${TYPE}-ca.crt > ${TYPE}-root-old.pem
awk 'BEGIN { RS = "-----END EC PRIVATE KEY-----\n" } NR==2 { print $0 RS }' ${DATA_DIR}/server/tls/${TYPE}-ca.key > ${TYPE}-root-old.key
else
cat ${DATA_DIR}/server/tls/${TYPE}-ca.crt > ${TYPE}-root-old.pem
cat ${DATA_DIR}/server/tls/${TYPE}-ca.key > ${TYPE}-root-old.key
fi
CERT_NAME="${PRODUCT}-$(echo ${TYPE} | tr / -)-root"
echo "Generating ${CERT_NAME} root and cross-signed certificate authority key and certificates"
${OPENSSL} ecparam -name prime256v1 -genkey -noout -out ${TYPE}-root.key
${OPENSSL} req -x509 -new -nodes -sha256 -days 7300 \
-subj "/CN=${CERT_NAME}@${TIMESTAMP}" \
-key ${TYPE}-root.key \
-out ${TYPE}-root-ssigned.pem \
-config ./.ca/config \
-extensions v3_ca
${OPENSSL} req -new -nodes \
-subj "/CN=${CERT_NAME}@${TIMESTAMP}" \
-key ${TYPE}-root.key |
${OPENSSL} ca -batch -notext -days 7300 \
-in /dev/stdin \
-out ${TYPE}-root-xsigned.pem \
-keyfile ${TYPE}-root-old.key \
-cert ${TYPE}-root-old.pem \
-config ./.ca/config \
-extensions v3_ca
CERT_NAME="${PRODUCT}-$(echo ${TYPE} | tr / -)-ca"
echo "Generating ${CERT_NAME} intermediate certificate authority key and certificates"
${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 -notext -days 7300 \
-in /dev/stdin \
-out ${TYPE}-ca.pem \
-keyfile ${TYPE}-root.key \
-cert ${TYPE}-root-ssigned.pem \
-config ./.ca/config \
-extensions v3_ca
cat ${TYPE}-ca.pem \
${TYPE}-root-ssigned.pem \
${TYPE}-root-xsigned.pem \
${TYPE}-root-old.pem > ${TYPE}-ca.crt
cat ${TYPE}-root.key >> ${TYPE}-ca.key
done
${OPENSSL} genrsa ${OPENSSL_GENRSA_FLAGS:-} -out service.key 2048
cat ${DATA_DIR}/server/tls/service.key >> service.key
export SERVER_CA_HASH=$(${OPENSSL} x509 -noout -fingerprint -sha256 -in server-ca.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}"
echo "Updated server token: ${SERVER_TOKEN}"
echo "Updated agent token: ${AGENT_TOKEN}"
echo
echo "To update certificates, you may now run:"
echo " k3s certificate rotate-ca --path=${TEMP_DIR}"