| Field | Value |
|---|---|
| Username | newuser |
| Scope | Cluster-wide (all namespaces) |
| Permissions | Read-only — get, list, watch |
| Secrets Access | Excluded (built-in view role) |
| Certificate Expiry | 1 year |
Before starting, make sure you have:
kubectlinstalled and configured with cluster-admin accessopensslinstalled on your local machine- Access to the cluster's CA (available via your existing kubeconfig)
Run the following commands on your local machine to generate a private key and Certificate Signing Request (CSR) for newuser.
# Generate a 2048-bit RSA private key
openssl genrsa -out newuser.key 2048
# Generate the CSR — CN is the Kubernetes username, O is the group
openssl req -new -key newuser.key -out newuser.csr -subj "/CN=newuser/O=readonly-group"
# Encode the CSR to base64 — copy this output for Step 2
cat newuser.csr | base64 | tr -d "\n"Paste the base64 output from Step 1 into the request field in 01-newuser-csr.yaml, then apply and approve it.
# 01-newuser-csr.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: newuser
spec:
request: <PASTE_BASE64_CSR_HERE>
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 31536000 # 1 year
usages:
- client auth# Submit the CSR to the cluster
kubectl apply -f 01-newuser-csr.yaml
# Approve the CSR so the cluster signs the certificate
kubectl certificate approve newuser
# Verify — STATUS should show "Approved,Issued"
kubectl get csr newuserOnce approved, extract the signed certificate and save it locally.
# Decode and save the signed certificate
kubectl get csr newuser -o jsonpath='{.status.certificate}' | base64 -d > newuser.crt
# Verify the certificate content and expiry date
openssl x509 -in newuser.crt -noout -subject -datesBind the built-in view ClusterRole to the user newuser. This grants cluster-wide read-only access across all namespaces.
Note: The built-in
viewrole does not include access to Secrets. If Secret access is required, a custom ClusterRole is needed.
# 02-newuser-clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: newuser-readonly-binding
subjects:
- kind: User
name: newuser
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io# Apply the ClusterRoleBinding to the cluster
kubectl apply -f 02-newuser-clusterrolebinding.yamlAssemble the kubeconfig file for newuser using the cluster info, signed certificate, and private key.
# Gather cluster information
CLUSTER_NAME=$(kubectl config view --minify -o jsonpath='{.clusters[0].name}')
CLUSTER_SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
CLUSTER_CA=$(kubectl config view --minify --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')
# Add cluster info to the new kubeconfig
kubectl config set-cluster $CLUSTER_NAME \
--server=$CLUSTER_SERVER \
--certificate-authority=<(echo $CLUSTER_CA | base64 -d) \
--embed-certs=true \
--kubeconfig=newuser-kubeconfig.yaml
# Add user credentials
kubectl config set-credentials newuser \
--client-certificate=newuser.crt \
--client-key=newuser.key \
--embed-certs=true \
--kubeconfig=newuser-kubeconfig.yaml
# Create a context linking cluster and user
kubectl config set-context newuser-context \
--cluster=$CLUSTER_NAME \
--user=newuser \
--kubeconfig=newuser-kubeconfig.yaml
# Set newuser-context as the active context
kubectl config use-context newuser-context \
--kubeconfig=newuser-kubeconfig.yamlRun these checks to confirm the correct permissions are in place before handing over the kubeconfig.
# READ — should return: yes
kubectl auth can-i get pods --as=newuser -A
kubectl auth can-i list deployments --as=newuser -A
# WRITE — should return: no
kubectl auth can-i delete pods --as=newuser -A
kubectl auth can-i create deployments --as=newuser -ASend newuser-kubeconfig.yaml to your staff securely. They can use it in one of the following ways:
# Option A — Use per command
kubectl get pods -A --kubeconfig=newuser-kubeconfig.yaml
# Option B — Set as default for the session
export KUBECONFIG=~/newuser-kubeconfig.yaml
# Option C — Merge with existing kubeconfig
KUBECONFIG=~/.kube/config:~/newuser-kubeconfig.yaml kubectl config view --flatten > ~/.kube/config| File | Description | Share with Staff? |
|---|---|---|
newuser.key |
Private key | ❌ Keep secret |
newuser.crt |
Signed certificate | ❌ Intermediate file |
01-newuser-csr.yaml |
CSR manifest | ❌ Cluster use only |
02-newuser-clusterrolebinding.yaml |
RBAC binding manifest | ❌ Cluster use only |
newuser-kubeconfig.yaml |
Final kubeconfig | ✅ Share this |
⚠️ Never share or commitnewuser.keyto version control.
- To revoke access, delete the ClusterRoleBinding:
kubectl delete clusterrolebinding newuser-readonly-binding
- To fully revoke, also delete the CSR:
kubectl delete csr newuser
- Certificate expiry is set to 1 year. Plan for renewal before it expires.
- If Secret access is ever needed, replace the
viewrole with a customClusterRolethat includessecretsin its resource list.