Expert · Infrastructure as code · topic 38 of 50 · 30 min
IaC in a team: reviews, pipelines and policy
Explanation
Why process matters
IaC removes click mistakes, but a wrong line of code can now delete a production database in seconds. The answer is the same discipline developers use for application code: version control, review, automated checks and a controlled way to release. The goal is simple: no change reaches production without a reviewed plan.
The pull request workflow
- Create a branch and change the .tf files or the template.
- Open a pull request (PR). The CI pipeline (an automated build system such as GitHub Actions, GitLab CI or AWS CodePipeline) runs fmt, validate, policy checks and plan.
- The pipeline posts the plan output in the PR, so the reviewer sees "Plan: 1 to add, 0 to change, 0 to destroy." and the details.
- A teammate reviews both the code and the plan. A surprise destroy or replace is a reason to stop.
- After merge to main, the pipeline applies. For production, it waits for a manual approval first.
name: infra
on:
pull_request:
paths: ['infra/**']
push:
branches: [main]
paths: ['infra/**']
permissions:
id-token: write # lets the job get short-lived AWS credentials (OIDC), no stored keys
contents: read
jobs:
terraform:
runs-on: ubuntu-latest
defaults:
run:
working-directory: infra
steps:
- uses: actions/checkout@v7
- uses: hashicorp/setup-terraform@v3
- uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::111122223333:role/github-terraform
aws-region: ap-south-1
- run: terraform init -input=false
- run: terraform fmt -check
- run: terraform validate
- run: terraform plan -input=false -out=tfplan
- if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: terraform apply -input=false tfplanEnvironments: dev, stage and prod
Every environment should come from the same code, with differences only in settings. In Terraform, use a variable file per environment (dev.tfvars, prod.tfvars) and a separate state for each, either a separate folder and backend key per environment or Terraform workspaces. In CloudFormation, deploy the same template as separate stacks with different parameters. Many companies also put production in its own AWS account, so a mistake in dev cannot touch it.
Never put secrets in templates
A secret (a password, API key or token) written in a .tf file or template ends up in Git history forever, where anyone with read access can find it. Store secrets in AWS Secrets Manager, AWS Systems Manager Parameter Store, Azure Key Vault or Google Secret Manager, and let the code reference them. CloudFormation has dynamic references such as {{resolve:secretsmanager:prod/results/db:SecretString:password}}. Even better, let the service manage the secret: Amazon RDS can create and store the master password in Secrets Manager for you (ManageMasterUserPassword in CloudFormation, manage_master_user_password in Terraform).
Policy as code
Policy as code means writing your rules ("no public buckets", "every resource has an owner tag", "only these instance types") as code that runs automatically in the pipeline, before apply. A human reviewer gets tired on Friday evening; a policy check does not.
- Checkov: an open-source scanner with hundreds of ready-made checks for Terraform, CloudFormation, Kubernetes and more.
- Open Policy Agent (OPA): a general policy engine. You write rules in a language called Rego and run them against the plan in JSON form, often with a tool called conftest.
- AWS CloudFormation Guard (cfn-guard): an AWS open-source tool that checks templates against rules you write.
- At the cloud level, AWS Config rules, Service Control Policies and Azure Policy catch what slips through, even for changes made outside IaC.
Tagging standards
Tags are key and value labels on resources, such as env=prod, owner=payments-team, cost-centre=CC-104 and project=results. They let finance split the bill by team, let operations find who owns a forgotten server, and let backup plans select resources. Agree on required tags, check them with policy as code, and set them once for all resources: the Terraform AWS provider supports default_tags in the provider block.
Importing what was built by hand
Most companies already have resources created in the console. You do not need to delete and rebuild them. Terraform can bring existing resources under management with an import block (Terraform 1.5 and later) or the terraform import command, and CloudFormation can import existing resources into a stack. After importing, run plan until it shows no changes, which proves the code matches reality.
Stop console changes
Give people read-only console access to production and let only the pipeline role make changes. Keep a "break-glass" admin role for real emergencies, log its use, and copy any emergency fix back into the code the same day. Run plan or drift detection on a schedule so drift is noticed within hours, not months.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
IaC in a team: reviews, pipelines and policy · 1/7
In a team, infrastructure changes go through the same process as application code: Git, review, automated checks and a pipeline.
Prefer a video by a teacher? Find free videos on “terraform github actions pull request plan apply pipeline policy as code checkov” on YouTube ↗
In real life: A hospital chain stops public buckets before they exist
A hospital chain in Chennai stores lab reports in S3. After a near miss where a test bucket was made public, the platform team added Checkov and a small custom policy to the Terraform pipeline. Now any PR that creates a bucket without the public access block, without encryption settings, or without the owner and data-class tags fails before a human even reviews it. The developer sees the exact rule and line in the PR, fixes it in minutes, and the production AWS account only accepts changes from the pipeline role.
Practice (0/3 done)
A developer needs the database password in a Terraform configuration. What is the safest approach?
Write checkPolicy(resources, requiredTags). Each resource is an object like { name: "results", type: "s3_bucket", encrypted: true, public: false, tags: { env: "prod" } }. Return a list of problems as strings, in resource order. For each resource, check in this order: (1) only for type "s3_bucket": if encrypted is not true, add "<name>: not encrypted"; if public is true, add "<name>: public access". (2) for every resource: for each tag in requiredTags (in that order) that is missing from tags, add "<name>: missing tag <tag>". (AWS now encrypts new S3 objects by default, but many companies still require an explicit encryption setting, often with their own KMS key, so the policy checks it.)
Write a one-page "IaC rules" document for a team of five engineers who manage AWS with Terraform. Cover how a change goes from a laptop to production, how environments are separated, where state and secrets live, which automated checks run, and what happens in an emergency.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Modules, environments and Terraform in CIDevOps: Git, Docker, Kubernetes and CI/CD · Infrastructure as code with Terraform
- Terraform state, backends and driftDevOps: Git, Docker, Kubernetes and CI/CD · Infrastructure as code with Terraform
- Why infrastructure as codeDevOps: Git, Docker, Kubernetes and CI/CD · Infrastructure as code with Terraform
- Keeping secrets safeBackend Development · Backend security
- Terraform basics: HCL, providers, resources and the workflowDevOps: Git, Docker, Kubernetes and CI/CD · Infrastructure as code with Terraform
- Environment variables and secretsFull-Stack Development · Deploying and running the app
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
In a good IaC workflow, when does the change get applied to production?
Answer: After the PR is reviewed and merged, by the pipeline, usually with an approval step
The pipeline applies reviewed, merged code, with a manual approval for production.
What is policy as code?
Answer: Rules such as "no public buckets" written as code and checked automatically before apply
Tools like Checkov, OPA and cfn-guard check templates and plans against written rules in the pipeline.
Your company has 200 resources that were created in the console. What is the usual way to bring them under Terraform?
Answer: Import them (import blocks or terraform import), then plan until it shows no changes
Importing adds existing resources to the state; a clean plan proves the code matches them.
Why do teams define required tags like owner and cost-centre?
Answer: To split the bill by team, find owners of resources and select resources for backups and policies
Tags drive cost reports, ownership and automation. AWS does not require them by default, so teams enforce them with policy.
What is a main risk of using workspaces for dev and prod?Related
Answer: It is easy to run apply in the wrong workspace, and all environments share one backend and credentials
Workspaces share code, backend and usually credentials, so a slip can hit prod.
Why should terraform.tfstate not be committed to Git?Related
Answer: It can contain secrets in plain text and it must be shared with locking, which Git cannot do
State can hold passwords and keys, and it needs locking to stop two applies at once. Use an encrypted remote backend.
You run the same IaC apply twice in a row with no changes to the files. What should happen the second time?Related
Answer: Nothing changes, because the apply is idempotent
Idempotent means running it again gives the same result, so the second run finds nothing to do.
A bucket was created by hand last year. How do you bring it under Terraform without recreating it?Related
Answer: Use an import block (or terraform import), then plan and apply
Import adopts an existing object into state. A plain resource block would try to create a new one.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- This is the last topic of “Infrastructure as code”. The module exam comes next.
- Module 9 exam: Infrastructure as code · 12 questions · 20 min, without help. 4 topics of this module still to finish first.
- Then the next module, High availability, scaling and disaster recovery. 50 topics left in the course before the final exam.