Skip to content

Kubeconfig & Kubernetes PKI Fundamentals

Comprehensive guide to understanding Kubernetes PKI (Public Key Infrastructure), X.509 certificates, and kubeconfig file structure. Learn how to work with certificates, create custom users, and manage cluster authentication.

Quick Reference: kubectl config Commands

bash
# View configuration
kubectl config view                    # Show entire kubeconfig
kubectl config view --raw              # Show with decoded credentials
kubectl config view --flatten          # Merge all kubeconfigs
kubectl config view --minify           # Show only current context
kubectl config view -o json            # Output as JSON

# Set cluster
kubectl config set-cluster kubernetes \
  --server=https://172.30.1.2:6443 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt

# Set user credentials (certificate-based)
kubectl config set-credentials kubelet \
  --client-certificate=/etc/kubernetes/pki/kubelet.crt \
  --client-key=/etc/kubernetes/pki/kubelet.key \
  --embed-certs=true

# Set user credentials (token-based)
kubectl config set-credentials token-user \
  --token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# Create context
kubectl config set-context default \
  --cluster=kubernetes \
  --user=kubelet \
  --namespace=default

# Use context
kubectl config use-context default

# Get current context
kubectl config current-context

# Get all clusters, users, contexts
kubectl config get-clusters
kubectl config get-users
kubectl config get-contexts

# Rename context
kubectl config rename-context old-name new-name

# Delete entries
kubectl config delete-cluster cluster-name
kubectl config delete-user user-name
kubectl config delete-context context-name

# Unset (remove) configuration
kubectl config unset current-context
kubectl config unset clusters.cluster-name
kubectl config unset users.user-name
kubectl config unset contexts.context-name.namespace

Advanced: kubectl config Usage Patterns

Pattern 1: Setup Complete Cluster Access (One Command Sequence)

bash
# 1. Add cluster configuration
kubectl config set-cluster prod-cluster \
  --server=https://api.prod.example.com:6443 \
  --certificate-authority=/path/to/ca.crt

# 2. Add user with certificate
kubectl config set-credentials prod-admin \
  --client-certificate=/path/to/admin.crt \
  --client-key=/path/to/admin.key \
  --embed-certs=true

# 3. Create context binding
kubectl config set-context prod-admin \
  --cluster=prod-cluster \
  --user=prod-admin \
  --namespace=default

# 4. Switch to use it
kubectl config use-context prod-admin

# Verify
kubectl cluster-info
kubectl get nodes

Pattern 2: Add Token-Based User

bash
# For service account tokens
kubectl config set-credentials service-user \
  --token=$(kubectl create token my-service-account)

# For predefined token
kubectl config set-credentials token-user \
  --token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0...

# Use in context
kubectl config set-context token-context \
  --cluster=kubernetes \
  --user=token-user

Pattern 3: Multiple Kubeconfigs

bash
# Combine multiple kubeconfig files
export KUBECONFIG=~/.kube/config:~/.kube/prod-config:~/.kube/dev-config

# View all merged
kubectl config view

# Switch between clusters easily
kubectl config use-context prod-admin
kubectl config use-context dev-admin

# Make permanent
echo 'export KUBECONFIG=~/.kube/config:~/.kube/prod-config:~/.kube/dev-config' >> ~/.zshrc

Pattern 4: Extract User Credentials

bash
# Extract certificate from kubeconfig
kubectl config view --raw | \
  grep 'client-certificate-data:' | \
  head -1 | \
  awk '{print $2}' | \
  base64 -d > user.crt

# Extract key from kubeconfig
kubectl config view --raw | \
  grep 'client-key-data:' | \
  head -1 | \
  awk '{print $2}' | \
  base64 -d > user.key

# Extract CA certificate
kubectl config view --raw | \
  grep 'certificate-authority-data:' | \
  head -1 | \
  awk '{print $2}' | \
  base64 -d > ca.crt

Pattern 5: Context-Specific Namespace

bash
# Create different contexts pointing to same cluster but different namespaces
kubectl config set-context dev-namespace \
  --cluster=kubernetes \
  --user=devuser \
  --namespace=development

kubectl config set-context prod-namespace \
  --cluster=kubernetes \
  --user=devuser \
  --namespace=production

