Skip to content

kubectl Security Commands Cheatsheet

Quick reference for all security-related kubectl commands you will need during the CKS exam. Commands are organized by category for rapid lookup.

Alias Reminder

Always set up your alias first: alias k=kubectl

All examples below use k instead of kubectl.


RBAC Investigation

Checking Permissions

bash
# Check if a user/SA can perform an action
k auth can-i create deployments --as=system:serviceaccount:dev:mysa -n dev

# Check all permissions for a ServiceAccount
k auth can-i --list --as=system:serviceaccount:dev:mysa -n dev

# Check permissions for a user
k auth can-i --list --as=john -n production

# Check if current user can do something
k auth can-i delete pods -n kube-system

Viewing RBAC Resources

bash
# List all roles and clusterroles
k get roles -A
k get clusterroles

# List all bindings
k get rolebindings -A
k get clusterrolebindings

# Describe a specific role (see verbs and resources)
k describe role <role-name> -n <namespace>
k describe clusterrole <clusterrole-name>

# Describe a binding (see subjects and roleRef)
k describe rolebinding <binding-name> -n <namespace>
k describe clusterrolebinding <binding-name>

Finding Dangerous RBAC

bash
# Find all ClusterRoleBindings to cluster-admin
k get clusterrolebindings -o json | jq -r '
  .items[] | select(.roleRef.name=="cluster-admin") |
  .metadata.name'

# Find roles with wildcard permissions
k get clusterroles -o json | jq -r '
  .items[] | select(.rules[]?.resources[]? == "*") |
  .metadata.name'

# Find roles with secrets access
k get clusterroles -o json | jq -r '
  .items[] | select(.rules[]?.resources[]? == "secrets") |
  .metadata.name'

# Find roles that can exec into pods
k get clusterroles -o json | jq -r '
  .items[] | select(.rules[]?.resources[]? == "pods/exec") |
  .metadata.name'

Creating RBAC Resources

bash
# Create a role (imperative)
k create role pod-reader \
  --verb=get,list,watch \
  --resource=pods \
  -n dev

# Create a clusterrole
k create clusterrole secret-reader \
  --verb=get,list \
  --resource=secrets

# Create a rolebinding
k create rolebinding pod-reader-binding \
  --role=pod-reader \
  --serviceaccount=dev:mysa \
  -n dev

# Create a clusterrolebinding
k create clusterrolebinding secret-reader-binding \
  --clusterrole=secret-reader \
  --serviceaccount=dev:mysa

# Bind to a user
k create rolebinding admin-binding \
  --clusterrole=admin \
  --user=john \
  -n dev

ServiceAccount Commands

bash
# Create a ServiceAccount
k create serviceaccount mysa -n dev

# Create a time-bound token (1 hour)
k create token mysa -n dev --duration=1h

# Patch SA to disable automount
k patch sa default -n dev \
  -p '{"automountServiceAccountToken": false}'

# Set SA on a deployment
k set serviceaccount deployment/myapp mysa -n dev

# Check which SA a pod uses
k get pod <pod> -n <ns> -o jsonpath='{.spec.serviceAccountName}'

# Check if token is mounted
k get pod <pod> -n <ns> -o jsonpath='{.spec.volumes[?(@.name=="kube-api-access-*")]}'

Secret Management

bash
# Create a secret
k create secret generic db-creds \
  --from-literal=username=admin \
  --from-literal=password='S3cur3!' \
  -n finance

# Create TLS secret
k create secret tls my-tls \
  --cert=tls.crt \
  --key=tls.key \
  -n web

# View secret (base64 encoded)
k get secret db-creds -n finance -o yaml

# Decode a secret value
k get secret db-creds -n finance \
  -o jsonpath='{.data.password}' | base64 -d

# List all secrets in all namespaces
k get secrets -A

# Check if secrets are encrypted at rest
# (must SSH to control plane)
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep encryption-provider-config

Network Policy Commands

bash
# List network policies
k get networkpolicies -A
k get netpol -A  # short form

# Describe a network policy
k describe netpol <name> -n <namespace>

# Create a default deny ingress (imperative is not supported -- use YAML)
cat <<EOF | k apply -f -
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: NAMESPACE
spec:
  podSelector: {}
  policyTypes:
  - Ingress
EOF

# Test network connectivity between pods
k exec <pod> -n <ns> -- wget -qO- --timeout=2 http://<target-ip>:<port>
k exec <pod> -n <ns> -- nc -zv <target-ip> <port> -w 2
k exec <pod> -n <ns> -- curl -s --connect-timeout 2 http://<target-ip>:<port>

# Check which policies affect a pod
k get netpol -n <ns> -o json | jq -r '
  .items[] | select(.spec.podSelector.matchLabels | to_entries | 
  all(.key as $k | .value as $v | true)) | .metadata.name'

Pod Security Investigation

bash
# Check pod security context
k get pod <pod> -n <ns> -o jsonpath='{.spec.securityContext}'
k get pod <pod> -n <ns> -o jsonpath='{.spec.containers[0].securityContext}'

# Check if pod is running as root
k get pod <pod> -n <ns> -o jsonpath='{.spec.containers[0].securityContext.runAsUser}'

