Skip to content

Instantly share code, notes, and snippets.

@facsiaginsa
Last active April 29, 2026 04:34
Show Gist options
  • Select an option

  • Save facsiaginsa/ec0ac6b005a95353c572284a08ae474c to your computer and use it in GitHub Desktop.

Select an option

Save facsiaginsa/ec0ac6b005a95353c572284a08ae474c to your computer and use it in GitHub Desktop.
How to Create a Human User in Kubernetes (Read Only All Resources)

Kubernetes Read-Only User Setup Guide

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

Prerequisites

Before starting, make sure you have:

  • kubectl installed and configured with cluster-admin access
  • openssl installed on your local machine
  • Access to the cluster's CA (available via your existing kubeconfig)

Step 1 — Generate Private Key and CSR

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"

Step 2 — Submit CSR to Kubernetes

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 newuser

Step 3 — Retrieve the Signed Certificate

Once 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 -dates

Step 4 — Apply ClusterRoleBinding

Bind the built-in view ClusterRole to the user newuser. This grants cluster-wide read-only access across all namespaces.

Note: The built-in view role 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.yaml

Step 5 — Build the kubeconfig File

Assemble 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.yaml

Step 6 — Verify Permissions

Run 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 -A

Step 7 — Deliver the kubeconfig to Staff

Send 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 Summary

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

Security Notes

⚠️ Never share or commit newuser.key to 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 view role with a custom ClusterRole that includes secrets in its resource list.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment