The pull request that opened the database
A Terraform change to 'debug a connection issue' opens the RDS security group to 0.0.0.0/0 and makes the bucket policy public. The plan looked small, and it was approved.
- Weakness
- CWE-284 · Improper access control · OWASP A05 Security misconfiguration
- Target
- the ShopLite Terraform code (Terraform course)
Run these techniques only against the lab you own. Using them on systems you don't have permission to test is illegal.
The threat
01Misconfiguration is the most common cloud breach
Most cloud data exposures aren't sophisticated exploits: they're a storage bucket made public, a database reachable from the internet, or an overly broad IAM policy, often introduced as a 'temporary' change. Automated internet-wide scanners find open databases and public buckets within hours. With infrastructure as code, these mistakes arrive as diffs in pull requests, where they can be caught automatically.
infra/security.tf (the change under review)add to filehcl resource "aws_vpc_security_group_ingress_rule" "db_debug" { security_group_id = aws_security_group.db.id cidr_ipv4 = "0.0.0.0/0" # "temporary, for debugging" ip_protocol = "tcp" from_port = 5432 to_port = 5432 }
What's at risk
- The production database's login port reachable from the entire internet, relying on the password alone.
Detect
01Scan the Terraform in the PR
terminal$ docker run --rm -v "$PWD/infra:/src" aquasec/trivy:0.63.0 config --severity HIGH,CRITICAL /src── output ──security.tf (terraform)Tests: 112 (SUCCESSES: 111, FAILURES: 1)Failures: 1 (HIGH: 0, CRITICAL: 1)AVD-AWS-0107 (CRITICAL): Security group rule allows ingress from public internet.════════════════════════════════════════security.tf:61-67────────────────────────────────────────63 │ cidr_ipv4 = "0.0.0.0/0"02Or checkov, with a different rule set
Running two scanners catches more, since their rule sets differ.
checkov -d infra --compactreports the same public-ingress finding under its own rule ID. Pick one scanner as the blocking gate and keep the other advisory, so developers aren't asked to satisfy two tools for the same finding.
Defend
01Fix the need, not just the rule
The engineer needed to reach the database to debug. The Session Manager tunnel from the Terraform course (Mission 4.1) gives exactly that, with no open ports and full audit logging. Remove the rule; document the tunnel in the runbook.
Vulnerable
infra/security.tfadd to filehcl cidr_ipv4 = "0.0.0.0/0" # "temporary, for debugging"Hardened
runbook: connecting to the databasewhole filebash aws ssm start-session --target <probe-instance> \ --document-name AWS-StartPortForwardingSessionToRemoteHost \ --parameters "host=<db-endpoint>,portNumber=5432,localPortNumber=15432"02Make the scanner a required PR check
Run it on every PR that touches
infra/ormodules/, upload results as SARIF so findings appear inline on the diff, and mark the check required in branch protection. Accepted risks are suppressed in code with a reason, so the decision is reviewed and visible.Hardened
.github/workflows/iac-scan.ymlwhole fileyaml on: pull_request: paths: ["infra/**", "modules/**"] permissions: { contents: read, security-events: write } jobs: trivy-config: runs-on: ubuntu-latest steps: - uses: actions/checkout@<sha> # v4 - uses: aquasecurity/trivy-action@<sha> # 0.32.0 with: scan-type: config severity: HIGH,CRITICAL exit-code: "1" format: sarif output: trivy.sarif - uses: github/codeql-action/upload-sarif@<sha> # v3 if: always() with: { sarif_file: trivy.sarif }
Verify
01Scanner passes; the policy gate on the plan agrees
The static scan is clean, and the OPA plan policy from the Terraform course (Mission 7.3) would also have denied the rule, since it checks for public ingress in the PLANNED values. Two independent layers: code scanning catches it early; plan policy catches values that only resolve at plan time.
terminal$ docker run --rm -v "$PWD/infra:/src" aquasec/trivy:0.63.0 config -q --severity HIGH,CRITICAL /src── output ──(no findings)
The concepts
Shift left, and keep the right
Scanning IaC in pull requests catches misconfigurations before they exist. It can't catch changes made outside code, such as console edits or other tools. So keep runtime detection too: AWS Config rules, Security Hub, and drift detection (Terraform course, Mission 7.4). Prevention in the PR, detection in the account.
Your turn
How do you suppress a trivy config finding for one resource with a reason?
Interview questions
How do you prevent insecure infrastructure changes?