# Switch context to change namespace automatically
kubectl config use-context dev-namespace   # Now using development namespace
kubectl get pods                            # Shows pods from development
kubectl config use-context prod-namespace  # Now using production namespace
kubectl get pods                            # Shows pods from production

Pattern 6: Temporary Context Override

bash
# Switch context just for one command
kubectl --context=staging-admin get nodes

# Override namespace for one command
kubectl --namespace=kube-system get pods

# Override entire cluster connection
kubectl --server=https://different-api:6443 get nodes

Pattern 7: Audit Kubeconfig

bash
# Show current context
kubectl config current-context

# Show all contexts with current marker
kubectl config get-contexts

# Show which cluster/user/namespace current context uses
kubectl config view | grep -A3 "current-context"

# Check if specific context exists
kubectl config get-contexts | grep "^[*]" | awk '{print $2}'

# Get API server for current context
kubectl config view | grep -A2 "current-context" | grep cluster | awk '{print $2}'

Pattern 8: Cluster Switching Script

bash
#!/bin/bash
# Interactive cluster switcher

# Get all contexts
CONTEXTS=$(kubectl config get-contexts | awk 'NR > 1 {print $2}')

echo "Available contexts:"
select CONTEXT in $CONTEXTS; do
  kubectl config use-context "$CONTEXT"
  echo "Switched to: $CONTEXT"
  kubectl config current-context
  kubectl cluster-info | head -1
  break
done

Part 1: Kubernetes PKI Basics

What is PKI?

PKI (Public Key Infrastructure) is a system for creating, managing, and validating digital certificates used for authentication and encryption in Kubernetes. Every component that needs to authenticate uses certificates signed by the cluster's Certificate Authority (CA).

PKI Directory Structure

All Kubernetes certificates are stored in /etc/kubernetes/pki/:

/etc/kubernetes/pki/
├── ca.crt                  # Cluster CA certificate (what signed everything)
├── ca.key                  # Cluster CA private key (secret! signs new certs)
├── apiserver.crt           # API Server certificate
├── apiserver.key           # API Server private key
├── kubelet*.crt            # Kubelet certificates
├── controller-manager.crt  # Controller manager certificate
├── scheduler.crt           # Scheduler certificate
├── front-proxy-ca.*        # Front proxy CA for API aggregation
├── etcd/                   # ETCD certificates (database)
│   ├── ca.crt
│   ├── server.crt
│   └── server.key
└── sa.key                  # Service account signing key (not X.509)

Why Multiple CAs?

Kubernetes uses different CAs for security isolation:

  1. Cluster CA (ca.crt/ca.key): Main CA, signs kubelet, controller-manager, scheduler certificates
  2. API Server CA: Dedicated CA for API server communication
  3. Front Proxy CA: For aggregated API servers
  4. ETCD CA: Isolated CA for ETCD database communication

Part 2: Understanding X.509 Certificates

Certificate Structure

Every X.509 certificate contains identity information:

Certificate Structure
├── Version: v3 (X.509v3)
├── Serial Number: Unique ID (2897472356293683110)
├── Signature Algorithm: sha256WithRSAEncryption
├── Issuer: CN=kubernetes (who signed this cert)
├── Validity Period
│   ├── Not Before: Jan 1 2026 GMT
│   └── Not After: Dec 30 2035 GMT (10 year validity)
├── Subject: CN=kubernetes-admin (who this cert is for)
├── Public Key Info
│   ├── Algorithm: RSA
│   └── Size: 2048 bits
└── Extensions (critical for Kubernetes)
    ├── Subject Alternative Names (SAN): DNS names, IP addresses
    ├── Key Usage: digitalSignature, keyEncipherment
    └── Extended Key Usage: serverAuth, clientAuth

Certificate Components

1. CN (Common Name) - The Identity

CN identifies WHO the certificate is for:

CN=kubernetes-admin      # User name "kubernetes-admin"
CN=kubelet              # System component "kubelet"
CN=controller-manager   # System component "controller-manager"
CN=kubernetes           # API server default identity

2. O (Organization) - User Groups for RBAC

Organization field maps to groups, used for Role-Based Access Control:

O=system:masters              # Built-in admin group
O=kubeadm:cluster-admins      # Created by kubeadm (admins)
O=system:nodes                # For kubelet certificates
O=developers                  # Custom developer group
O=system:authenticated        # Standard authenticated users group

