Module 6: Rollback And Safety Nets

6. Guardrails of `apply`, named

Description

The previous lesson left one piece pending: an automated guardrail that blocks a specific dangerous action, without relying on a human noticing it. Lesson 7 builds a minimal, real version of that piece. Before getting there, this lesson names —without building— the tool the industry uses to do this at scale: conftest, and the policy language it rests on, Rego, the same language behind Open Policy Agent (OPA).

Connection to the module

This lesson is deliberately short and conceptual, with a single purpose: so you understand the exact difference between what you build in lesson 7 (a hand-written, artisanal grep, for one concrete case) and what a real policy system would do (declarative rules, evaluated against the complete plan, maintainable by an entire team). Without this lesson, it would be easy to finish lesson 7 thinking a grep is "how guardrails are done" — it isn't, it's the first rung, honest about its own limits.


What conftest is, in one sentence

conftest is a command-line tool that evaluates a structured file —in this case, the JSON output from terraform show -json you already know from lesson 5— against a set of declarative rules, written in Rego, Open Policy Agent's policy language. If any rule is violated, conftest fails with a nonzero exit code — exactly the signal a CI step needs to stop a job, the same principle behind lesson 7's guardrail, but with far more capable evaluation machinery behind it.

   LESSON 7's GUARDRAIL                          A REAL SYSTEM WITH conftest

   terraform show -json > plan.json               terraform show -json > plan.json
        │                                               │
        ▼                                               ▼
   grep -oE 'text pattern'                         conftest test plan.json
   (hand-written, one single case)                 (evaluates against .rego files,
        │                                            declarative rules, as many
        ▼                                            as the team needs)
   exit 1 if it finds "delete"                           │
   on Shipments                                          ▼
                                                     exit 1 if ANY rule
                                                     is violated — extensible without
                                                     touching the evaluation mechanism

A real rule, the kind a team would write for Andes Cargo's stack, could say something as simple —in Rego, not a grep— as: "no plan may include a delete action on aws_dynamodb_table.shipments, no matter what other change accompanies it." It sounds similar to lesson 7's guardrail because, in effect, it solves the same problem — the difference is in how that rule gets expressed, and how far it can be pushed before the mechanism becomes unsustainable.


Why a grep doesn't scale, and a policy does

Here's the exact technical reason a real policy-as-code system exists, beyond "because it sounds more professional":

  • A grep knows exactly one pattern. Lesson 7's specifically looks for "address":"aws_dynamodb_table.shipments" followed by "actions":[...] with "delete" inside. If tomorrow Andes Cargo wanted to also protect the bucket against destruction, or block any change that reduces an IAM role's permissions, each new case would need its own text pattern, hand-written and hand-maintained.
  • Rego evaluates structure, not text. A Rego policy doesn't search for a character string in a flat file — it walks the JSON as a real data structure, with full access to any field, any condition, any combination of rules ("block if A is destroyed, unless B is also being created in the same plan," for example) — expressiveness a text grep can't reach without becoming fragile.
  • A policy set is versioned code, owned by the security team. In a mature system, Rego rules live in their own repository (or directory), reviewed, tested, with their own change discipline — not a loose script inside a ci.yml step, maintained by whoever last had time to touch it.

Where this really gets built: cloud-security-and-guardrails-guide

This guide names conftest and policy-as-code here, deliberately, without building any policy system. Writing Rego rules, integrating them into a CI/CD pipeline, deciding which policies block the apply and which only warn, and designing the governance of who can approve an exception, is a complete discipline in its own right —exactly the territory of cloud-security-and-guardrails-guide, the sister guide that picks up this exact point and develops it end-to-end, with Andes Cargo's same Terraform plan as input.

What this guide leaves you with, instead, is the right question and the minimal mechanism that answers it: if you already know how to read a JSON plan well enough to write a grep that detects one concrete dangerous action —what you do in lesson 7—, you already have half the work done to understand what a Rego policy evaluates when you write one for real.


Common mistakes

