030 Project 30: Terraform Risk Reporter
030 Build a Terraform Risk Reporter
Use the parsed plan to fail CI on risky deletes/replacements.
Full main.go
package main
import (
"encoding/json"
"fmt"
"os"
)
type plan struct {
ResourceChanges []struct {
Address string `json:"address"`
Change struct {
Actions []string `json:"actions"`
} `json:"change"`
} `json:"resource_changes"`
}
func hasAction(actions []string, x string) bool {
for _, a := range actions {
if a == x {
return true
}
}
return false
}
func main() {
if len(os.Args) != 2 {
fmt.Println("usage: tf-risk <plan.json>")
os.Exit(2)
}
b, err := os.ReadFile(os.Args[1])
if err != nil {
panic(err)
}
var p plan
if err := json.Unmarshal(b, &p); err != nil {
panic(err)
}
risky := 0
for _, rc := range p.ResourceChanges {
a := rc.Change.Actions
replace := len(a) == 2 && a[0] == "delete" && a[1] == "create"
if hasAction(a, "delete") || replace {
risky++
fmt.Printf("RISK: %s actions=%v\n", rc.Address, a)
}
}
fmt.Printf("risky changes=%d\n", risky)
if risky > 0 {
os.Exit(1)
}
}Step-by-Step Explanation
- Export Terraform plan in JSON form.
- Parse
resource_changesinto typed structs. - Classify actions such as create/update/delete/replace.
- Compute risk, policy, or cost summaries.
- Gate CI based on explicit thresholds.
Code Anatomy
- Decoder layer parses JSON file.
- Analysis layer converts raw actions into signals.
- Reporting layer prints summary and sets exit status.
Learning Goals
- Build deterministic IaC review tools.
- Enforce infrastructure policy as code.
- Reduce risky deploys with automated checks.