# Check capabilities
k get pod <pod> -n <ns> -o jsonpath='{.spec.containers[0].securityContext.capabilities}'

# Find all privileged pods
k get pods -A -o json | jq -r '
  .items[] |
  select(.spec.containers[].securityContext.privileged == true) |
  "\(.metadata.namespace)/\(.metadata.name)"'

# Find pods without readOnlyRootFilesystem
k get pods -A -o json | jq -r '
  .items[] |
  .metadata.namespace as $ns | .metadata.name as $pod |
  .spec.containers[] |
  select(.securityContext.readOnlyRootFilesystem != true) |
  "\($ns)/\($pod)/\(.name)"'

# Find pods running as root (UID 0)
k get pods -A -o json | jq -r '
  .items[] |
  select(.spec.containers[].securityContext.runAsUser == 0 or
         .spec.securityContext.runAsUser == 0) |
  "\(.metadata.namespace)/\(.metadata.name)"'

# Check Pod Security Admission labels on a namespace
k get ns <namespace> --show-labels | grep pod-security
k get ns <namespace> -o jsonpath='{.metadata.labels}' | jq .

Pod Security Admission Labels

bash
# Apply Pod Security Standard labels
k label ns <namespace> \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/warn-version=latest \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/audit-version=latest

# Dry-run to check which pods would be rejected
k label --dry-run=server --overwrite ns <namespace> \
  pod-security.kubernetes.io/enforce=restricted

Certificate Commands

bash
# Check certificate expiration (kubeadm clusters)
sudo kubeadm certs check-expiration

# Renew all certificates
sudo kubeadm certs renew all

# Renew a specific certificate
sudo kubeadm certs renew apiserver

# Inspect a certificate with openssl
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text

# Check certificate expiry date
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -enddate

# Check certificate SANs
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | \
  grep -A1 "Subject Alternative Name"

# Check certificate issuer
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -issuer

# Verify certificate against CA
openssl verify -CAfile /etc/kubernetes/pki/ca.crt \
  /etc/kubernetes/pki/apiserver.crt

# Check etcd certificates
openssl x509 -in /etc/kubernetes/pki/etcd/server.crt -noout -enddate

Image and Container Investigation

bash
# Check what image a pod is using
k get pod <pod> -n <ns> -o jsonpath='{.spec.containers[*].image}'

# Check all images in a namespace
k get pods -n <ns> -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'

# Check all images cluster-wide
k get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'

# Update an image
k set image deployment/<name> <container>=<new-image> -n <ns>

# Check container runtime on a node
k get nodes -o jsonpath='{.items[*].status.nodeInfo.containerRuntimeVersion}'

Audit and Logging

bash
# Check if audit logging is enabled
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep audit

# View audit logs
tail -f /var/log/kubernetes/audit/audit.log | jq .

# Filter audit logs for secrets access
cat /var/log/kubernetes/audit/audit.log | \
  jq 'select(.objectRef.resource == "secrets")'

# Filter for specific user
cat /var/log/kubernetes/audit/audit.log | \
  jq 'select(.user.username == "john")'

# Filter for specific verb
cat /var/log/kubernetes/audit/audit.log | \
  jq 'select(.verb == "delete")'

# Count events by user
cat /var/log/kubernetes/audit/audit.log | \
  jq -r '.user.username' | sort | uniq -c | sort -rn

Quick Debugging

bash
# Check pod events
k describe pod <pod> -n <ns> | tail -20

# Check pod logs
k logs <pod> -n <ns>
k logs <pod> -n <ns> -c <container>  # specific container
k logs <pod> -n <ns> --previous       # previous instance

# Check node conditions
k describe node <node> | grep -A5 Conditions

# Check API server status (on control plane)
crictl ps | grep kube-apiserver
crictl logs <container-id> 2>&1 | tail -20

# Check static pod manifests
ls /etc/kubernetes/manifests/

# Dry-run to validate YAML
k apply -f manifest.yaml --dry-run=server
k apply -f manifest.yaml --dry-run=client

# Generate YAML without applying
k run test --image=nginx $do > pod.yaml
k create deployment test --image=nginx $do > deploy.yaml

Quick Reference Table

TaskCommand
Switch contextk config use-context <name>
Current contextk config current-context
Check permissionk auth can-i <verb> <resource> --as=<user> -n <ns>
Create SAk create sa <name> -n <ns>
Create SA tokenk create token <sa> -n <ns> --duration=1h
Create rolek create role <name> --verb=get --resource=pods -n <ns>
Create bindingk create rolebinding <name> --role=<role> --sa=<ns>:<sa> -n <ns>
Create secretk create secret generic <name> --from-literal=key=val -n <ns>
Decode secretk get secret <name> -n <ns> -o jsonpath='{.data.key}' | base64 -d
Get pod imagek get pod <pod> -n <ns> -o jsonpath='{.spec.containers[0].image}'
Update imagek set image deploy/<name> <container>=<image> -n <ns>
Dry-run YAMLk run <name> --image=<img> --dry-run=client -o yaml
Force deletek delete pod <name> -n <ns> --force --grace-period=0
Label namespacek label ns <ns> key=value

Released under the MIT License.