# Terraform Guard (`dori1/terraform-guard`) Actor

Pre-apply Terraform and OpenTofu safety gate for AI agents and CI pipelines. Checks the exact plan JSON before apply and blocks risky database deletes, stateful replacements, public ingress, force-destroy buckets, and other production-impacting changes.

- **URL**: https://apify.com/dori1/terraform-guard.md
- **Developed by:** [Doron Aloni](https://apify.com/dori1) (community)
- **Categories:** Developer tools, MCP servers, Automation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.25 / terraform plan safety check

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## terraform-guard

AI-agent-native Terraform plan safety gate.

`terraform-guard` checks the JSON output of a Terraform/OpenTofu plan before
`apply` and returns a deterministic verdict:

- `allow`: no dangerous change detected
- `warn`: risky change needs human review
- `block`: likely data loss, exposure, outage, or privilege blast radius

It is designed for the new failure mode: coding agents can now edit
infrastructure and may try to run `terraform apply`. This tool gives agents,
CI systems, and humans a machine-readable pre-apply stop sign.

### Quick Start

```bash
pip install -e ".[dev]"
terraform plan -out=tf.plan
terraform show -json tf.plan > plan.json
terraform-guard check plan.json --pro --format text
```

Write PR/CI artifacts:

```bash
terraform-guard check plan.json --pro \
  --markdown-file terraform-guard.md \
  --sarif-file terraform-guard.sarif \
  --json-file terraform-guard.json
```

CI-friendly exit codes:

- `0`: allow
- `1`: parse/input error
- `2`: warn when `--fail-on warn`
- `3`: block

### MCP

Run the local MCP server:

```bash
terraform-guard-mcp
```

MCP tool:

- `terraform_guard_check_plan(plan_json, ruleset)`
- `terraform_guard_list_rules(ruleset)`

Local Pro mode is gated by `TFGUARD_LICENSE_KEY`. The current offline demo
accepts keys beginning with `TFG-PRO-`; production licensing must replace this
with signed offline licenses or marketplace verification.

### GitHub Action

This repository includes a root `action.yml` for GitHub Action distribution:

```yaml
- run: terraform plan -input=false -out=tf.plan
- run: terraform show -json tf.plan > tfplan.json
- uses: your-org/terraform-guard@v0
  with:
    plan-path: tfplan.json
    pro: "true"
    fail-on: block
    upload-sarif: "true"
```

Examples:

- `docs/examples/github-action-plan-gate.yml`
- `docs/examples/github-action-apply-gate.yml`
- `docs/examples/gitlab-ci.yml`
- `docs/examples/atlantis.yaml`

The action writes JSON, Markdown, and SARIF reports under
`terraform-guard-output/`.

### Apify

This repo includes an Apify Actor scaffold:

```text
.actor/actor.json
.actor/input_schema.json
.actor/output_schema.json
.actor/openapi.json
.actor/pay_per_event.json
Dockerfile
```

The Actor supports two modes:

- normal Actor run: paste `planJson`, get a dataset/KV result
- Standby mode: exposes a Streamable HTTP MCP endpoint at `/mcp`

Pay-per-event hooks are wired for:

- `terraform-plan-check`
- `terraform-pro-ruleset`

Configure the same events in Apify Console when publishing.

### Rules

Free rules:

| ID | Severity | Check |
| --- | --- | --- |
| TFG001 | block | Database delete |
| TFG002 | block | Stateful resource replacement |
| TFG003 | warn | Newly introduced public ingress |
| TFG004 | block | Network delete or replacement |

Pro rules:

| ID | Severity | Check |
| --- | --- | --- |
| TFG005 | block | Deletion protection disabled |
| TFG006 | block | Database replacement by broad type match |
| TFG007 | warn | Backup retention reduced |
| TFG008 | warn | Wildcard or broad administrative IAM |
| TFG009 | block | Load balancer removed or replaced |
| TFG010 | block | Force-destroy storage bucket |
| TFG011 | warn | Object storage made public |
| TFG012 | block | Encryption at rest disabled |
| TFG013 | block | Cryptographic key deleted or replaced |
| TFG014 | warn | Database made publicly reachable |

### Recommended Product Lane

Do not position this as another static Terraform scanner. Checkov and Trivy
already own broad IaC scanning.

The wedge is narrower and sharper:

> pre-apply approval gate for AI-generated infrastructure changes.

Best distribution targets:

- local CLI and MCP for Cursor, Claude, Codex, VS Code, and other agents
- GitHub/GitLab CI gates with PR comments
- Atlantis, Spacelift, env0, and Terraform Cloud run-task integrations
- Apify as an agent marketplace and pay-per-event experiment

The moat should be low-false-positive plan risk scoring, repo/workspace
baselines, approval evidence, and integrations in the actual apply path.

More detail:

- `docs/CI_APPLY_PATH_INTEGRATIONS.md`
- `docs/MONETIZATION_AND_REGISTRATION.md`
- `docs/PRODUCT_STRATEGY.md`

### Development

```bash
pip install -e ".[dev]"
pytest
ruff check .
```

### Privacy

The core scanner runs locally and does not call cloud APIs. Terraform plans can
contain sensitive infrastructure metadata, so local CLI/MCP and self-hosted CI
should be the primary enterprise deployment path. Hosted Apify runs are best for
demo, marketplace discovery, and teams comfortable uploading plan JSON.

# Actor input Schema

## `mode` (type: `string`):

Run a Terraform plan check or list active safety rules.

## `planJson` (type: `string`):

Paste output from `terraform show -json tf.plan`. JSON line streams from `terraform plan -json` are accepted with limited field-level detection.

## `ruleset` (type: `string`):

Free runs destructive core checks. Pro adds IAM, bucket, encryption, key, backup, load-balancer, and public database checks.

## Actor input object example

```json
{
  "mode": "check_plan",
  "ruleset": "pro"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("dori1/terraform-guard").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("dori1/terraform-guard").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call dori1/terraform-guard --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dori1/terraform-guard"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/CpaLSGhDwJMFDAi9i/builds/ItWGbUXC2OePXTaaB/openapi.json