Example Certificate Subject:

Subject: O=kubeadm:cluster-admins, CN=kubernetes-admin
         ↓                      ↓
      Groups              User Name

3. SAN (Subject Alternative Names) - Where the Certificate is Valid

SAN lists all valid hostnames and IPs for the certificate:

DNS Names:
- kubernetes
- kubernetes.default
- kubernetes.default.svc
- kubernetes.default.svc.cluster.local
- localhost

IP Addresses:
- 127.0.0.1 (localhost)
- 10.96.0.1 (Kubernetes service IP)
- 10.0.0.100 (Control plane node IP)
- 10.0.0.101 (Other control plane nodes)

Why important? If a DNS name or IP is NOT in SAN, the certificate is invalid for that endpoint!


Part 3: Inspecting Certificates with OpenSSL

Basic Certificate Inspection

bash
# View certificate details
openssl x509 -in /etc/kubernetes/pki/ca.crt -text -noout

# View first 30 lines
openssl x509 -in /etc/kubernetes/pki/ca.crt -text -noout | head -30

# Extract specific fields
openssl x509 -in cert.crt -noout -subject      # Get CN and O
openssl x509 -in cert.crt -noout -issuer       # Who signed it
openssl x509 -in cert.crt -noout -dates        # Validity period

Extract Certificate from Kubeconfig

Kubeconfig stores certificates as base64-encoded data. To decode:

bash
# Extract CA certificate from kubeconfig
kubectl config view --raw | \
  grep 'certificate-authority-data:' | head -1 | \
  awk '{print $2}' | \
  base64 -d > ca.crt

# Inspect
openssl x509 -in ca.crt -text -noout | head -20

Check Certificate Validity

bash
# View Not Before and Not After dates
openssl x509 -in cert.crt -noout -dates
# Output:
# notBefore=Jan  1 07:08:58 2026 GMT
# notAfter=Dec 30 07:13:58 2035 GMT

# Check days until expiration
openssl x509 -in cert.crt -noout -enddate | cut -d'=' -f2 | \
  xargs -I {} date -d {} +%s | \
  xargs -I {} expr \( {} - $(date +%s) \) / 86400

View SAN Extensions

bash
# See all Subject Alternative Names
openssl x509 -in cert.crt -text -noout | grep -A5 "Subject Alternative Name"

# Example output:
#     X509v3 Subject Alternative Name: 
#         DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, 
#         IP Address:10.96.0.1, IP Address:10.0.0.1

Part 4: Kubeconfig File Format

Complete Kubeconfig Structure

yaml
apiVersion: v1
kind: Config
preferences: {}

# SECTION 1: Clusters - How to connect to clusters
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTi... # Base64 CA cert
    server: https://172.30.1.2:6443               # API server URL
  name: kubernetes                                 # Cluster name (identifier)

# SECTION 2: Users - Authentication credentials
users:
- name: kubernetes-admin
  user:
    # Method A: Certificate-based auth (most common)
    client-certificate-data: LS0tLS1CRUdJTi...    # Base64 client cert
    client-key-data: LS0tLS1CRUdJTi...            # Base64 client key
    
# SECTION 3: Contexts - Bind (cluster + user + namespace)
contexts:
- context:
    cluster: kubernetes           # Which cluster (from clusters[])
    user: kubernetes-admin        # Which user (from users[])
    namespace: default            # Default namespace for this context
  name: kubernetes-admin@kubernetes  # Context name (identifier)

# SECTION 4: Current context - Default when you run kubectl
current-context: kubernetes-admin@kubernetes

Section Details

Clusters Section

Defines how to reach a Kubernetes cluster:

yaml
clusters:
- cluster:
    # CA cert to verify API server certificate
    certificate-authority-data: [base64 encoded]
    # OR use file path:
    # certificate-authority: /etc/kubernetes/pki/ca.crt
    
    # API server URL
    server: https://api.example.com:6443
    
    # DANGEROUS: Skip cert verification (never in production)
    # insecure-skip-tls-verify: true
  name: production-cluster

Users Section

Defines HOW to authenticate:

