Skip to content

Instantly share code, notes, and snippets.

@pbertera
Last active September 13, 2024 07:06
Show Gist options
  • Save pbertera/ca4eedb46a5446228d6dafb0f0125d4b to your computer and use it in GitHub Desktop.
Save pbertera/ca4eedb46a5446228d6dafb0f0125d4b to your computer and use it in GitHub Desktop.
OpenShift API Client CA replace script
#!/bin/bash
set -e -o pipefail
cleanup(){
rm -f ${USER}.key ${USER}.csr ${USER}.crt ${NAME}-ca.key ${NAME}-ca.crt
}
msg(){
echo "$(date) $@"
}
msgne(){
echo -ne "$(date) $@)"
}
genCerts(){
msg "create the CA key"
openssl genrsa -out ${NAME}-ca.key 4096
msg "create the CA certificate"
openssl req -x509 -new -nodes -key ${NAME}-ca.key -sha256 -days $VALIDITY -out ${NAME}-ca.crt -subj "${CA_SUBJ}"
msg "create the ${USER} req"
openssl req -nodes -newkey rsa:2048 -keyout ${USER}.key -subj "${USER_SUBJ}" -out ${USER}.csr
msg "sign the ${USER} req"
# see https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers
openssl x509 -extfile <(printf "extendedKeyUsage = clientAuth") -req -in ${USER}.csr \
-CA ${NAME}-ca.crt -CAkey ${NAME}-ca.key -CAcreateserial -out ${USER}.crt -days $VALIDITY -sha256
}
backupCA(){
clientCA=$(oc get apiserver/cluster -o 'jsonpath={.spec.clientCA.name}')
annotate="yes"
if [ "$clientCA" == "" ]; then
clientCA=admin-kubeconfig-client-ca
annotate="no"
fi
msg "backup of $clientCA ConfigMap"
oc get cm $clientCA -n openshift-config -o yaml > ${clientCA}-CA-backup.yaml
oc extract cm/$clientCA -n openshift-config --to=- --keys=ca-bundle.crt | openssl x509 -in - -text -noout > ${clientCA}-CA-backup.crt
if [ "$annotate" == "yes" ]; then
oc annotate -n openshift-config cm $clientCA "$ANNOTATION"="$(date -R)"
fi
}
addClientCA(){
msg "create the client-ca ConfigMap"
suffix=$(md5sum ${NAME}-ca.crt | cut -c 1-5)
oc create configmap client-ca-${suffix} -n openshift-config --from-file=ca-bundle.crt=${NAME}-ca.crt
msg "patch the ApiServer"
oc patch apiserver cluster --type=merge -p "{\"spec\": {\"clientCA\": {\"name\": \"client-ca-${suffix}\"}}}"
}
replaceDefaultCA(){
msg "replace admin-kubeconfig-client-ca ConfigMap"
oc create configmap admin-kubeconfig-client-ca -n openshift-config --from-file=ca-bundle.crt=${NAME}-ca.crt \
--dry-run -o yaml | oc replace -f -
}
removeCAfromAPIServer(){
msg "removing the ca from APIServer/cluster"
oc --kubeconfig="$NEW_KUBECONFIG" patch apiserver cluster --type=json -p="[{'op': 'remove', 'path': '/spec/clientCA'}]"
}
createKubeConfig(){
msg "add system:admin credentials, context to the kubeconfig"
oc config set-credentials system:admin --client-certificate=${USER}.crt \
--client-key=${USER}.key --embed-certs --kubeconfig=$NEW_KUBECONFIG
msg "create context for the ${USER}"
oc config set-context ${USER} --cluster=$(oc config view -o jsonpath='{.clusters[0].name}') \
--namespace=default --user=${USER} --kubeconfig=$NEW_KUBECONFIG
msg "extract certificate authority"
oc -n openshift-authentication rsh `oc get pods -n openshift-authentication -o name | head -1` \
cat /run/secrets/kubernetes.io/serviceaccount/ca.crt > ingress-ca.crt
msg "set certificate authority data"
oc config set-cluster $(oc config view -o jsonpath='{.clusters[0].name}') \
--server=$(oc config view -o jsonpath='{.clusters[0].cluster.server}') \
--certificate-authority=ingress-ca.crt --kubeconfig=$NEW_KUBECONFIG --embed-certs
msg "set current context to ${USER}"
oc config use-context ${USER} --kubeconfig=$NEW_KUBECONFIG
}
testKubeConfig(){
set +e
msgne "test client certificate authentication with ${USER}:"
max_retry=100
counter=0
until oc --kubeconfig="$NEW_KUBECONFIG" login -u ${USER} > /dev/null 2>&1
do
sleep 10
[[ $counter -eq $max_retry ]] && echo "Failed!" && exit 1
echo -ne .
((counter++))
done
set -e
}
usage(){
echo "$0 [options]"
echo
echo "OPTIONS:"
echo " -r | --replace replace the default CA (no)"
echo " -R | --remove remove the CA from the APIServer (no)"
echo " -u | --user set the user (system:admin)"
echo " -g | --group set the group (system:masters)"
echo " -v | --validity set the certificate days (3500)"
exit
}
main(){
while [ $# -gt 0 ]; do
case "$1" in
-r | --replace-default-ca)
REPLACE_DEFAULT_CA=yes
shift
;;
-R | --remove)
REMOVE_CA_FROM_APISERVER=yes
shift
;;
-u | --user)
USER=$2
shift
shift
;;
-g | --group)
GROUP=$2
shift
shift
;;
-v | --validity)
VALIDITY=$2
shift
shift
;;
-h | --help)
usage
shift
;;
esac
done
USER_SUBJ="/O=${GROUP}/CN=${USER}"
cleanup
genCerts
backupCA
addClientCA
createKubeConfig
testKubeConfig
[[ "$REPLACE_DEFAULT_CA" == "yes" ]] && replaceDefaultCA
[[ "$REMOVE_CA_FROM_APISERVER" == "yes" ]] && removeCAfromAPIServer
}
NAME=myCA
CA_SUBJ="/OU=openshift/CN=admin-kubeconfig-signer-custom"
USER=system:admin
GROUP=system:masters
VALIDITY=3650
NEW_KUBECONFIG=kubeconfig.${USER}
ANNOTATION="backup.kubadmin-rotator.script"
REPLACE_DEFAULT_CA=no
REMOVE_CA_FROM_APISERVER=no
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment