Cheat Sheets / Kubernetes & Platform

Kubernetes Security & Hardening cheat sheet

102 commands from every lesson of Kubernetes Security & Hardening, on one page.

01 · Cluster PKI & certificates

Inspect certificates

sudo kubeadm certs check-expirationExpiry of every kubeadm-managed certificate
openssl x509 -in cert.crt -noout -subject -issuer -enddateWho, signed by whom, valid until
openssl x509 -in apiserver.crt -noout -ext subjectAltNameNames and IPs the API server cert is valid for
echo | openssl s_client -connect <host>:6443 2>/dev/null | openssl x509 -noout -datesCheck a live endpoint's certificate

Kubelet certificates

ls -l /var/lib/kubelet/pki/kubelet client/serving certs on a node
kubectl get csrCertificate signing requests (e.g. kubelet serving certs)
kubectl certificate approve <csr>Approve a pending CSR (after checking it!)

02 · cert-manager in production

Install & inspect

helm repo add jetstack https://charts.jetstack.ioAdd the cert-manager chart repository
helm install cert-manager jetstack/cert-manager -n cert-manager --create-namespace --set crds.enabled=trueInstall with CRDs (older charts: installCRDs=true)
kubectl get clusterissuers,issuers -AConfigured issuers and their readiness
kubectl get certificate -ACertificates, Ready status and secret names
kubectl describe certificate <name>Events: why it isn't issued yet
kubectl get certificaterequests,orders,challenges -AThe issuance pipeline (ACME)

03 · Authentication methods

Who am I?

kubectl auth whoamiUsername and groups the API server sees
kubectl config view --minifyThe user entry kubectl is using

Client certificate via the CSR API

openssl genrsa -out asha.key 2048A private key
openssl req -new -key asha.key -subj "/CN=asha/O=devops" -out asha.csrCN = username, O = group
kubectl certificate approve ashaApprove the CertificateSigningRequest
kubectl get csr asha -o jsonpath='{.status.certificate}' | base64 -d > asha.crtFetch the signed certificate

ServiceAccount tokens

kubectl create token app -n shop --duration=1hA short-lived token for a ServiceAccount
cat /var/run/secrets/kubernetes.io/serviceaccount/tokenThe projected token inside a pod

04 · OIDC login for kubectl

API server (kube-apiserver flags)

--oidc-issuer-url=https://sso.example.com/realms/platformWho issues the tokens (must be HTTPS)
--oidc-client-id=kubernetesThe audience (client) tokens must be issued for
--oidc-username-claim=email --oidc-username-prefix=oidc:Which claim becomes the username (with a prefix)
--oidc-groups-claim=groups --oidc-groups-prefix=oidc:Which claim holds group membership

kubectl side (kubelogin)

kubectl krew install oidc-loginInstall kubelogin as a kubectl plugin
kubectl oidc-login setup --oidc-issuer-url=… --oidc-client-id=kubernetesTest the login and print the claims
kubectl auth whoamiConfirm username and groups

05 · SSO, federation & MFA

Design checklist

One source of identityEnterprise IdP (Entra ID, Okta, Google…) for every cluster
Broker when neededKeycloak/Dex/Pinniped federate the IdP to many clusters
MFA at the IdPKubernetes never sees passwords or second factors
Short tokensMinutes, refreshed by the IdP; faster offboarding
Break-glassOffline, sealed, monitored credentials: rotated after every use

Useful commands

kubectl auth whoamiConfirm who you're logged in as
sudo kubeadm kubeconfig user --client-name=breakglass-2026q3 --org=kubeadm:cluster-adminsGenerate a separate emergency admin kubeconfig (kubeadm)

06 · RBAC design at scale

Review access

kubectl auth can-i --list --as=oidc:asha@example.com --as-group=oidc:developers -n shopEverything a user+group may do in a namespace
kubectl get clusterrolebindings -o wideCluster-wide grants and their subjects
kubectl who-can get secrets -n shopWho can read secrets (kubectl-who-can plugin)
kubectl get clusterroles -l rbac.authorization.k8s.io/aggregate-to-edit=trueRoles aggregated into 'edit'

Dangerous verbs & resources

secrets: get/list/watchRead every credential in scope
pods: create (any)Run as any ServiceAccount in that namespace, mount its Secrets
bind / escalate on rolesGrant yourself more than you have
impersonateAct as another user or group
nodes/proxy, pods/execReach into nodes or containers

07 · Ingress controllers & TLS

Inspect

kubectl get ingressclassInstalled controllers (and the default)
kubectl get ingress -AHosts, addresses and TLS per Ingress
kubectl describe ingress <name>Rules, backends and events

Test TLS

curl -vk --resolve shop.example.com:443:<LB-IP> https://shop.example.com/Test a host before DNS points to it
openssl s_client -connect <LB-IP>:443 -servername shop.example.com </dev/null | openssl x509 -noout -subject -datesWhich certificate is served for this name (SNI)

08 · Gateway API

Objects

