Safeguard
Infrastructure Security

Securing managed Kubernetes clusters with IaC scanning

IaC scanning catches Kubernetes RBAC, network, and IAM misconfigurations in Terraform and Helm before they ever reach EKS, GKE, or AKS clusters.

Michael
Cloud Security Architect
7 min read

On December 3, 2018, Kubernetes disclosed CVE-2018-1002105, a CVSS 9.8 privilege escalation flaw in the API server proxy that let anyone with basic network access to a cluster send arbitrary requests to backend services as a fully privileged user. The bug lived in the control plane, but the real-world exposure was almost always compounded by something an IaC scanner would have caught weeks earlier: a Terraform module that left the API server publicly reachable, or a Helm chart that granted a service account cluster-admin by default. Managed Kubernetes services — Amazon EKS, Google GKE, Azure AKS — outsource control-plane patching and etcd security to the cloud provider, but every RBAC binding, network policy, node group IAM role, and admission controller config still ships as code the customer writes. That code is where the actual attack surface for managed clusters gets defined, and it's exactly what IaC scanning is built to check before it ever reaches a live cluster.

What is IaC scanning for Kubernetes, and why does it matter on managed clusters?

IaC scanning is static analysis of the Terraform, CloudFormation, Helm charts, Kustomize overlays, and raw manifests that define a cluster and its workloads, run against policy rules before terraform apply or kubectl apply ever executes. It matters specifically on managed clusters because AWS, Google, and Microsoft draw a hard line in their shared-responsibility documentation: the provider secures the control plane, hypervisor, and etcd storage, while the customer owns RBAC, network policy, secrets management, IAM-to-Kubernetes role mapping, and workload configuration. On EKS, control plane API audit logging is not enabled by default — a customer has to turn it on explicitly in the cluster's Terraform or eksctl config, and plenty of clusters run for years without it. On GKE Standard (as opposed to Autopilot), Workload Identity and network policy enforcement are opt-in settings buried in the same google_container_cluster resource block that provisions the cluster. None of that is control-plane risk. All of it is IaC risk, checkable at commit time.

Which Kubernetes misconfigurations does IaC scanning actually catch before deployment?

IaC scanning reliably catches six categories: privileged containers, missing resource limits, hostPath volume mounts, wildcard RBAC rules, default service-account token automounting, and publicly exposed dashboards or API endpoints — all of which map directly to controls in the CIS Kubernetes Benchmark (currently at v1.9). A Deployment manifest with securityContext: { privileged: true } or no runAsNonRoot constraint is a one-line static check, not a runtime investigation. A ClusterRole with resources: ["*"] and verbs: ["*"] is grep-able in a Helm template before it's ever templated out and applied. CVE-2021-25741, disclosed in Kubernetes 1.20-1.22 in June 2021, let a malicious subPath symlink in a pod spec redirect writes to arbitrary host paths — a scanner checking for unconstrained subPath usage in volume mounts would flag the pattern regardless of whether that specific CVE existed, because the underlying manifest shape is the same class of risk. This is the core value of shifting checks into IaC: the vulnerable pattern gets caught once, in source control, instead of once per cluster, in production.

How did the Tesla cryptojacking incident start, and what would an IaC scan have stopped?

It started with an unauthenticated Kubernetes dashboard, publicly reachable on the internet, that RedLock researchers discovered in February 2018 inside a Tesla-owned AWS environment. Attackers reached the dashboard without credentials, pulled AWS access keys from a pod's environment variables, and used that access to run cryptocurrency mining jobs on Tesla's compute at the company's expense — no exploit of Kubernetes itself was required, just a control plane component exposed with no authentication in front of it. An IaC scan checking the load balancer or ingress configuration for the dashboard Service, combined with a rule flagging --anonymous-auth=true or missing authentication on any Kubernetes management interface, would have caught the exposure in the Terraform or manifest that provisioned it, before the Service object ever had a public IP attached. The lesson generalizes past this one incident: dashboards, etcd, and kubelet read-only ports are the management-plane components attackers scan for first, and every one of them is defined in code before it's ever exposed in production.

What's different about scanning managed Kubernetes versus self-managed clusters?

The difference is that managed clusters add a cloud-IAM-to-Kubernetes-RBAC mapping layer that self-managed clusters don't have, and that layer uses provider-specific syntax an IaC scanner has to understand to catch misconfigurations in it. On EKS, that mapping lives in the aws-auth ConfigMap (or the newer AccessEntry API introduced in 2023), which binds IAM roles to Kubernetes groups — a single overly broad entry mapping an IAM role assumable by any EC2 instance to system:masters effectively hands cluster-admin to anything running in the VPC. On GKE, the equivalent is Workload Identity Federation, where a misconfigured iam.gke.io/gcp-service-account annotation on a Kubernetes ServiceAccount can let a compromised pod assume a GCP service account with project-level permissions. On AKS, it's Azure AD Workload Identity and pod-managed identity bindings, which prior to Azure AD Pod Identity's 2023 deprecation in favor of Workload Identity, had documented CVEs around IMDS access from any pod on a node. An IaC scanner tuned only to generic Kubernetes RBAC will miss all three of these; it has to parse the Terraform aws_eks_access_entry, google_service_account_iam_member, or azurerm_kubernetes_cluster blocks that create the binding in the first place.

Which IaC formats should a Kubernetes security program actually scan?

A Kubernetes security program needs to scan five distinct surfaces, not one: the Terraform or OpenTofu that provisions the cluster and node groups, the Helm charts that template workloads, the Kustomize overlays that patch them per environment, the raw YAML manifests applied directly via kubectl or GitOps controllers like Argo CD and Flux, and the CI/CD pipeline definitions (GitHub Actions, GitLab CI, Jenkinsfiles) that string all of it together and often hold the credentials used to apply it. A team that scans only its Terraform will miss a Helm chart's values.yaml setting automountServiceAccountToken: true by default across every pod in a namespace. A team that scans only Kubernetes YAML will miss a Terraform node group definition that attaches an overly permissive instance profile to every worker node in the cluster, which then becomes reachable to any pod without a network policy blocking node metadata access. Treating IaC scanning as a single-format checkbox — Terraform only, or Kubernetes YAML only — is the most common gap security teams have when they say they've "done" IaC scanning for their Kubernetes environment.

How Safeguard Helps

Safeguard scans Terraform, Helm, Kustomize, and raw Kubernetes manifests as part of the same pipeline that generates and ingests SBOMs for the container images those manifests deploy, so a misconfigured RBAC binding and a vulnerable base image show up as one connected risk instead of two disconnected findings. Reachability analysis then filters that combined signal against what's actually running in the cluster and what code paths are exercised at runtime, so a wildcard ClusterRole attached to a pod nobody calls doesn't compete for attention with one that's internet-facing. Griffin AI triages the findings against exploitability and blast radius — including the IAM-to-RBAC mapping specific to EKS, GKE, or AKS — and ranks them accordingly. For the fixable subset, Safeguard opens auto-fix pull requests directly against the Terraform module or Helm chart, with the corrected securityContext, scoped RBAC rule, or tightened aws-auth entry already in the diff, so engineers are reviewing a fix instead of writing one from scratch.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.