yaml
users:
- name: admin
  user:
    # Method 1: Certificate + Key (TLS client auth)
    client-certificate-data: [base64]
    client-key-data: [base64]
    
    # Method 2: Token (for service accounts)
    token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    
    # Method 3: Username/Password (deprecated, rarely used)
    username: user
    password: pass123

Contexts Section

Binds together cluster + user + namespace:

yaml
contexts:
- context:
    cluster: production-cluster   # Reference from clusters[]
    user: admin                   # Reference from users[]
    namespace: kube-system        # Default namespace for commands
  name: prod-admin               # Context identifier

Part 5: Creating Custom Users with Certificates

Step 1: Generate Private Key

bash
# Create a 2048-bit RSA private key for the user
openssl genrsa -out devuser.key 2048

# Result: A private key file that should be kept secret

Step 2: Create Certificate Signing Request (CSR)

A CSR is a request to the CA to sign a certificate:

bash
openssl req -new \
  -key devuser.key \
  -out devuser.csr \
  -subj "/CN=devuser/O=developers/O=kubeadm:cluster-admins"

# /CN=devuser              → Username (Common Name)
# /O=developers            → Group 1
# /O=kubeadm:cluster-admins → Group 2 (RBAC admin group)

Step 3: Sign CSR with Cluster CA

The cluster admin signs the CSR, creating a valid certificate:

bash
# Sign CSR with cluster CA (valid for 365 days)
openssl x509 -req -in devuser.csr \
  -CA /etc/kubernetes/pki/ca.crt \
  -CAkey /etc/kubernetes/pki/ca.key \
  -CAcreateserial \
  -out devuser.crt \
  -days 365

# After this, devuser.crt is a valid Kubernetes certificate

Step 4: Add to Kubeconfig

bash
# 1. Add cluster (if not already there)
kubectl config set-cluster kubernetes \
  --server=https://api.example.com:6443 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt

# 2. Add user with certificate
kubectl config set-credentials devuser \
  --client-certificate=devuser.crt \
  --client-key=devuser.key \
  --embed-certs=true    # Embed cert/key data in kubeconfig file

# 3. Create context
kubectl config set-context devuser-context \
  --cluster=kubernetes \
  --user=devuser

# 4. Switch to use this context
kubectl config use-context devuser-context

# 5. Verify connection
kubectl get nodes

Complete Automation Script

bash
#!/bin/bash
set -e

USERNAME="devuser"
GROUP="developers"
DAYS_VALID=365
CLUSTER_IP="api.example.com:6443"
CA_CERT="/etc/kubernetes/pki/ca.crt"
CA_KEY="/etc/kubernetes/pki/ca.key"

echo "[1/5] Generating private key..."
openssl genrsa -out ${USERNAME}.key 2048

echo "[2/5] Creating certificate signing request..."
openssl req -new \
  -key ${USERNAME}.key \
  -out ${USERNAME}.csr \
  -subj "/CN=${USERNAME}/O=${GROUP}"

echo "[3/5] Signing CSR with cluster CA..."
openssl x509 -req -in ${USERNAME}.csr \
  -CA ${CA_CERT} \
  -CAkey ${CA_KEY} \
  -CAcreateserial \
  -out ${USERNAME}.crt \
  -days ${DAYS_VALID}

echo "[4/5] Adding to kubeconfig..."
kubectl config set-cluster kubernetes \
  --server=https://${CLUSTER_IP} \
  --certificate-authority=${CA_CERT}

kubectl config set-credentials ${USERNAME} \
  --client-certificate=${USERNAME}.crt \
  --client-key=${USERNAME}.key \
  --embed-certs=true

kubectl config set-context ${USERNAME}-context \
  --cluster=kubernetes \
  --user=${USERNAME}

echo "[5/5] Verifying..."
kubectl config get-contexts | grep ${USERNAME}

echo "✅ User '${USERNAME}' created successfully!"
echo "To use: kubectl config use-context ${USERNAME}-context"
echo "To apply RBAC: kubectl create rolebinding dev-role --clusterrole=view --user=${USERNAME}"

Part 7: Kubernetes API CertificateSigningRequest (CSR)

Creating CSR Through Kubernetes API (Real-World Method)

In production clusters, instead of manually signing certificates, you create a CertificateSigningRequest object and let the cluster's control plane sign it.