GatewayClassWhich implementation (like IngressClass): owned by the infrastructure provider
GatewayListeners (ports, protocols, hostnames, TLS): owned by the platform team
HTTPRouteRouting rules for an app: owned by the app team
ReferenceGrantAllows a reference into another namespace (e.g. a Route to a Service)

Inspect

kubectl get gatewayclass,gateway -AImplementations and gateways (with addresses)
kubectl get httproute -ARoutes and their parent gateways
kubectl describe httproute <name>status.parents: Accepted / ResolvedRefs conditions

09 · Network policies & mTLS

Policy building blocks

podSelector: {}All pods in the namespace
policyTypes: ["Ingress", "Egress"]Which directions this policy restricts
namespaceSelector: {matchLabels: {kubernetes.io/metadata.name: shop}}Pods in a specific namespace (label set automatically)
ipBlock: {cidr: 10.0.0.0/8}Traffic to/from IP ranges (outside the cluster)

Test

kubectl -n shop exec deploy/web -- wget -qO- -T 3 http://api:8080Allowed? (timeout = blocked)
kubectl get networkpolicy -AWhich namespaces are isolated

10 · Pod Security & admission control

Pod Security Admission (namespace labels)

kubectl label ns shop pod-security.kubernetes.io/enforce=restrictedReject non-compliant pods
kubectl label ns shop pod-security.kubernetes.io/warn=restrictedWarn clients but allow
kubectl label ns shop pod-security.kubernetes.io/audit=restrictedRecord violations in the audit log
kubectl label --dry-run=server --overwrite ns shop pod-security.kubernetes.io/enforce=restrictedPreview which existing pods would violate

Custom policy

kubectl get validatingadmissionpoliciesBuilt-in CEL policies
kubectl get clusterpoliciesKyverno policies
kubectl get constrainttemplates,constraintsGatekeeper policies

11 · Secrets management

Encryption at rest

--encryption-provider-config=/etc/kubernetes/enc/enc.yamlkube-apiserver flag pointing at the EncryptionConfiguration
etcdctl … get /registry/secrets/<ns>/<name> | hexdump -C | headCheck the raw value is encrypted (k8s:enc:… prefix)
kubectl get secrets -A -o json | kubectl replace -f -Rewrite all Secrets so they're re-encrypted with the current key

Getting secrets into the cluster

kubectl get externalsecrets -AExternal Secrets Operator: sync status
kubeseal --format yaml < secret.yaml > sealed.yamlSealed Secrets: encrypt for Git
vault kv get secret/shop/dbRead a secret from Vault (CLI)

12 · Supply chain security

Inspect images

syft registry.example.com/shop/api:1.4.2 -o spdx-json > sbom.jsonGenerate an SBOM
trivy image --severity HIGH,CRITICAL registry.example.com/shop/api:1.4.2Scan for known vulnerabilities
trivy sbom sbom.jsonScan an existing SBOM
crane digest registry.example.com/shop/api:1.4.2The immutable digest behind a tag

Sign & verify (cosign)

cosign generate-key-pairCreate cosign.key / cosign.pub (or use keyless signing)
cosign sign --key cosign.key <image>@sha256:<digest>Sign an image by digest
cosign verify --key cosign.pub <image>@sha256:<digest>Verify the signature
cosign attest --key cosign.key --type spdxjson --predicate sbom.json <image>@sha256:<digest>Attach a signed SBOM attestation

13 · Audit logging & runtime detection

API audit (kube-apiserver flags)

--audit-policy-file=/etc/kubernetes/audit/policy.yamlWhich events to record, at which level
--audit-log-path=/var/log/kubernetes/audit/audit.logWhere to write (or use a webhook backend)
--audit-log-maxage=30 --audit-log-maxbackup=10 --audit-log-maxsize=200Rotation: days, files, MB
jq 'select(.objectRef.resource=="secrets") | {user: .user.username, verb, ns: .objectRef.namespace}' audit.logWho touched Secrets

Falco

helm repo add falcosecurity https://falcosecurity.github.io/chartsChart repository
helm install falco falcosecurity/falco -n falco --create-namespaceInstall Falco
kubectl -n falco logs -l app.kubernetes.io/name=falco -fWatch alerts

14 · CIS benchmark hardening

Run kube-bench

kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yamlRun kube-bench as a Job on a node
kubectl logs job/kube-benchRead the report
kube-bench run --targets nodeRun only node checks (binary on a node)

Kubelet settings to check (KubeletConfiguration)

authentication.anonymous.enabled: falseNo anonymous kubelet API access
authorization.mode: WebhookKubelet asks the API server who may do what
readOnlyPort: 0Disable the unauthenticated read-only port
protectKernelDefaults: trueFail rather than silently changing kernel settings
rotateCertificates: trueRotate the kubelet client certificate

15 · Capstone: hardened cluster from scratch

Verification commands

kubectl auth can-i --list --as=system:serviceaccount:shop:default -n shopWhat the default ServiceAccount may do (should be nothing useful)
kubectl run test --image=nginx:1.27 -n shopShould be rejected under restricted PSA
kubectl -n shop exec deploy/web -- wget -qO- -T 3 http://api.payments:8080Cross-namespace call (should time out)
kubectl logs job/kube-benchBenchmark result