Skip to content

Instantly share code, notes, and snippets.

@naingyeminn
Created January 21, 2023 19:51
Show Gist options
  • Save naingyeminn/24160831a1965c69e683c094e9975ae4 to your computer and use it in GitHub Desktop.
Save naingyeminn/24160831a1965c69e683c094e9975ae4 to your computer and use it in GitHub Desktop.
Generate kubeconfig with user-based client certificate and assign role.
#!/bin/bash
if [ -z "${1}" ]; then
echo "Please provide a username and the namespace or the username only for the cluster role..."
echo "Usage: ${0} USERNAME [NAMESPACE] [ROLE]"
echo "Example: ${0} auditor default view"
exit
fi
USERNAME=${1}
if [ -z ${2} ]; then
NAMESPACE=default
else
NAMESPACE=${2}
fi
CERT_NAME=${USERNAME}-${NAMESPACE}
CLUSTER_SERVER=$(kubectl config view --flatten --minify -o jsonpath='{.clusters[0].cluster.server}')
CLUSTER_NAME=$(kubectl config view --flatten --minify -o jsonpath='{.clusters[0].name}')
CA_CERT=$(kubectl config view --flatten --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
echo "Removing old csr..."
kubectl get csr ${CERT_NAME} && kubectl delete csr ${CERT_NAME}
echo "Generating new key (${USERNAME}.key) and csr (${USERNAME}.csr)..."
openssl req -new -newkey rsa:4096 -keyout ${USERNAME}.key -out ${USERNAME}.csr -noenc -subj "/CN=${USERNAME}/0=${NAMESPACE}"
echo "Creating csr (${CERT_NAME}) in k8s..."
cat <<EOF | kubectl create -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: ${CERT_NAME}
spec:
groups:
- system:authenticated
request: $(cat ${USERNAME}.csr | base64 | tr -d '\n')
signerName: kubernetes.io/kube-apiserver-client
usages:
- digital signature
- key encipherment
- client auth
EOF
echo "Signing the csr (${CERT_NAME})..."
kubectl certificate approve ${CERT_NAME}
echo "Exporting the certificate (${CERT_NAME}.crt)..."
kubectl get csr $CERT_NAME -o jsonpath='{.status.certificate}' | base64 -d > ${CERT_NAME}.crt
echo "Generating the config for ${USERNAME} (${CERT_NAME}.kubeconfig)..."
cat <<EOF > ${CERT_NAME}.kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ${CA_CERT}
server: ${CLUSTER_SERVER}
name: ${USERNAME}-${CLUSTER_NAME}
contexts:
- context:
cluster: ${USERNAME}-${CLUSTER_NAME}
namespace: ${NAMESPACE}
user: ${USERNAME}
name: ${CERT_NAME}
current-context: ${CERT_NAME}
kind: Config
users:
- name: ${USERNAME}
user:
client-certificate-data: $(base64 -w0 < ${CERT_NAME}.crt)
client-key-data: $(base64 -w0 < ${USERNAME}.key)
EOF
#############################################################
bind_role () {
ROLE_TYPE=`([ $(kubectl get role -o custom-columns=NAME:.metadata.name --no-headers -A | grep "^${1}$") ] && echo role) || ([ $(kubectl get clusterrole -o custom-columns=NAME:.metadata.name --no-headers | grep "^${1}$") ] && echo clusterrole)`
if [ -z "${ROLE_TYPE}" ]; then
echo "There is no Role/ClusterRole named ${1}"
exit
fi
RB_NAME=${NAMESPACE}-${1}
echo "Binding the ${USERNAME} user with the cluster ${1} role..."
kubectl -n ${NAMESPACE} get rolebinding ${RB_NAME} &> /dev/null
if [ $? -gt 0 ]; then
kubectl -n ${NAMESPACE} create rolebinding ${RB_NAME} --${ROLE_TYPE} ${1} --user ${USERNAME}
else
kubectl -n ${NAMESPACE} patch rolebinding ${RB_NAME} --type='json' -p='[{"op": "add", "path": "/subjects/0", "value": {"kind": "User", "name": "'${USERNAME}'" } }]'
fi
}
bind_role ${3}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment