5.2.4.4. CA upload
This section covers uploading root certificates to the Kubernetes cluster. The kubeadm-certs secret is created manually and contains the keys and certificates required when adding new control plane nodes (
kubeadm join). This approach allows sensitive data to be securely transferred between control plane nodes.
- Init
Uploading root certificates to Kubernetes
● Required
Uploading root certificates to Kubernetes
● Required
This section provides instructions for uploading root certificates to the Kubernetes control plane. The certificates are uploaded in encrypted form as a Secret resource, which allows them to be securely transferred and decrypted on another node for managing the control plane node lifecycle.
- HardWay
- Kubeadm
Environment variables for configuration file template
export AUTH_EXTRA_GROUPS="system:bootstrappers:kubeadm:default-node-token"
Role model preparation
This block prepares the role model for granting access to the kubeadm-certs secret. This is necessary so that control plane nodes can securely obtain root certificates through the Kubernetes API when joining the cluster. The role is bound to the ${AUTH_EXTRA_GROUPS} group, which kubeadm typically falls under during join.
kubectl \
--kubeconfig=/etc/kubernetes/super-admin.conf apply -f - <<EOF
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kubeadm:kubeadm-certs
namespace: kube-system
rules:
- apiGroups:
- ""
resourceNames:
- kubeadm-certs
resources:
- secrets
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kubeadm:kubeadm-certs
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubeadm:kubeadm-certs
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: ${AUTH_EXTRA_GROUPS}
EOF
Working directory
mkdir -p /etc/kubernetes/openssl
Environment variables
export CERTIFICATE_UPLOAD_KEY=0c00c2fd5c67c37656c00d78a9d7e1f2eb794ef8e4fc3e2a4b532eb14323cd59
cat <<EOF > /etc/kubernetes/openssl/encrypt.py
#!/usr/bin/env python3
import sys, base64, os
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key = bytes.fromhex(sys.argv[1])
path = sys.argv[2]
with open(path, "rb") as f:
data = f.read()
nonce = os.urandom(12)
aesgcm = AESGCM(key)
ct = aesgcm.encrypt(nonce, data, None)
# kubeadm expects: nonce + ciphertext (including auth tag)
payload = nonce + ct
print(base64.b64encode(payload).decode())
EOF
cat <<'EOF' > /etc/kubernetes/openssl/upload-certs.sh
#!/bin/bash
set -euo pipefail
CERT_PATH="/etc/kubernetes/pki"
PY_SCRIPT="$(dirname "$0")/encrypt.py"
declare -A files=(
["ca.crt"]="$CERT_PATH/ca.crt"
["ca.key"]="$CERT_PATH/ca.key"
["etcd-ca.crt"]="$CERT_PATH/etcd/ca.crt"
["etcd-ca.key"]="$CERT_PATH/etcd/ca.key"
["front-proxy-ca.crt"]="$CERT_PATH/front-proxy-ca.crt"
["front-proxy-ca.key"]="$CERT_PATH/front-proxy-ca.key"
["sa.key"]="$CERT_PATH/sa.key"
["sa.pub"]="$CERT_PATH/sa.pub"
)
KEY="${CERTIFICATE_UPLOAD_KEY:-}"
if [[ -z "$KEY" ]]; then
echo "[ERROR] CERTIFICATE_UPLOAD_KEY is not set"
exit 1
fi
echo "[INFO] Using certificate key: $KEY"
TMP_DIR=$(mktemp -d)
SECRET_FILE="$TMP_DIR/secret.yaml"
cat <<EOF_SECRET > "$SECRET_FILE"
apiVersion: v1
kind: Secret
metadata:
name: kubeadm-certs
namespace: kube-system
type: Opaque
data:
EOF_SECRET
for name in "${!files[@]}"; do
path="${files[$name]}"
if [[ ! -f "$path" ]]; then
echo "[WARN] Skipping missing file: $path"
continue
fi
echo "[INFO] Encrypting $name..."
b64=$(python3 "$PY_SCRIPT" "$KEY" "$path")
echo " $name: $b64" >> "$SECRET_FILE"
done
echo "[INFO] Applying secret to cluster..."
kubectl apply -f "$SECRET_FILE"
echo "[INFO] Secret successfully uploaded."
EOF
Setting permissions
chmod +x /etc/kubernetes/openssl/upload-certs.sh
Running the script
/etc/kubernetes/openssl/upload-certs.sh
[INFO] Using certificate key: 0c00c2fd5c67c37656c00d78a9d7e1f2eb794ef8e4fc3e2a4b532eb14323cd59
[INFO] Encrypting front-proxy-ca.key...
[INFO] Encrypting sa.key...
[INFO] Encrypting front-proxy-ca.crt...
[INFO] Encrypting etcd-ca.crt...
[INFO] Encrypting sa.pub...
[INFO] Encrypting ca.key...
[INFO] Encrypting ca.crt...
[INFO] Encrypting etcd-ca.key...
[INFO] Applying secret to cluster...
secret/kubeadm-certs configured
[INFO] Secret successfully uploaded.
Uploading certificates
kubeadm init phase upload-certs \
--config=/var/run/kubeadm/kubeadm.yaml \
--kubeconfig=/etc/kubernetes/super-admin.conf \
--upload-certs
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
0c00c2fd5c67c37656c00d78a9d7e1f2eb794ef8e4fc3e2a4b532eb14323cd59