WAF++ WAF++
Back to WAF++ Homepage

Controls – Security (WAF-SEC)

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

WAF-SEC-010

Identity & Access Management Baseline

Critical

IAM

Yes

Root account protection, MFA enforcement, OIDC instead of static keys

WAF-SEC-020

Least Privilege & RBAC Enforcement

Critical

IAM

Yes

No wildcard policies, permission boundaries, quarterly access reviews

WAF-SEC-030

Encryption at Rest with CMK

High

Encryption

Yes

CMK for PII/financial data, KMS rotation, encryption of all data stores

WAF-SEC-040

Encryption in Transit – TLS Enforcement

High

Encryption

Yes

TLS 1.2+ minimum, no HTTP without redirect, secure cipher suites

WAF-SEC-050

Network Segmentation & Security Group Hardening

High

Network Security

Yes

Private-by-default, no 0.0.0.0/0 on management ports, VPC flow logs

WAF-SEC-060

Secrets Management – No Hardcoded Credentials

Critical

Secrets

Yes

No plaintext secrets in code/ENV, automatic rotation, secrets manager

WAF-SEC-070

Vulnerability & Patch Management

Medium

Vulnerability Management

Partial

Container scanning in CI, SBOM generation, patch SLA by CVSS

WAF-SEC-080

Security Monitoring & Threat Detection

High

Monitoring

Yes

GuardDuty, CloudTrail multi-region, CloudWatch alarms for critical events

WAF-SEC-090

Policy-as-Code & Compliance Automation

Medium

Policy-as-Code

Yes

wafpass/OPA as blocking CI gate, SCPs for org-level guardrails

WAF-SEC-100

Incident Response Readiness

Medium

Incident Response

Low

Versioned IR playbooks, annual exercises, defined escalation paths

WAF-SEC-110

Supply Chain Security & SBOM

High

Supply Chain

Partial

Mandatory SBOM, image signing (Cosign), SLSA requirements, dependency scanning

WAF-SEC-120

Container & Runtime Security

High

Container Security

Yes

Non-root, read-only FS, no privileged mode, distroless images, admission control

WAF-SEC-130

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 with http_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 – No Action: * with Resource: *

  • waf-sec-020.tf.aws.no-administrator-access-policy – No AdministratorAccess for 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 uses aws: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 with publicly_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 use secrets, not environment

  • 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 with scan_on_push = true

  • waf-sec-070.tf.aws.ecr-image-tag-immutability – ECR with image_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


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


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.hcl present 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, runAsUser not 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: no privileged = true

  • waf-sec-120.tf.aws.ecs-no-root-user – ECS task definition: user not "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-rootsecurityContext.runAsNonRoot: true set

  • waf-sec-120.tf.aws.eks-control-plane-logging – EKS control plane logging enabled

Evidence:

  • Kubernetes manifest exports with securityContext configurations 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 DataClassification tag (public, internal, confidential, restricted)

  • Resources with confidential or restricted classification 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 internal or higher classification

What wafpass checks automatically:

  • waf-sec-130.tf.any.data-classification-tag-requiredDataClassification tag on all storage resources

  • waf-sec-130.tf.aws.confidential-restricted-cmk-encryption – CMK requirement for confidential/restricted resources

  • 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-resources with DataClassification filter

  • Amazon Macie finding summary of the last 30 days (JSON export)


Complete Controls Catalog

All controls across all pillars: Controls Catalog →