Terraform and IaC Security Assessment Pack
Intro: These tasks are intentionally practical. The question is rarely โwhat does this resource do?โ The question is โwhat trust assumption did the author just make, and where does it leak?โ
Task 1 - Terraform backend has no clear locking or encryption story
terraform {
backend "s3" {
bucket = "team-terraform-state"
key = "prod/network/terraform.tfstate"
region = "us-east-1"
}
}
Prompt
What is missing? Why does it matter operationally and from a security perspective?
Reveal the worked answer
Missing elements to discuss
- no explicit locking story;
- no mention of bucket hardening or access policy;
- no state sensitivity discussion;
- no clear KMS / encryption description;
- no segregation of environments or ownership.
Better answer
A strong candidate says the backend block is only part of the story. You must also review the bucket policy, encryption, locking mechanism, access model, and environment separation.
Task 2 - Security group allows broad access because CIDR is passed from a shared variable
variable "admin_cidrs" {
type = list(string)
default = ["0.0.0.0/0"]
}
resource "aws_security_group_rule" "ssh_ingress" {
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = var.admin_cidrs
security_group_id = aws_security_group.app.id
}
Prompt
What would you fix in code and in process?
Reveal the worked answer
Code fix direction
- remove insecure defaults;
- require explicit caller-provided ranges;
- consider replacing SSH with Session Manager or JIT access patterns.
Process fix direction
- add policy checks for
0.0.0.0/0on admin ports; - block merge on critical exposure;
- require justification for exceptions.
Task 3 - Module source is unpinned and fetched from Git on every run
module "vpc" {
source = "git::https://github.com/example-org/terraform-vpc.git"
name = "prod-vpc"
}
Prompt
Why is this weak from a supply-chain perspective? Show a safer pattern.
Reveal the worked answer
Why weak
Without a pinned ref, the module content can drift unexpectedly. Review and execution no longer mean the same thing over time.
Safer pattern
module "vpc" {
source = "git::https://github.com/example-org/terraform-vpc.git?ref=v1.4.2"
name = "prod-vpc"
}
Better still
Use an internal reviewed module distribution path and deliberate update workflow.
Task 4 - Ansible task leaks secrets into logs and shell history
- name: configure application secret
shell: |
echo "APP_SECRET={{ app_secret }}" >> /etc/app.env
become: true
Prompt
This is mixed Terraform/IaC review territory. Explain the issue and propose a safer Ansible pattern.
Reveal the worked answer
What is wrong
shellis unnecessary for a simple file update;- secrets may appear in logs, task output, or process inspection;
- idempotence is poor.
Safer Ansible pattern
- name: configure application secret
copy:
dest: /etc/app.env
content: "APP_SECRET={{ app_secret }}\n"
owner: root
group: root
mode: "0600"
no_log: true
become: true
Strong answer also mentions
Prefer a secret manager or injected runtime identity if the environment supports it.
Task 5 - terraform apply is triggered from merge requests with live cloud credentials
Scenario
The pipeline runs terraform plan and terraform apply in the same MR workflow against a real staging account, using long-lived cloud keys in CI variables.
Prompt
What are the issues and how would you redesign the workflow?
Reveal the worked answer
Issues
- unreviewed or insufficiently reviewed infra mutation from MR context;
- long-lived credentials in CI;
- likely plan/apply trust collapse;
- higher blast radius if a malicious MR lands on a trusted runner.
Better redesign
- run lint, validate, and policy checks on every MR;
- run plan in a controlled review stage;
- require explicit promotion or protected-branch/tag context for apply;
- replace long-lived cloud keys with OIDC/federated identity where possible.