Controls – Security (WAF-SEC)
- Controls Overview
- WAF-SEC-010 – Identity & Access Management Baseline
- WAF-SEC-020 – Least Privilege & RBAC Enforcement
- WAF-SEC-030 – Encryption at Rest with CMK
- WAF-SEC-040 – Encryption in Transit – TLS Enforcement
- WAF-SEC-050 – Network Segmentation & Security Group Hardening
- WAF-SEC-060 – Secrets Management – No Hardcoded Credentials
- WAF-SEC-070 – Vulnerability & Patch Management
- WAF-SEC-080 – Security Monitoring & Threat Detection
- WAF-SEC-090 – Policy-as-Code & Compliance Automation
- WAF-SEC-100 – Incident Response Readiness
- WAF-SEC-110 – Supply Chain Security & SBOM
- WAF-SEC-120 – Container & Runtime Security
- WAF-SEC-130 – Data Classification & Sensitive Data Protection
- Complete Controls Catalog
Security controls translate the Security Principles into measurable, auditable requirements for IaC-managed cloud infrastructure. They are the core of the WAF++ framework: machine-readable, automatically checkable, and equipped with concrete evidence requirements.
Each control has a unique ID in the format WAF-SEC-NNN, a severity rating,
machine-readable YAML checks, and a maturity-level graduation.
The YAML source files are located under modules/controls/controls/WAF-SEC-*.yml
and can be executed directly by the WAF++ Checker Tool.
The 13 controls are formulated as minimum requirements: anyone who meets all 13 has a solid security foundation – not a complete security program, but a demonstrably hardened cloud infrastructure that withstands audits.
Complete controls catalog across all pillars: Controls Catalog.
Controls Overview
| Control ID | Title | Severity | Category | Automated | Short Description |
|---|---|---|---|---|---|
Identity & Access Management Baseline |
Critical |
IAM |
Yes |
Root account protection, MFA enforcement, OIDC instead of static keys |
|
Least Privilege & RBAC Enforcement |
Critical |
IAM |
Yes |
No wildcard policies, permission boundaries, quarterly access reviews |
|
Encryption at Rest with CMK |
High |
Encryption |
Yes |
CMK for PII/financial data, KMS rotation, encryption of all data stores |
|
Encryption in Transit – TLS Enforcement |
High |
Encryption |
Yes |
TLS 1.2+ minimum, no HTTP without redirect, secure cipher suites |
|
Network Segmentation & Security Group Hardening |
High |
Network Security |
Yes |
Private-by-default, no 0.0.0.0/0 on management ports, VPC flow logs |
|
Secrets Management – No Hardcoded Credentials |
Critical |
Secrets |
Yes |
No plaintext secrets in code/ENV, automatic rotation, secrets manager |
|
Vulnerability & Patch Management |
Medium |
Vulnerability Management |
Partial |
Container scanning in CI, SBOM generation, patch SLA by CVSS |
|
Security Monitoring & Threat Detection |
High |
Monitoring |
Yes |
GuardDuty, CloudTrail multi-region, CloudWatch alarms for critical events |
|
Policy-as-Code & Compliance Automation |
Medium |
Policy-as-Code |
Yes |
wafpass/OPA as blocking CI gate, SCPs for org-level guardrails |
|
Incident Response Readiness |
Medium |
Incident Response |
Low |
Versioned IR playbooks, annual exercises, defined escalation paths |
|
Supply Chain Security & SBOM |
High |
Supply Chain |
Partial |
Mandatory SBOM, image signing (Cosign), SLSA requirements, dependency scanning |
|
Container & Runtime Security |
High |
Container Security |
Yes |
Non-root, read-only FS, no privileged mode, distroless images, admission control |
|
Data Classification & Sensitive Data Protection |
High |
Data Protection |
Partial |
Data classification schema, tagging policy, Macie scan, data access controls |
WAF-SEC-010 – Identity & Access Management Baseline
Severity: Critical | Category: IAM | Automatable: High
Intent: Without a solid IAM foundation, all other security controls can be circumvented by a single compromised account.
Requirement: An IAM baseline MUST be implemented: Root account secured with MFA and not used for daily operations; IAM password policy with complexity requirements; IMDSv2 enforced for EC2 instances; no long-lived access keys for IAM users in production.
Terraform Checks (excerpt):
-
waf-sec-010.tf.aws.iam-password-policy– IAM password policy with minimum length, complexity -
waf-sec-010.tf.aws.no-root-access-key– No active root access key -
waf-sec-010.tf.aws.ec2-imdsv2-required– EC2 instances withhttp_tokens = "required" -
waf-sec-010.tf.aws.no-iam-user-access-keys-in-production– No long-lived access keys
Evidence:
-
Terraform IAM policy configuration without root access keys
-
CloudTrail export: No root ConsoleLogin in the last 90 days
Best Practice: IAM Best Practice →
WAF-SEC-020 – Least Privilege & RBAC Enforcement
Severity: Critical | Category: IAM | Automatable: High
Intent: Excessive IAM permissions are the most common amplifier of cloud security incidents.
Requirement: No IAM policy MAY combine Action: * with Resource: *.
IAM roles MUST be configured according to the principle of least privilege.
Production resources MUST restrict permissions to specific actions and ARNs.
Quarterly IAM access reviews MUST be documented.
Terraform Checks (excerpt):
-
waf-sec-020.tf.aws.no-wildcard-iam-policy– NoAction: *withResource: * -
waf-sec-020.tf.aws.no-administrator-access-policy– NoAdministratorAccessfor application roles -
waf-sec-020.tf.aws.iam-role-boundary-policy– Permission boundaries for developer roles -
waf-sec-020.tf.aws.no-inline-admin-policy– No inline policies with admin scope
Evidence:
-
Terraform IAM roles without wildcard policies
-
IAM Access Analyzer findings report (no publicly accessible resources)
WAF-SEC-030 – Encryption at Rest with CMK
Severity: High | Category: Encryption | Automatable: High
Intent: Encryption protects data even if access control fails. Provider-managed keys are not data control – CMK is the minimum requirement.
Requirement: All data stores for PII, financial, and health data MUST be encrypted with Customer Managed Keys (CMK) via KMS. KMS key rotation MUST be enabled. Unencrypted EBS volumes, S3 buckets, and RDS instances in production environments are not permitted.
Terraform Checks (excerpt):
-
waf-sec-030.tf.aws.s3-bucket-kms-encryption– S3 usesaws:kms(CMK, not AES256) -
waf-sec-030.tf.aws.ebs-volume-encrypted– EBS volumes encrypted -
waf-sec-030.tf.aws.rds-storage-encrypted– RDS storage encryption enabled -
waf-sec-030.tf.aws.kms-key-rotation-enabled– KMS key rotation active -
waf-sec-030.tf.aws.dynamodb-table-encrypted– DynamoDB table with CMK
Evidence:
-
Terraform KMS CMK resources with
enable_key_rotation = true -
S3, RDS, EBS resources with explicit KMS key ARN
Best Practice: Encryption Strategy →
WAF-SEC-040 – Encryption in Transit – TLS Enforcement
Severity: High | Category: Encryption | Automatable: High
Intent: Unencrypted connections are unacceptable in production – regardless of whether traffic is internal or external.
Requirement: All external and internal API endpoints MUST enforce TLS 1.2 or higher. HTTP connections MUST be redirected to HTTPS. Deprecated protocols (SSL, TLS 1.0/1.1) MUST be disabled. Load balancers MUST use a secure TLS security policy.
Terraform Checks (excerpt):
-
waf-sec-040.tf.aws.alb-https-only– ALB listener enforces HTTPS (no plain HTTP) -
waf-sec-040.tf.aws.alb-tls-policy-modern– ALB TLS policy >= ELBSecurityPolicy-TLS13-1-2 -
waf-sec-040.tf.aws.cloudfront-minimum-protocol-tls12– CloudFront minimum protocol TLSv1.2 -
waf-sec-040.tf.aws.api-gateway-tls– API Gateway with TLS -
waf-sec-040.tf.aws.rds-no-plaintext-endpoint– RDS connections with TLS
Evidence:
-
Terraform ALB/NLB configuration with TLS security policy
-
SSL Labs report for public endpoints (Grade A or better)
WAF-SEC-050 – Network Segmentation & Security Group Hardening
Severity: High | Category: Network Security | Automatable: High
Intent: Network segmentation limits lateral movement by attackers. Without segmentation, compromised systems can reach all other systems in the same network.
Requirement: Production VPCs MUST separate private and public subnets.
Database resources MUST be in dedicated private subnets.
Security groups MUST NOT allow 0.0.0.0/0 for management ports (SSH 22, RDP 3389).
Open 0.0.0.0/0 egress rules are prohibited without explicit exceptions.
Terraform Checks (excerpt):
-
waf-sec-050.tf.aws.no-public-ssh– No security group with port 22 open to 0.0.0.0/0 -
waf-sec-050.tf.aws.no-public-rdp– No security group with port 3389 open to 0.0.0.0/0 -
waf-sec-050.tf.aws.no-unrestricted-ingress– No unrestricted ingress rules -
waf-sec-050.tf.aws.rds-not-public– RDS instance withpublicly_accessible = false -
waf-sec-050.tf.aws.vpc-flow-logs-enabled– VPC flow logs enabled
Evidence:
-
Terraform security group configurations without management port exposures
-
VPC architecture diagram with subnet separation
Best Practice: Network Security →
WAF-SEC-060 – Secrets Management – No Hardcoded Credentials
Severity: Critical | Category: Secrets | Automatable: High
Intent: Hardcoded credentials are the most direct path to a compromised system. Git history is permanent – a password once committed must be considered compromised.
Requirement: No secret (password, API key, private key, token) MAY exist in Terraform code, variable defaults, container definitions as plaintext ENV, or in the Git repository. All secrets MUST be managed in a dedicated secret store (AWS Secrets Manager, Parameter Store, HashiCorp Vault). Rotation MUST be configured for all secrets.
Terraform Checks (excerpt):
-
waf-sec-060.tf.any.no-plaintext-password-in-defaults– No password-like values in defaults -
waf-sec-060.tf.aws.ecs-no-plaintext-secrets-env– ECS task definitions usesecrets, notenvironment -
waf-sec-060.tf.aws.secrets-manager-rotation-enabled– Secrets Manager rotation configured -
waf-sec-060.tf.any.no-private-key-in-terraform– No PEM keys in Terraform code
Evidence:
-
Terraform code without plaintext secrets
-
git-secrets or trufflehog scan report (no findings in git history)
Best Practice: Secrets Management →
WAF-SEC-070 – Vulnerability & Patch Management
Severity: Medium | Category: Vulnerability Management | Automatable: Medium
Intent: Unpatched software is the most common source of successful attacks. Vulnerability management is not a one-time project – it is a continuous process.
Requirement: Container images MUST be scanned for critical CVEs before deployment. A patch SLA document MUST be defined (Critical: < 24h, High: < 7d, Medium: < 30d). ECR image scanning MUST be enabled for all production repositories.
Terraform Checks (excerpt):
-
waf-sec-070.tf.aws.ecr-image-scanning-on-push– ECR repository withscan_on_push = true -
waf-sec-070.tf.aws.ecr-image-tag-immutability– ECR withimage_tag_mutability = "IMMUTABLE" -
waf-sec-070.tf.aws.inspector-enabled– AWS Inspector for EC2/container enabled (optional)
Evidence:
-
Terraform ECR configuration with scan-on-push
-
Latest vulnerability scan report: 0 critical unpatched CVEs
Best Practice: Vulnerability Management →
WAF-SEC-080 – Security Monitoring & Threat Detection
Severity: High | Category: Monitoring | Automatable: High
Intent: Attacks that overcome prevention must be detected. Without monitoring, breaches remain undetected for months or years.
Requirement: AWS GuardDuty MUST be enabled in all production accounts. CloudTrail MUST be multi-region with log file validation and without a public S3 bucket. CloudWatch alarms MUST be configured for critical events (root login, IAM policy changes, security group changes).
Terraform Checks (excerpt):
-
waf-sec-080.tf.aws.guardduty-enabled– GuardDuty enabled -
waf-sec-080.tf.aws.cloudtrail-multi-region– CloudTrail multi-region with log validation -
waf-sec-080.tf.aws.cloudtrail-s3-not-public– CloudTrail S3 bucket not public -
waf-sec-080.tf.aws.cloudwatch-alarm-root-login– Alarm on root account activity -
waf-sec-080.tf.aws.cloudwatch-alarm-iam-changes– Alarm on IAM policy changes -
waf-sec-080.tf.aws.security-hub-enabled– Security Hub enabled
Evidence:
-
Terraform GuardDuty and CloudTrail configuration
-
CloudWatch alarm configurations for critical events
WAF-SEC-090 – Policy-as-Code & Compliance Automation
Severity: Medium | Category: Compliance | Automatable: High
Intent: Manual security reviews do not scale. Policy-as-Code is the only way to enforce consistent security standards across many teams and repositories.
Requirement: An automated security check (WAF++ Checker, OPA/Conftest, tfsec, checkov) MUST be active in the CI/CD pipeline and block critical findings. SCPs (Service Control Policies) or Azure Policies SHOULD be used for organization-wide guardrails.
Terraform Checks (excerpt):
-
waf-sec-090.tf.aws.organizations-scp-exists– SCP for critical actions present (optional) -
waf-sec-090.tf.any.required-terraform-version– Terraform version pinned -
waf-sec-090.tf.any.required-providers-version-pinned– Provider versions pinned
Evidence:
-
CI/CD pipeline logs with WAF++ Checker runs (all PRs scanned)
-
OPA policy files in the repository
Best Practice: Pattern 6 – Policy-as-Code Gateway →
WAF-SEC-100 – Incident Response Readiness
Severity: Medium | Category: Incident Response | Automatable: Low
Intent: An incident response plan that has never been practiced is a wish, not a plan. Readiness means: tested processes, clear responsibilities, working tools.
Requirement: An incident response playbook MUST exist (versioned, reviewed). It MUST contain escalation paths, communication protocols, and technical steps for common scenarios (data breach, ransomware, account compromise). Playbooks MUST be practiced at least annually through tabletop exercises.
Terraform Checks (excerpt):
-
waf-sec-100.tf.aws.config-recorder-enabled– AWS Config recorder active (for forensics) -
waf-sec-100.tf.aws.s3-access-logging-enabled– S3 access logging for critical buckets -
waf-sec-100.tf.aws.cloudtrail-enabled-all-regions– CloudTrail for complete forensics
Evidence:
-
Incident response playbook (versioned, with review date)
-
Record of the last IR exercise (tabletop exercise)
WAF-SEC-110 – Supply Chain Security & SBOM
Severity: High | Category: Supply Chain | Automatable: Partial
WAF-SEC-110 ensures that all software artifacts originate from verifiable, tamper-resistant sources and are fully documented. Modern supply chain attacks (SolarWinds, XZ Utils) show that the attack vector is not the application itself but its dependencies. This control requires SBOM generation, image signing, and build provenance requirements – the foundation for software trust chains in regulated environments.
Key Requirements:
-
For all production container images, an SBOM (Software Bill of Materials) in CycloneDX or SPDX format MUST be generated and archived
-
Container images MUST be cryptographically signed (Cosign/Notary); the signature MUST be verified before deployment
-
CI/CD pipelines MUST use OIDC-based identities (no static pipeline credentials); dependency scanning MUST be active for all dependencies
What wafpass checks automatically:
-
waf-sec-110.tf.aws.ecr-image-scanning-on-push– ECR scan-on-push for all repositories -
waf-sec-110.tf.aws.ecr-tag-immutability– ECR image tag immutability enabled -
waf-sec-110.tf.any.lockfile-present–.terraform.lock.hclpresent in repository -
waf-sec-110.ci.any.sbom-generation-step– CI/CD pipeline contains SBOM generation step -
waf-sec-110.ci.any.image-signing-step– CI/CD pipeline contains image signing step (Cosign)
Evidence:
-
SBOM artifacts (CycloneDX JSON) in CI/CD artifact storage, at least per release
-
Cosign signature verification in the deployment pipeline
WAF-SEC-120 – Container & Runtime Security
Severity: High | Category: Container Security | Automatable: Yes
WAF-SEC-120 addresses the specific security risks of container workloads. Container images that run as root, have privileged access, or use writable file systems represent a significant attack surface – even if the underlying Kubernetes cluster is well-configured. A compromised privileged container is equivalent to a host compromise; this control draws the line between workload isolation and host access.
Key Requirements:
-
All containers MUST run as non-root user (
runAsNonRoot: true,runAsUsernot 0); privileged mode is prohibited in production environments -
Container file systems MUST be mounted read-only (
readOnlyRootFilesystem: true) with explicit tmpfs mounts for write access -
Kubernetes admission control (OPA Gatekeeper or Kyverno) MUST enforce container security requirements as mandatory rules; distroless or minimal base images are required
What wafpass checks automatically:
-
waf-sec-120.tf.aws.ecs-no-privileged-containers– ECS task definition: noprivileged = true -
waf-sec-120.tf.aws.ecs-no-root-user– ECS task definition:usernot"root"or"0" -
waf-sec-120.tf.aws.ecs-readonly-root-filesystem– ECS task definition:readonlyRootFilesystem = true -
waf-sec-120.k8s.any.no-privileged-containers– No privileged containers in Kubernetes workloads -
waf-sec-120.k8s.any.run-as-non-root–securityContext.runAsNonRoot: trueset -
waf-sec-120.tf.aws.eks-control-plane-logging– EKS control plane logging enabled
Evidence:
-
Kubernetes manifest exports with
securityContextconfigurations for all production workloads -
OPA Gatekeeper / Kyverno policy listing from the cluster
WAF-SEC-130 – Data Classification & Sensitive Data Protection
Severity: High | Category: Data Protection | Automatable: Partial
WAF-SEC-130 ensures that all cloud resources carry a data classification and that resources with sensitive data are protected according to their classification. Without data classification, all data is treated equally: either everything is over-protected (expensive) or everything is under-protected (compliance risk). Classification enables proportional, demonstrable protection measures and is the basis for GDPR accountability and audit evidence.
Key Requirements:
-
All production resources (S3, RDS, DynamoDB, EFS) MUST carry a
DataClassificationtag (public,internal,confidential,restricted) -
Resources with
confidentialorrestrictedclassification MUST be CMK-encrypted and must not allow public access -
Amazon Macie (or an equivalent sensitive data discovery tool) MUST be active for all S3 buckets with
internalor higher classification
What wafpass checks automatically:
-
waf-sec-130.tf.any.data-classification-tag-required–DataClassificationtag on all storage resources -
waf-sec-130.tf.aws.confidential-restricted-cmk-encryption– CMK requirement forconfidential/restrictedresources -
waf-sec-130.tf.aws.macie-enabled– Amazon Macie enabled -
waf-sec-130.tf.aws.s3-no-public-access-confidential– Public access to classified buckets blocked -
waf-sec-130.tf.any.tag-policy-enforced– AWS Tag Policy or Azure Policy for tag enforcement active
Evidence:
-
Tag compliance report:
aws resourcegroupstaggingapi get-resourceswithDataClassificationfilter -
Amazon Macie finding summary of the last 30 days (JSON export)
Complete Controls Catalog
All controls across all pillars: Controls Catalog →