Looking for a .rego file inside andes-cargo-infra/ after this lesson (expectation-based). What happens: someone, after reading about conftest, looks for a policy/ directory or some rules file inside this guide's project. How to spot it: if you search for Rego syntax in any file in this repository. How to fix it: this guide, by design, names conftest without building any policy system — the real mechanism you do build is in lesson 7, and it's deliberately simpler (a grep, not a declarative policy).

Thinking lesson 7's grep is "a bad version of conftest" to be avoided (conceptual). What happens: someone concludes that, since conftest is superior in capability, lesson 7's grep is a design mistake in this guide. How to fix it: the grep isn't a failed attempt at building conftest — it's, on purpose, the earlier rung: the minimal real pattern, honest about its own limit, that leaves you at exactly the right starting point to understand why the industry built something more capable afterward. Both things are legitimate in their place: a hand-crafted grep for one specific case, learned here; a declarative policy for a complete system, learned in cloud-security-and-guardrails-guide.


Exercises

Exercise 1 — Write, in prose, the Rego rule that would protect Andes Cargo's bucket. Without writing actual Rego code —that complete discipline lives in the sister guide—, describe in one sentence the exact condition a security team would want to automate for the andes-cargo-shipment-docs bucket.

See solution

A reasonable rule, in prose: "If the plan includes a delete action on module.shipment_docs_bucket.aws_s3_bucket.this, or any change that disables enable_versioning, the pipeline fails and the Pull Request can't merge without an additional explicit approval from someone outside the team that proposed the change." The point of this exercise isn't Rego's exact syntax, it's confirming you already know how to identify, in prose, the precise condition an automated policy should watch for — the same kind of reasoning you already practiced in terraform-and-iac-guide, Module 8.

Exercise 2 — Explain, without using the word "better," why Rego solves a problem a grep can't solve well. To a colleague asking "why bother with a new language if the grep already works?"

See solution

A complete answer sounds, roughly, like this: "The grep works perfectly for exactly one pattern, hand-written — the problem shows up when the team needs more than one rule, or rules that depend on combinations of conditions (for example, 'block this destruction, unless the same plan is also creating a valid replacement'). Writing that as plain text with grep gets fragile fast — any change to the JSON's format, or any new condition, forces you to rewrite the pattern from scratch. Rego evaluates the JSON as a real data structure, not as text, so it can express arbitrarily complex conditions without the evaluation mechanism itself changing — each new rule is one more .rego file, not a rewrite of the whole engine."

Exercise 3 — Locate the exact boundary between this module and cloud-security-and-guardrails-guide, in your own words. Without re-reading this lesson, describe in two sentences what this module did build about guardrails, and what's explicitly left for the sister guide.

See solution

This module builds a minimal, real, executed guardrail (lesson 7): a hand-crafted grep over the JSON plan, which blocks one concrete, well-defined case (destroying the Shipments table), demonstrated with act end-to-end. What's left for cloud-security-and-guardrails-guide is the complete policy-as-code system: declarative rules in Rego, evaluated with conftest, with its own governance discipline over what fails the build, what only warns, and who can approve an exception — the ability to express any policy, not just the one case this guide names by name.


Summary and next step

In this lesson you named conftest and Rego/Open Policy Agent as the industry's real mechanism for evaluating a Terraform plan against declarative policies, and understood the exact difference between that and the hand-crafted grep you build in the next lesson: expressiveness, structure versus text, and a complete governance discipline this guide doesn't build. cloud-security-and-guardrails-guide is where that complete system gets built end-to-end.

Before moving on you should be able to: explain what conftest is and what it evaluates; name at least two concrete reasons a declarative policy scales better than a grep; and precisely locate the boundary between this module and the sister guide.

Lesson 7 —hands-on— builds this guide's real guardrail: a minimal check, honest about its own limit, that genuinely blocks an attempt to destroy the Shipments table.

Resources

  1. Open Policy Agent — Official documentation — the policy engine (Rego) conftest is built on.
  2. Conftest — Official documentation — the tool named in this lesson, including examples of policies on terraform plan.
  3. Terraform Docs — Command: show — the command that produces the JSON output both conftest and lesson 7's guardrail evaluate.
  4. terraform-and-iac-guide, Module 8, lesson 4 — this guide family's first mention of conftest, with the same "name without building" pattern.