Skip to content

Instantly share code, notes, and snippets.

@Baarsgaard
Created January 23, 2025 19:32
Show Gist options
  • Select an option

  • Save Baarsgaard/49302e4b302860f740fb54d96f84297a to your computer and use it in GitHub Desktop.

Select an option

Save Baarsgaard/49302e4b302860f740fb54d96f84297a to your computer and use it in GitHub Desktop.
Create new User kubeconfig using cert based authentication, requires a working kubeconfig with permission to create and sign `certificatesigningrequests`
#!/bin/bash
set -euo pipefail
# Usage:
USER="$1"
ROLE="${2:-cluster-admin}"
NAMESPACE="${3:-default}"
log() {
LVL="$1"
MSG="$2"
EXIT="${3:-}"
# Log everything to stderr to not mix it with the final kubeconfig
>&2 echo "$(date --iso-8601=seconds) $LVL $MSG"
if [[ -n "$EXIT" ]]; then
exit $EXIT
fi
}
log info "Generating rsa key"
openssl genrsa -out "$USER.key" 4096
log info "Generating Certificate Signing Request"
openssl req -new -key "$USER.key" -nodes -out "$USER.csr" -config <(cat << CSRCNF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = $USER
O = developers
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
CSRCNF
)
CSR_B64="$(base64 -w 0 "$USER.csr")"
log info "Create and apply Certificate Signing Request manifest"
>/dev/null kubectl apply -f - << K8SCSR
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: $USER-$ROLE
namespace: $NAMESPACE
spec:
signerName: kubernetes.io/kube-apiserver-client
groups:
- system:authenticated
request: $CSR_B64
usages:
- client auth
K8SCSR
log info "Approve and Sign Certificate"
>/dev/null kubectl certificate approve -n "$NAMESPACE" "$USER-$ROLE"
log info "Get Certificate"
kubectl get csr "$USER-$ROLE" -o jsonpath='{.status.certificate}' | base64 -d > "$USER.crt"
>/dev/null kubectl delete csr "$USER-$ROLE"
log info "Reading current kubeconfig"
CURRENT_KUBECONFIG="$(kubectl config view --raw)"
# Get current context
CURRENT_CONTEXT="$(kubectl config current-context)"
# Use name of context to find cluster name
CLUSTER_NAME="$(yq ".contexts[] | select(.name == \"$CURRENT_CONTEXT\") | .context.cluster" <(echo "$CURRENT_KUBECONFIG"))"
log info "Saving connection parameters to $USER.kubeconfig"
>/dev/null kubectl config set-cluster "$CLUSTER_NAME" \
--kubeconfig="$USER.kubeconfig" \
--server="$(yq ".clusters[] | select(.name == \"$CLUSTER_NAME\") | .cluster.server" <(echo "$CURRENT_KUBECONFIG"))" \
--certificate-authority=<(:|openssl s_client -connect 127.0.0.1:41233 | grep -A 40 'BEGIN CERTIFICATE' | grep -B 40 'END CERTIFICATE') \
--embed-certs=true
log info "Saving credentials(certificate) to $USER.kubeconfig"
>/dev/null kubectl config set-credentials "$USER" \
--kubeconfig="$USER.kubeconfig" \
--client-certificate="$USER.crt" \
--client-key="$USER.key" \
--embed-certs=true
log info "Saving $USER<->$CLUSTER_NAME context to $USER.kubeconfig"
>/dev/null kubectl config set-context "$USER" \
--kubeconfig="$USER.kubeconfig" \
--cluster="$CLUSTER_NAME" \
--namespace="$NAMESPACE" \
--user="$USER"
>/dev/null kubectl config use-context "$USER" \
--kubeconfig="$USER.kubeconfig"
# Assign permissions to User as the last step
kubectl apply -f - << CRB
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: "$USER"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: "$ROLE"
subjects:
- kind: User
name: "$USER"
apiGroup: rbac.authorization.k8s.io
CRB
log info "Test new kubeconfig: kubectl --kubeconfig $USER.kubeconfig get pods -n $NAMESPACE"
>&2 kubectl config view --kubeconfig="$USER.kubeconfig"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment