Security review procedure for Infrastructure-as-Code configurations including Terraform, Kubernetes manifests, and AWS CloudFormation templates.
.tf, .tofu files (Terraform/OpenTofu)tfsec, checkov, trivy config, kube-linter, cfn-nag for automated scanningEstablish:
Run available scanners first to catch low-hanging fruit:
# Terraform
tfsec . # Static analysis for Terraform
checkov -d . # Policy-as-code scanning
trivy config . # Misconfiguration scanning
# Kubernetes
kube-linter lint . # Kubernetes manifest linting
trivy config . # Misconfiguration scanning
kubesec scan manifest.yaml # Security risk scoring
# CloudFormation
cfn-lint template.yaml # CloudFormation linting
cfn_nag_scan --input-path . # Security-focused scanning
checkov -d . # Policy-as-code scanning
Review each domain systematically. Reference the corresponding prompt data file for the detected IaC type:
data/secure-code-prompts/terraform.mddata/secure-code-prompts/kubernetes.mddata/secure-code-prompts/cloudformation.md| Check | Terraform | Kubernetes | CloudFormation |
|---|---|---|---|
| Least privilege | aws_iam_policy wildcards |
RBAC ClusterRole wildcards | AWS::IAM::Policy wildcards |
| No hardcoded creds | Variables, provider blocks | ServiceAccount tokens | Parameters, UserData |
| Role scoping | Trust relationships | Namespace-scoped roles | AssumeRolePolicyDocument |
| Separation of duties | Separate roles per function | Separate ServiceAccounts | Separate IAM roles |
| Check | Terraform | Kubernetes | CloudFormation |
|---|---|---|---|
| No plaintext secrets | sensitive = true, no defaults |
No secrets in manifests | No secrets in Parameters |
| External secret store | Vault provider, AWS SM data source | External Secrets Operator | Secrets Manager references |
| No secrets in state | Remote encrypted state | No ConfigMaps for secrets | No secrets in Outputs |
| Check | Terraform | Kubernetes | CloudFormation |
|---|---|---|---|
| No open ingress | Security group 0.0.0.0/0 |
NetworkPolicy exists | SecurityGroup 0.0.0.0/0 |
| Restricted ports | SSH/RDP not world-open | Services not NodePort/LB unnecessarily | No unrestricted SSH/RDP |
| Private networking | Private subnets for sensitive resources | Internal ClusterIP default | VPC private subnets |
| Segmentation | Separate VPCs/subnets | NetworkPolicies per namespace | Network ACLs |
| Check | Terraform | Kubernetes | CloudFormation |
|---|---|---|---|
| At rest | encrypted = true on storage |
etcd encryption, PV encryption | StorageEncrypted: true |
| In transit | TLS on load balancers | TLS on Ingress, mTLS between services | HTTPS listeners |
| Key management | KMS key references | Secrets encryption config | KMS key references |
| Check | Terraform | Kubernetes | CloudFormation |
|---|---|---|---|
| No public access | S3 block_public_access |
PV access modes | S3 PublicAccessBlockConfiguration |
| Versioning | versioning { enabled = true } |
N/A | VersioningConfiguration |
| Backup | Lifecycle rules, snapshots | PV reclaim policies | Backup retention |
| Check | Terraform | Kubernetes | CloudFormation |
|---|---|---|---|
| Audit logging | CloudTrail, Flow Logs enabled | Audit policy configured | CloudTrail resource exists |
| Access logging | S3 access logs, ALB logs | Pod logging to aggregator | S3/ALB access logging |
| Alerting | CloudWatch alarms | Prometheus/alerting rules | CloudWatch Alarms |
Check for databases, admin interfaces, message queues, or internal APIs exposed to the public internet. Recommend private networking and access restrictions.
| Check | Terraform | Kubernetes | CloudFormation |
|---|---|---|---|
| Pinned versions | Provider/module version constraints | Image tags (not latest) |
Template version tracking |
| Trusted sources | Terraform Registry, verified modules | Trusted registries only | Verified nested stacks |
| Integrity | Module hashes in lockfile | Image digest pinning | Template validation |
Terraform:
sensitive = true on all secret variablesKubernetes:
privileged: true containers → almost never neededrunAsNonRoot: true and allowPrivilegeEscalation: falseCloudFormation:
For each finding, use the standard output format:
### [SEVERITY] Title
- **Resource**: resource type and identifier
- **Issue**: Description of the misconfiguration
- **Impact**: What an attacker can achieve
- **Recommendation**: How to fix it
- **Example Fix**: Corrected IaC code snippet
Provide:
| Benchmark | Applies To |
|---|---|
| CIS AWS Foundations | Terraform (AWS), CloudFormation |
| CIS Azure Foundations | Terraform (Azure) |
| CIS GCP Foundations | Terraform (GCP) |
| CIS Kubernetes | Kubernetes manifests |
| NSA/CISA K8s Hardening | Kubernetes clusters |
| AWS Well-Architected (Security) | CloudFormation, Terraform (AWS) |
| Pod Security Standards | Kubernetes pods |