Practical: Generate CSR and Submit to Kubernetes

Step 1: Generate Private Key and CSR (Client-Side)

bash
# Generate private key
openssl genrsa -out newuser.key 2048

# Create CSR (note: generate CSR with subject, no signing yet)
openssl req -new \
  -key newuser.key \
  -out newuser.csr \
  -subj "/CN=newuser/O=developers"

# Verify CSR was created
openssl req -in newuser.csr -text -noout

Step 2: Create Kubernetes CSR Object

bash
# Base64 encode the CSR
CSR_CONTENT=$(cat newuser.csr | base64 | tr -d '\n')

# Create CSR object
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: newuser-csr
spec:
  request: $CSR_CONTENT
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 31536000  # 1 year
  usages:
  - client auth
EOF

# Verify CSR was created
kubectl get csr
kubectl describe csr newuser-csr

Step 3: Approve the CSR

bash
# Admin approves the request
kubectl certificate approve newuser-csr

# Verify it's approved
kubectl get csr newuser-csr
# Status should show: Approved, Issued

# View the approved certificate (base64 encoded)
kubectl get csr newuser-csr -o jsonpath='{.status.certificate}' | base64 -d > newuser.crt

# Verify the certificate
openssl x509 -in newuser.crt -text -noout | head -20

Step 4: Add User to Kubeconfig

bash
# Set cluster (if not already present)
kubectl config set-cluster kubernetes \
  --server=https://api.example.com:6443 \
  --certificate-authority=/path/to/ca.crt

# Add user with the issued certificate
kubectl config set-credentials newuser \
  --client-certificate=newuser.crt \
  --client-key=newuser.key \
  --embed-certs=true

# Create context
kubectl config set-context newuser-context \
  --cluster=kubernetes \
  --user=newuser

# Test access
kubectl config use-context newuser-context
kubectl get pods

Complete Automation Script

bash
#!/bin/bash
set -e

USERNAME="$1"
GROUP="${2:-developers}"
CLUSTER_NAME="${3:-kubernetes}"
API_SERVER="${4:-https://api.example.com:6443}"
CA_PATH="${5:-/etc/kubernetes/pki/ca.crt}"

if [ -z "$USERNAME" ]; then
  echo "Usage: $0 <username> [group] [cluster-name] [api-server] [ca-path]"
  exit 1
fi

echo "📋 Creating user certificate via Kubernetes CSR API..."
echo ""

# Step 1: Generate private key
echo "[1/5] Generating private key..."
openssl genrsa -out "${USERNAME}.key" 2048 2>/dev/null
chmod 600 "${USERNAME}.key"

# Step 2: Create CSR file
echo "[2/5] Creating certificate signing request..."
openssl req -new \
  -key "${USERNAME}.key" \
  -out "${USERNAME}.csr" \
  -subj "/CN=${USERNAME}/O=${GROUP}" 2>/dev/null

# Step 3: Submit CSR to Kubernetes
echo "[3/5] Submitting CSR to Kubernetes API..."
CSR_CONTENT=$(cat "${USERNAME}.csr" | base64 | tr -d '\n')

kubectl apply -f - <<EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: ${USERNAME}-csr
spec:
  request: $CSR_CONTENT
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 31536000
  usages:
  - client auth
EOF

# Step 4: Wait for approval (manual or automated)
echo "[4/5] CSR created. Waiting for approval..."
echo "      Admin needs to run: kubectl certificate approve ${USERNAME}-csr"

# Optional: auto-approve for testing
# kubectl certificate approve ${USERNAME}-csr

# Wait for approval (with timeout)
TIMEOUT=300
ELAPSED=0
while [ $ELAPSED -lt $TIMEOUT ]; do
  STATUS=$(kubectl get csr "${USERNAME}-csr" -o jsonpath='{.status.conditions[?(@.type=="Approved")].type}' 2>/dev/null || echo "")
  if [ "$STATUS" == "Approved" ]; then
    echo "      ✅ CSR Approved!"
    break
  fi
  sleep 5
  ELAPSED=$((ELAPSED + 5))
done

# Step 5: Extract certificate and configure kubeconfig
echo "[5/5] Extracting certificate and configuring kubeconfig..."
kubectl get csr "${USERNAME}-csr" -o jsonpath='{.status.certificate}' | base64 -d > "${USERNAME}.crt"

