Infrastructure Rule Enforcement as Code — validate Terraform against YAML rules
Project description
Riveter
Infrastructure Rule Enforcement as Code — validate Terraform configurations against YAML rules before deployment.
Riveter catches security misconfigurations and compliance violations during development, not after. Define rules in plain YAML, use one of 15 built-in compliance packs, or do both.
Installation
macOS / Linux — Homebrew
brew install ScottRyanHoward/riveter/riveter
AI features are bundled — just add your ANTHROPIC_API_KEY to use them.
All platforms — pip (requires Python 3.12+)
pip install riveter # core
pip install riveter[ai] # + AI rule generation and explain features
Windows — pip is the recommended path. Install Python 3.12+, then run the pip command above. No PATH setup required beyond Python itself.
Direct download — grab the latest binary from the Releases page if you prefer a standalone executable with no Python dependency. AI features are bundled, same as Homebrew.
Quick Start
# Scan with a built-in rule pack
riveter scan -p aws-security -t main.tf
# Scan with a custom rules file
riveter scan -r my-rules.yml -t main.tf
# Combine multiple packs
riveter scan -p aws-security -p cis-aws -t main.tf
# Scan an entire directory
riveter scan -p aws-security -t ./infra/
# Save an HTML report
riveter scan -p aws-security -t main.tf -f html -o report.html
# Validate deployed state (drift detection)
riveter scan-state -p aws-security -s terraform.tfstate
# Pipe remote state from any Terraform backend
terraform state pull | riveter scan-state -p aws-security -s -
# Generate rules for your Terraform files using AI (requires ANTHROPIC_API_KEY)
riveter generate-rules -t ./infra/ -o my-rules.yml
riveter scan -r my-rules.yml -t ./infra/
# See available rule packs
riveter list-rule-packs
Commands
riveter scan
Validates Terraform against rules and exits non-zero if any checks fail.
| Flag | Short | Description |
|---|---|---|
--terraform PATH |
-t |
Required. Path to a .tf file or directory |
--rule-pack NAME |
-p |
Built-in rule pack (repeatable) |
--rules FILE |
-r |
Custom rules YAML file |
--output-format FMT |
-f |
table (default), json, junit, sarif, html |
--output FILE |
-o |
Write output to a file; table summary still shown in terminal |
--include-rules PATTERN |
Only run rules matching glob pattern (repeatable) | |
--exclude-rules PATTERN |
Skip rules matching glob pattern (repeatable) | |
--config FILE |
-c |
Config file path (auto-detected if omitted) |
--explain |
-e |
Attach AI-generated explanations to violations (requires ANTHROPIC_API_KEY) |
--debug |
Enable debug logging |
riveter scan-state
Validates a Terraform state file against rules for drift detection.
| Flag | Short | Description |
|---|---|---|
--state PATH |
-s |
Required. Path to terraform.tfstate, or - for stdin |
--rule-pack NAME |
-p |
Built-in rule pack (repeatable) |
--rules FILE |
-r |
Custom rules YAML file |
--output-format FMT |
-f |
table (default), json, junit, sarif, html |
--output FILE |
-o |
Write output to a file; table summary still shown in terminal |
--include-rules PATTERN |
Only run rules matching glob pattern (repeatable) | |
--exclude-rules PATTERN |
Skip rules matching glob pattern (repeatable) | |
--config FILE |
-c |
Config file path (auto-detected if omitted) |
--debug |
Enable debug logging |
State format: Requires Terraform state format v4 (Terraform 0.13+). Data sources are automatically excluded — only managed resources are validated.
riveter generate-rules
Uses Claude to suggest 3–5 enforceable Riveter rules per resource type found in your Terraform files. Output is a valid rules YAML file you can review, customize, and pass to riveter scan -r. Requires ANTHROPIC_API_KEY.
| Flag | Short | Description |
|---|---|---|
--terraform PATH |
-t |
Required. Path to a .tf file or directory |
--output FILE |
-o |
Write generated rules to a file (default: stdout) |
--focus TEXT |
Guide the AI, e.g. "PCI-DSS compliance" or "cost optimization" |
|
--model MODEL |
Override the Claude model | |
--debug |
Enable debug logging |
riveter list-rule-packs
Lists all available rule packs with name, version, rule count, and description.
Built-in Rule Packs
| Pack | Rules | Coverage |
|---|---|---|
aws-security |
26 | EC2, S3, RDS, VPC, IAM, KMS, Lambda |
azure-security |
28 | VMs, Storage, SQL, Key Vault, NSGs |
gcp-security |
29 | Compute, Storage, SQL, VPC, IAM |
kubernetes-security |
40 | EKS, AKS, GKE |
multi-cloud-security |
40 | Cross-cloud patterns |
cis-aws |
22 | CIS AWS Foundations Benchmark v3.0.0 |
cis-azure |
34 | CIS Azure Foundations Benchmark v2.0.0 |
cis-gcp |
43 | CIS GCP Foundations Benchmark v2.0.0 |
aws-well-architected |
34 | AWS Well-Architected Framework |
azure-well-architected |
35 | Azure Well-Architected Framework |
gcp-well-architected |
30 | GCP Architecture Framework |
aws-hipaa |
35 | HIPAA compliance |
azure-hipaa |
30 | Azure HIPAA |
aws-pci-dss |
40 | PCI-DSS v4.0 compliance |
soc2-security |
28 | SOC 2 Trust Service Criteria |
Writing Custom Rules
Create a YAML file with a rules key:
rules:
- id: ec2-must-be-encrypted
resource_type: aws_instance
description: All EC2 root volumes must be encrypted
assert:
root_block_device.encrypted: true
- id: ec2-prod-approved-types
resource_type: aws_instance
description: Production EC2s must use approved instance types
filter:
tags.Environment: production
assert:
instance_type:
regex: "^(t3|m5|c5)\\.(large|xlarge|2xlarge)$"
- id: s3-versioning-enabled
resource_type: aws_s3_bucket
description: S3 buckets must have versioning enabled
assert:
versioning.enabled: true
tags.Owner: present
Rule Fields
| Field | Required | Description |
|---|---|---|
id |
Yes | Unique rule identifier |
resource_type |
Yes | Terraform resource type, or "*" for all |
assert |
Yes | Assertions that must all be true |
description |
No | Human-readable summary |
filter |
No | Conditions a resource must match for the rule to apply |
metadata |
No | Extra metadata (tags, references, etc.) |
Assertion Operators
By default, property: value is an equality check. Use operator syntax for richer comparisons:
assert:
# Equality (default)
instance_type: t3.large
associate_public_ip_address: false
# Presence check
tags.Owner: present
# Regex match
instance_type:
regex: "^(t3|m5)\\.(large|xlarge)$"
# Numeric comparisons: gt, gte, lt, lte, ne, eq
root_block_device.volume_size:
gte: 100
# List operations
allowed_cidrs:
contains: "10.0.0.0/8"
ingress_rules:
length:
lte: 5
# none_match — no item in the list may match all fields of any pattern
ingress:
none_match:
- from_port: 22
cidr_blocks:
contains: "0.0.0.0/0"
- from_port: 3389
cidr_blocks:
contains: "0.0.0.0/0"
Nested Properties
Use dot notation to access nested attributes:
assert:
root_block_device.encrypted: true
tags.Environment: present
Filters
Filters restrict which resources a rule applies to. A rule is only evaluated for resources where all filter conditions match:
filter:
tags.Environment: production # equality
max_session_duration: present # "present" skips the rule if the field is absent
Output Formats
Table (default)
Rich terminal output with color-coded PASS/FAIL/SKIP status.
JSON
riveter scan -p aws-security -t main.tf -f json -o results.json
JUnit XML (CI/CD)
riveter scan -p aws-security -t main.tf -f junit -o results.xml
Compatible with GitHub Actions, Jenkins, GitLab CI, and any JUnit-aware CI system.
SARIF
riveter scan -p aws-security -t main.tf -f sarif -o results.sarif
Upload to GitHub Code Scanning for inline annotations.
HTML
riveter scan -p aws-security -t main.tf -f html -o report.html
Generates a self-contained HTML report with no external dependencies. Open in any browser to explore results with interactive filtering by status and resource/rule name. Click any row to expand full assertion details. When --explain is used, AI-generated explanations appear in the expanded detail panel for each failure. Useful for sharing scan results with stakeholders and auditors who can't easily read JSON or SARIF.
AI Features (Optional)
Both AI features require an Anthropic API key (pay-as-you-go). Get one at https://console.anthropic.com, then export it:
Homebrew / standalone binary: AI support is already bundled — skip to the API key step below. pip install: Run
pip install riveter[ai]to include the AI package.
export ANTHROPIC_API_KEY=sk-ant-...
Rule Generation
Don't know where to start with rules? Let Claude write a first draft based on your actual Terraform:
# Generate rules and print to stdout
riveter generate-rules -t ./infra/
# Save to a file and scan immediately
riveter generate-rules -t ./infra/ -o my-rules.yml
riveter scan -r my-rules.yml -t ./infra/
# Focus on a specific compliance framework
riveter generate-rules -t main.tf --focus "PCI-DSS compliance" -o pci-rules.yml
Riveter parses your Terraform, groups resources by type, and calls Claude once per type to suggest 3–5 enforceable rules. Each rule is validated against the rule schema before output — invalid suggestions are silently dropped. Always review and test generated rules before enforcing them in CI.
Violation Explanations
Riveter can explain violations in plain English — why a rule matters, what the risk is, and exactly how to fix it in your Terraform config.
Add --explain to any scan (cost: ~$0.001 per explanation):
riveter scan -p aws-security -t main.tf --explain
Or drill into a specific violation after the fact:
riveter explain ec2_no_public_ip \
--resource aws_instance.web_server --terraform main.tf -p aws-security
To always enable explanations, add this to riveter.yml:
ai:
explain_on_fail: true
model: claude-sonnet-4-20250514 # optional — overrides the default model
generate_model: claude-sonnet-4-20250514 # optional — model used for generate-rules
Note:
--explainis available onriveter scanonly, notscan-state.
Config File
Create riveter.yml (or .riveter.yml) in your project root:
rule_packs:
- aws-security
- cis-aws
rule_dirs:
- ./my-custom-rules # load rule packs from additional local directories
output_format: table
output_file: report.html # optional — same as passing -o report.html
include_rules:
- "*encryption*"
exclude_rules:
- "*test*"
ai:
explain_on_fail: true
model: claude-sonnet-4-20250514 # optional — model for --explain
generate_model: claude-sonnet-4-20250514 # optional — model for generate-rules
For scalar options (output_format, output_file), CLI values override the config file. For list options (rule_packs, rule_dirs, include_rules, exclude_rules), CLI values extend the config file list.
CI/CD Integration
GitHub Actions
- name: Scan Terraform with Riveter
run: |
brew install ScottRyanHoward/riveter/riveter
riveter scan -p aws-security -t main.tf -f junit -o riveter-results.xml
- name: Publish test results
uses: mikepenz/action-junit-report@v4
with:
report_paths: riveter-results.xml
if: always()
Exit Codes
| Code | Meaning |
|---|---|
0 |
All checks passed |
1 |
One or more checks failed (or a usage error occurred) |
Documentation
- User Guide — detailed usage, configuration, and CI/CD recipes
- Developer Guide — architecture, adding rule packs, contributing
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file riveter-0.2.40.tar.gz.
File metadata
- Download URL: riveter-0.2.40.tar.gz
- Upload date:
- Size: 129.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe4bf645ccf3d961349acd26bb0d492e91924bf63f6b19e02509d2a231434656
|
|
| MD5 |
12f3f2c8c9a39b846f70ee91a1d43035
|
|
| BLAKE2b-256 |
d0c518c3aab3165ba65ae8620046d575337c1ac30220c44cc03be114ae8dd5f1
|
Provenance
The following attestation bundles were made for riveter-0.2.40.tar.gz:
Publisher:
release.yml on ScottRyanHoward/riveter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
riveter-0.2.40.tar.gz -
Subject digest:
fe4bf645ccf3d961349acd26bb0d492e91924bf63f6b19e02509d2a231434656 - Sigstore transparency entry: 1425281060
- Sigstore integration time:
-
Permalink:
ScottRyanHoward/riveter@817e31bb067e3bd9d03d75698a0783d0083b4551 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ScottRyanHoward
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@817e31bb067e3bd9d03d75698a0783d0083b4551 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file riveter-0.2.40-py3-none-any.whl.
File metadata
- Download URL: riveter-0.2.40-py3-none-any.whl
- Upload date:
- Size: 92.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6df838b28e22207bb43e0100a2e22724205cf7e874abc4dccec4de4275700e13
|
|
| MD5 |
e2e6404c351a9df71d59505da72928ff
|
|
| BLAKE2b-256 |
90740103a649988589aee0ed016e92e9a96beb17d4dd2f08d76f436e8f05ef14
|
Provenance
The following attestation bundles were made for riveter-0.2.40-py3-none-any.whl:
Publisher:
release.yml on ScottRyanHoward/riveter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
riveter-0.2.40-py3-none-any.whl -
Subject digest:
6df838b28e22207bb43e0100a2e22724205cf7e874abc4dccec4de4275700e13 - Sigstore transparency entry: 1425281201
- Sigstore integration time:
-
Permalink:
ScottRyanHoward/riveter@817e31bb067e3bd9d03d75698a0783d0083b4551 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ScottRyanHoward
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@817e31bb067e3bd9d03d75698a0783d0083b4551 -
Trigger Event:
workflow_dispatch
-
Statement type: