Opa / Conftest Integration
Add policy context to your infrastructure changes by running Conftest/OPA policies and submitting violations as organized policy signals to enhance Overmind's risk analysis.
This GitHub Actionruns your Conftest/OPA policies in parallel with your Terraform analysis, giving you immediate feedback on compliance issues without slowing down your workflow.
Quick Start​
Add policy checks to your Overmind workflow in under 2 minutes:
- uses: overmindtech/policy-signals-action@v1
with:
policies-path: './policies'
overmind-api-key: ${{ secrets.OVM_API_KEY }}
What This Action Does​
This GitHub Action enhances your Overmind change analysis by:
- Running policy checks immediately when a PR is created or updated
- Submitting violations as organized policy signals to Overmind (runs in parallel with Terraform analysis)
- Providing instant feedback on compliance issues (typically within 30 seconds)
- Enriching PR comments with policy context alongside blast radius analysis
How It Works​
Policy violations appear as organized "Policies" signals in your PR analysis. Overmind aggregates Custom Signals by title and handles the generation of the Signal summary automatically.
The action follows this flow:
- PR triggers workflow - Both Terraform analysis and policy checks start
- Policies run immediately - Conftest evaluates your Terraform plan
- Violations become signals - Each violation is submitted as a Custom Signal linked to the PR URL
- Overmind aggregates - All signals for that PR are collected together
- Progressive updates - PR comment updates as signals arrive
- Complete context - Final comment includes both policy and blast radius info
Installation​
Prerequisites​
- An Overmind account (sign up free)
- Overmind API key stored as
OVM_API_KEY
in your GitHub secrets - Terraform repository with policy files (Rego format)
- A GitHub Pull Request (Custom Signals are linked to PRs)
Basic Setup​
Add the action to your workflow (.github/workflows/terraform.yml
):
name: Terraform Analysis with Policies
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
# Your existing terraform job continues unchanged
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: overmindtech/actions/install-cli@main
- uses: overmindtech/actions/submit-plan@main
with:
ovm-api-key: ${{ secrets.OVM_API_KEY }}
plan-json: ./tfplan.json
# NEW: Add policy checks in parallel
policy-checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: overmindtech/policy-signals-action@v1
with:
policies-path: './policies'
overmind-api-key: ${{ secrets.OVM_API_KEY }}
Create your first policy (policies/s3-tags.rego
):
package terraform.s3
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
not resource.change.after.tags.Owner
msg := sprintf("S3 bucket %s missing required 'Owner' tag", [resource.address])
}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
not resource.change.after.tags.Environment
msg := sprintf("S3 bucket %s missing required 'Environment' tag", [resource.address])
}
Push changes and watch the magic happen! Policy violations will appear in your PR comment within seconds.
Configuration​
Action Inputs​
Input | Description | Required | Default |
---|---|---|---|
policies-path | Path to your Conftest/OPA policy files | Yes | - |
overmind-api-key | Your Overmind API key | Yes | - |
terraform-plan-json | Path to terraform plan JSON (if available) | No | Auto-detected |
signal-severity | Default severity for policy violations (-5 to +5) | No | -3 |
signal-category | Category for organizing policy signals in Overmind | No | Policies |
ticket-link | Custom URL to link signals to (e.g., Terraform Cloud run) | No | GitHub PR URL |
fail-on-violations | Fail the action if violations are found | No | false |
conftest-version | Version of Conftest to install | No | 0.46.0 |
overmind-cli-version | Version of Overmind CLI to install | No | 1.9.4 |
Advanced Configuration​
- uses: overmindtech/policy-signals-action@v1
with:
policies-path: './policies'
overmind-api-key: ${{ secrets.OVM_API_KEY }}
terraform-plan-json: './tfplan.json'
signal-severity: -4 # Higher risk score for violations
signal-category: 'Security Policies' # Custom category
ticket-link: 'https://app.terraform.io/app/org/workspace/runs/run-xyz' # Terraform Cloud run
fail-on-violations: true # Block PR on policy violations
Terraform Cloud Integration​
The ticket-link
input is particularly useful for Terraform Cloud workflows:
- uses: overmindtech/policy-signals-action@v1
with:
policies-path: './policies'
overmind-api-key: ${{ secrets.OVM_API_KEY }}
ticket-link: ${{ env.TF_CLOUD_RUN_URL }} # Links signals to TFC run instead of GitHub PR
Example Policies​
Security Group Rules​
package terraform.security
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_security_group_rule"
resource.change.after.cidr_blocks[_] == "0.0.0.0/0"
resource.change.after.from_port == 22
msg := sprintf("Security group %s allows SSH from anywhere", [resource.address])
}
Cost Control​
package terraform.cost
allowed_instance_types := [
"t3.micro", "t3.small", "t3.medium"
]
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_instance"
not resource.change.after.instance_type in allowed_instance_types
msg := sprintf("Instance %s uses non-approved type: %s",
[resource.address, resource.change.after.instance_type])
}
Compliance​
package terraform.compliance
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_db_instance"
not resource.change.after.storage_encrypted
msg := sprintf("RDS instance %s has unencrypted storage", [resource.address])
}
Testing​
Local Policy Testing (No API Required)​
Test your policies work correctly without submitting to Overmind:
# Test policies catch violations in your terraform plan
./test/test-policies.sh ./policies ./tfplan.json
# This will show you what violations would be caught
# but won't submit anything to Overmind
Integration Testing (Real PR Required)​
To test the complete flow with actual signal submission:
# Set your environment variables
export OVERMIND_API_KEY="your_actual_api_key"
export TICKET_LINK="https://github.com/org/repo/pull/123"
# Run the real submission test
./test/test_real_submission.sh
Important: Custom Signals are always linked to a PR URL. You cannot test signal submission without a real, existing GitHub Pull Request.
FAQ​
How do Custom Signals work without a Change ID?​
Custom Signals are linked to Pull Request URLs, not specific Change IDs. When you submit a signal with a PR URL, Overmind automatically associates it with any changes for that PR, or holds it until a change is created.
Can I test this without a real PR?​
You can test that your policies detect violations locally using Conftest, but to test the full signal submission flow, you need a real GitHub PR. Custom Signals must be linked to an actual PR URL.
What happens if I submit signals before running terraform plan?​
That's the beauty of parallel execution! Signals are aggregated by PR URL, so they'll appear as soon as they're submitted. The PR comment will progressively update as both policy signals and Terraform analysis complete.
Do signals from different jobs get combined?​
Yes! All signals submitted with the same PR URL are automatically aggregated by Overmind, whether they come from policy checks, Terraform analysis, or any other source.
What happens when all policies pass?​
No Custom Signals are submitted! This is the ideal behavior:
- ✅ Clean runs are silent - You only hear from the policy system when there are issues
- ✅ No noise in PRs - Policy signals only appear when violations need attention
- ✅ Better performance - No unnecessary API calls when everything is compliant
- ✅ Clean Overmind dashboard - Only actual issues create signals
The action logs will show ✓ No policy violations found
and complete successfully. Your PR will only show the standard Terraform analysis without any policy-related Custom Signals.