Get started

OpenSourceOM Team ·

KSPM Explained: Kubernetes Security Posture Beyond CIS YAML

KSPM beyond CIS YAML: cluster config versus workload identity, connecting findings to cloud IAM, and where admission control differs from scans.

  • KSPM
  • Kubernetes
  • CIS benchmark
  • cloud IAM
  • security posture

KSPM (Kubernetes Security Posture Management) is posture for the cluster and the workloads on it: API-server flags, node/kubelet settings, RBAC, privileged pods, and—if you are doing it honestly—the cloud identity those pods mint. It is not “we ran the CIS YAML” and not a policy-engine how-to. In-cluster authorization is Kubernetes RBAC. The IRSA/WI hop to cloud admin is pod to cloud admin. This page is what KSPM is allowed to claim, and how OpenSourceOM should connect a CIS-shaped finding to a graph hop—or refuse to.

KSPM scan surfaces
  ├─ Cluster config     API flags, etcd, kubelet, PSA mode     (CIS-ish)
  ├─ Workload posture   privileged, hostNetwork, wild RBAC
  └─ Cloud binding      IRSA / WI / node instance profile      (not in CIS)

Only the rows that are hops belong on an attack path

Cluster config vs workload identity

Cluster config is the control plane and the nodes: --anonymous-auth, --authorization-mode, encryption at rest for secrets, kubelet anonymous, Pod Security Admission enforce mode, whether the API server is on a public NLB.

Workload identity is who the process is: Kubernetes SA, projected token, cloud role. CIS barely touches it. kube-bench will not fail a deployment because eks.amazonaws.com/role-arn points at AdministratorAccess.

Layer Example finding Path-relevant?
Cluster config Anonymous auth enabled Yes if Internet --REACHABLE--> API
Cluster config kubelet cert file 644 Rarely a hop; hygiene
Workload privileged: true + hostPID Yes if it yields node credentials
Workload cluster-admin on deploy SA Yes for Kubernetes API; not automatically cloud admin
Cloud binding IRSA to admin role Yes — often the highest hop
Cloud binding Node instance profile s3:* Yes for every pod that can reach IMDS

OpenSourceOM node split: Workload (control plane vs app pod), Identity (K8s SA vs cloud role). Mixing them into one “cluster CI” is how KSPM dashboards show 2,000 CIS fails and hide the one IRSA admin.

Failure mode: buying a “KSPM module” that is kube-bench XML plus a logo. You automated CIS. You did not do identity.

CIS is necessary and insufficient

Run CIS (kube-bench, or the managed equivalent in Defender/GKE security posture). It catches:

  • Anonymous requests to the API
  • AlwaysAllow authorization
  • Insecure kubelet flags
  • Missing file permissions on control-plane hosts (self-managed)

It does not catch:

  • StringLike IRSA sub *:*
  • Azure federated credential subject system:serviceaccount:*:*
  • GKE node SA roles/editor
  • A NetworkPolicy-less cluster with a public LoadBalancer to a debug pod
  • Secrets list in a Role that CIS never reads

Treat CIS as necessary hygiene on self-managed and as baseline on EKS/GKE/AKS (many controls are already the vendor’s problem). Do not use CIS score as reachable risk. Reachable risk needs REACHABLE and CAN_ASSUME, which CIS does not compute.

# CIS (control plane) — keep doing this
kube-bench run --targets master,node,policies

# Not CIS — still KSPM if you are honest
kubectl get sa -A -o json | jq '.items[] | select(.metadata.annotations["eks.amazonaws.com/role-arn"]!=null) | [.metadata.namespace,.metadata.name,.metadata.annotations["eks.amazonaws.com/role-arn"]]'
kubectl-who-can get secrets --all-namespaces

Failure mode: exempting managed node groups from CIS because “AWS owns the master,” then never listing IRSA annotations. You exempted the right CIS controls and skipped the real KSPM.

Connecting KSPM findings to cloud IAM

The join OpenSourceOM must make:

Pod / SA  --ASSUMES-->  cloud Identity  --CAN_ACCESS-->  Datastore | iam:*

         KSPM finding (privileged, hostNetwork, SA automount)
         only raises rank if this join exists or if Kubernetes API is the jewel

Privileged + hostNetwork matters when the pod can hit IMDS/WI and the node role is wide, or when it can take over the node and read projected tokens of other pods. If the node role is AmazonEKSWorkerNodePolicy plus ECR pull and IRSA is scoped, privileged is still bad (kernel) but not “cloud admin” until you prove the extra hop.

Public LoadBalancer + empty RBAC matters when the Service fronts a debug image with a cloud annotation.

CIS anonymous-auth matters when the API is REACHABLE from Internet (or from the VPN you treat as hostile). If the API is private-only and wrapped in IAP, the CIS fail is still real and still not the same ticket as IRSA admin.

Collector requirement: Kubernetes API and the cloud account that owns IRSA/WI/node roles. YAML-in-Git KSPM cannot see the node instance profile. Cloud-only CSPM cannot see the annotation until a K8s collector exists.

Failure mode: creating a Jira “fix CIS 5.2.1” for a privileged pod in a namespace whose SA has no cloud role and no hostPath, while ignoring the unprivileged API pod with AdministratorAccess. Severity came from the CIS id, not from the join.

Admission vs posture scans

Admission (PSA, Kyverno, Gatekeeper, ValidatingAdmissionPolicy) Posture scan (KSPM)
When Create/update/delete of a Kubernetes object Periodically, on live objects and/or rendered manifests
Sees The request (and sometimes dry-run) What actually runs, plus drift
Sees cloud IAM No Only if the scanner has a cloud collector
Good at Stopping the next privileged pod Finding the privileged pod someone kubectl apply’d at 2 a.m.
Bad at History; objects that bypassed (break-glass, excluded ns) Stopping the next apply unless you also have admission

You want both. Admission without scans: yesterday’s break-glass Namespace stays privileged forever. Scans without admission: you discover the same privileged Helm chart every Monday. Neither replaces cloud IAM review.

OpenSourceOM is a posture + path system, not an admission controller. Do not expect the graph to block a deploy. Expect it to rank the privileged pod that already exists if it sits on a walk. Wire admission in the platform cluster; wire collectors to OpenSourceOM.

This is also why a Gatekeeper constraint library is not KSPM. Constraints are policies at the gate. KSPM is the audit of state, including state the gate never saw.

Failure mode: enabling PSA enforce: baseline and turning off live KSPM “because admission covers it.” PSA does not know IRSA. PSA does not scan cloud roles. PSA does not see a public NLB Terraform that never touches a Pod spec.

Checklist

  • CIS/kube-bench (or managed equivalent) still runs; score is not the rank
  • IRSA/WI/node roles listed and joined to SAs; cloud admin on a pod is a path ticket
  • Privileged/hostPath findings ranked using IMDS/node-role/IRSA hops, not CIS id alone
  • Collectors: Kubernetes API + cloud account (YAML-only is insufficient)
  • Admission enabled for privileged/hostPath and live scan for break-glass drift
  • Anonymous API + internet REACHABLE is a path; kubelet file perms are hygiene
  • RBAC who-can on secrets is in CI (RBAC post); not confused with KSPM CIS XML

Related: Kubernetes RBAC security · Cloud-native application security · Pod to cloud admin