# Configure kubeconfig
kubectl config set-cluster "${CLUSTER_NAME}" \
  --server="${API_SERVER}" \
  --certificate-authority="${CA_PATH}"

kubectl config set-credentials "${USERNAME}" \
  --client-certificate="${USERNAME}.crt" \
  --client-key="${USERNAME}.key" \
  --embed-certs=true

kubectl config set-context "${USERNAME}-context" \
  --cluster="${CLUSTER_NAME}" \
  --user="${USERNAME}"

echo ""
echo "✅ User '${USERNAME}' created successfully!"
echo ""
echo "📌 Files created:"
echo "   - ${USERNAME}.key      (private key - KEEP SECURE)"
echo "   - ${USERNAME}.csr      (certificate signing request)"
echo "   - ${USERNAME}.crt      (signed certificate)"
echo ""
echo "📌 To use this user:"
echo "   kubectl config use-context ${USERNAME}-context"
echo "   kubectl get pods"
echo ""
echo "📌 To grant permissions:"
echo "   kubectl create rolebinding ${USERNAME}-view --clusterrole=view --user=${USERNAME}"

View and Manage CSRs

bash
# List all CSRs
kubectl get csr

# Show detailed CSR info
kubectl describe csr <csr-name>

# Show CSR in YAML
kubectl get csr <csr-name> -o yaml

# View the original CSR content
kubectl get csr <csr-name> -o jsonpath='{.spec.request}' | base64 -d | openssl req -text -noout

# Approve CSR
kubectl certificate approve <csr-name>

# Deny CSR
kubectl certificate deny <csr-name>

# Delete CSR
kubectl delete csr <csr-name>

# Watch for pending CSRs
kubectl get csr --watch

Available Signer Names

bash
# Different signerName values for different certificate types:

# 1. Client certificate for connecting to API server
signerName: kubernetes.io/kube-apiserver-client

# 2. Kubelet serving certificate (for kubelet HTTPS endpoint)
signerName: kubernetes.io/kubelet-serving

# 3. Legacy (kubeadm) client certificate
signerName: kubernetes.io/kube-apiserver-client-kubelet

# Check available signers in your cluster:
kubectl get certificatesigningrequests.certificates.k8s.io -o json | \
  jq '.items[].spec.signerName' | sort | uniq

CSR Best Practices for Kind Clusters

bash
# 1. For kind, approve CSRs immediately or auto-approve them
kubectl certificate approve <csr-name>

# 2. Create a helper function for approval in testing
auto-approve-csrs() {
  kubectl get csr --no-headers | awk '{print $1}' | while read csr; do
    if kubectl get csr "$csr" -o jsonpath='{.status.conditions}' | grep -q Approved; then
      continue
    fi
    echo "Approving: $csr"
    kubectl certificate approve "$csr"
  done
}

# 3. Watch for pending CSRs
watch 'kubectl get csr'

Part 8: Working with Kubeconfig - Examples

Example 1: Create Read-Only Viewer Account

bash
# Generate keys
openssl genrsa -out viewer.key 2048
openssl req -new -key viewer.key -out viewer.csr -subj "/CN=viewer/O=viewers"
openssl x509 -req -in viewer.csr -CA /etc/kubernetes/pki/ca.crt \
  -CAkey /etc/kubernetes/pki/ca.key -out viewer.crt -days 365

# Add to kubeconfig
kubectl config set-credentials viewer \
  --client-certificate=viewer.crt --client-key=viewer.key
kubectl config set-context viewer-context --cluster=kubernetes --user=viewer

# Create RBAC role binding
kubectl create rolebinding viewer-role --clusterrole=view --user=viewer

Example 2: Certificate Expiration Check

bash
# Check when certs expire
for cert in /etc/kubernetes/pki/*.crt; do
  echo "$cert:"
  openssl x509 -in "$cert" -noout -dates
done

# List certs expiring within 30 days
# (Useful for monitoring and renewal planning)

Example 3: Verify Certificate Trust Chain

bash
# Check if cert was signed by CA
openssl verify -CAfile /etc/kubernetes/pki/ca.crt cert.crt

# Output: cert.crt: OK (if valid)

Last Updated: January 9, 2026

Released under the MIT License.