-
Notifications
You must be signed in to change notification settings - Fork 1
Implement opa policy enforcement #289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This commit adds comprehensive Open Policy Agent (OPA) policies to enforce security best practices and cost control for AWS infrastructure: Policy files added: - policies/security-groups.rego: Prevents dangerous security group configurations * Blocks SSH/RDP access from 0.0.0.0/0 * Prevents overly permissive rules * Warns about exposed database and application ports - policies/s3-security.rego: Enforces S3 security standards * Requires standard tags (Environment, Name, Owner, Project) * Mandates server-side encryption * Warns about public access configurations - policies/cost-control.rego: Manages infrastructure costs * Flags expensive EC2/RDS instance types * Enforces cost tracking tags * Warns about high-cost configurations These policies use modern OPA syntax (rego.v1) and are compatible with the overmindtech/policy-signals-action for automated enforcement in CI/CD. Testing: - Policies tested with Conftest 0.62.0 (OPA 1.6.0) - Sample violations properly detected and reported - Ready for GitHub Actions integration
Integrates OPA policy enforcement into the CI/CD pipeline: - Adds policy-checks job that runs in parallel with fmt and execute jobs - Uses overmindtech/policy-signals-action@v1 for automated policy enforcement - Generates Terraform plan JSON specifically for policy evaluation - Runs on all pull request events (opened, synchronize, reopened) - Posts policy violation results as PR comments The policy checks will now automatically validate: - Security group configurations (SSH/RDP exposure) - S3 security settings (encryption, tags, public access) - Cost control measures (expensive instances, required tags) Policy violations will be reported as failures in the GitHub Actions run and detailed results will be posted as pull request comments.
Update all policy files to use older OPA syntax compatible with Conftest v0.46.0 (OPA 0.57.0) used in GitHub Actions: - Remove 'import rego.v1' statements - Change 'contains X if' to 'X[Y]' syntax - Change 'X in Y' to 'X == Y[_]' syntax - Fix duplicate package declarations Tested with Docker using openpolicyagent/conftest:v0.46.0 to match the GitHub Action environment exactly. Results: 36 tests, 27 passed, 2 warnings, 7 failures All expected policy violations detected correctly.
- Restructure workflow to run policy checks after plan submission - Add outputs to capture Terraform Cloud run URL from submit-plan - Create separate policy-checks job that depends on execute job - Pass custom ticket-link to policy-signals-action for proper Terraform Cloud integration - Policy violations now appear in Overmind UI linked to correct Terraform runs
Open in Overmind ↗
🟢 Change SignalsRoutine 🟢 🔥 RisksLow Risk of Impact from Hibernation Attribute and AMI Change 🟣 Expected Changes+/- ec2-instance › i-0e56e0f8eb58a4cf0- ami: ami-006aa762ec87a7afb
+ ami: ami-0174327c2510b4f8b
- arn: arn:aws:ec2:eu-west-2:540044833068:instance/i-0e56e0f8eb58a4cf0
+ arn: (known after apply)
- availability_zone: eu-west-2b
+ availability_zone: (known after apply)
- capacity_reservation_specification: [map[capacity_reservation_preference:open capacity_reservation_target:[]]]
+ capacity_reservation_specification: (known after apply)
- cpu_core_count: 1
+ cpu_core_count: (known after apply)
- cpu_options: [map[amd_sev_snp: core_count:1 threads_per_core:2]]
+ cpu_options: (known after apply)
- cpu_threads_per_core: 2
+ cpu_threads_per_core: (known after apply)
- credit_specification: [map[cpu_credits:unlimited]]
+ credit_specification: []
- disable_api_stop: false
+ disable_api_stop: (known after apply)
- disable_api_termination: false
+ disable_api_termination: (known after apply)
- ebs_block_device: []
+ ebs_block_device: (known after apply)
- ebs_optimized: false
+ ebs_optimized: (known after apply)
- enable_primary_ipv6: <nil>
+ enable_primary_ipv6: (known after apply)
- enclave_options: [map[enabled:false]]
+ enclave_options: (known after apply)
- ephemeral_block_device: []
+ ephemeral_block_device: (known after apply)
- hibernation: false
+ hibernation: <nil>
- host_id:
+ host_id: (known after apply)
- host_resource_group_arn: <nil>
+ host_resource_group_arn: (known after apply)
- iam_instance_profile:
+ iam_instance_profile: (known after apply)
- id: i-0e56e0f8eb58a4cf0
+ id: (known after apply)
- instance_initiated_shutdown_behavior: stop
+ instance_initiated_shutdown_behavior: (known after apply)
- instance_lifecycle:
+ instance_lifecycle: (known after apply)
- instance_market_options: []
+ instance_market_options: (known after apply)
- instance_state: running
+ instance_state: (known after apply)
- ipv6_address_count: 0
+ ipv6_address_count: (known after apply)
- ipv6_addresses: []
+ ipv6_addresses: (known after apply)
- maintenance_options: [map[auto_recovery:default]]
+ maintenance_options: (known after apply)
- metadata_options: [map[http_endpoint:enabled http_protocol_ipv6:disabled http_put_response_hop_limit:1 http_tokens:optional instance_metadata_tags:disabled]]
+ metadata_options: (known after apply)
- monitoring: false
+ monitoring: (known after apply)
- network_interface: []
+ network_interface: (known after apply)
- outpost_arn:
+ outpost_arn: (known after apply)
- password_data:
+ password_data: (known after apply)
- placement_group:
+ placement_group: (known after apply)
- placement_partition_number: 0
+ placement_partition_number: (known after apply)
- primary_network_interface_id: eni-03d8d79766b0341a3
+ primary_network_interface_id: (known after apply)
- private_dns: ip-10-0-10-44.eu-west-2.compute.internal
+ private_dns: (known after apply)
- private_dns_name_options: [map[enable_resource_name_dns_a_record:false enable_resource_name_dns_aaaa_record:false hostname_type:ip-name]]
+ private_dns_name_options: (known after apply)
- private_ip: 10.0.10.44
+ private_ip: (known after apply)
- public_dns: ec2-18-130-236-8.eu-west-2.compute.amazonaws.com
+ public_dns: (known after apply)
- public_ip: 18.130.236.8
+ public_ip: (known after apply)
- root_block_device: [map[delete_on_termination:true device_name:/dev/xvda encrypted:false iops:0 kms_key_id: tags:map[] tags_all:map[] throughput:0 volume_id:vol-0200e8799ecd1e004 volume_size:8 volume_type:standard]]
+ root_block_device: (known after apply)
- secondary_private_ips: []
+ secondary_private_ips: (known after apply)
- security_groups: []
+ security_groups: (known after apply)
- spot_instance_request_id:
+ spot_instance_request_id: (known after apply)
- tenancy: default
+ tenancy: (known after apply)
- user_data: <nil>
+ user_data: (known after apply)
- user_data_base64: <nil>
+ user_data_base64: (known after apply)+/- ec2-instance › i-0a427830cc9151c53- ami: ami-006aa762ec87a7afb
+ ami: ami-0174327c2510b4f8b
- arn: arn:aws:ec2:eu-west-2:540044833068:instance/i-0a427830cc9151c53
+ arn: (known after apply)
- availability_zone: eu-west-2a
+ availability_zone: (known after apply)
- capacity_reservation_specification: [map[capacity_reservation_preference:open capacity_reservation_target:[]]]
+ capacity_reservation_specification: (known after apply)
- cpu_core_count: 1
+ cpu_core_count: (known after apply)
- cpu_options: [map[amd_sev_snp: core_count:1 threads_per_core:2]]
+ cpu_options: (known after apply)
- cpu_threads_per_core: 2
+ cpu_threads_per_core: (known after apply)
- credit_specification: [map[cpu_credits:unlimited]]
+ credit_specification: []
- disable_api_stop: false
+ disable_api_stop: (known after apply)
- disable_api_termination: false
+ disable_api_termination: (known after apply)
- ebs_block_device: []
+ ebs_block_device: (known after apply)
- ebs_optimized: false
+ ebs_optimized: (known after apply)
- enable_primary_ipv6: <nil>
+ enable_primary_ipv6: (known after apply)
- enclave_options: [map[enabled:false]]
+ enclave_options: (known after apply)
- ephemeral_block_device: []
+ ephemeral_block_device: (known after apply)
- hibernation: false
+ hibernation: <nil>
- host_id:
+ host_id: (known after apply)
- host_resource_group_arn: <nil>
+ host_resource_group_arn: (known after apply)
- iam_instance_profile:
+ iam_instance_profile: (known after apply)
- id: i-0a427830cc9151c53
+ id: (known after apply)
- instance_initiated_shutdown_behavior: stop
+ instance_initiated_shutdown_behavior: (known after apply)
- instance_lifecycle:
+ instance_lifecycle: (known after apply)
- instance_market_options: []
+ instance_market_options: (known after apply)
- instance_state: running
+ instance_state: (known after apply)
- ipv6_address_count: 0
+ ipv6_address_count: (known after apply)
- ipv6_addresses: []
+ ipv6_addresses: (known after apply)
- maintenance_options: [map[auto_recovery:default]]
+ maintenance_options: (known after apply)
- metadata_options: [map[http_endpoint:enabled http_protocol_ipv6:disabled http_put_response_hop_limit:1 http_tokens:optional instance_metadata_tags:disabled]]
+ metadata_options: (known after apply)
- monitoring: false
+ monitoring: (known after apply)
- network_interface: []
+ network_interface: (known after apply)
- outpost_arn:
+ outpost_arn: (known after apply)
- password_data:
+ password_data: (known after apply)
- placement_group:
+ placement_group: (known after apply)
- placement_partition_number: 0
+ placement_partition_number: (known after apply)
- primary_network_interface_id: eni-060632729be4b5c61
+ primary_network_interface_id: (known after apply)
- private_dns: ip-10-0-9-171.eu-west-2.compute.internal
+ private_dns: (known after apply)
- private_dns_name_options: [map[enable_resource_name_dns_a_record:false enable_resource_name_dns_aaaa_record:false hostname_type:ip-name]]
+ private_dns_name_options: (known after apply)
- private_ip: 10.0.9.171
+ private_ip: (known after apply)
- public_dns: ec2-35-178-235-99.eu-west-2.compute.amazonaws.com
+ public_dns: (known after apply)
- public_ip: 35.178.235.99
+ public_ip: (known after apply)
- root_block_device: [map[delete_on_termination:true device_name:/dev/xvda encrypted:false iops:0 kms_key_id: tags:map[] tags_all:map[] throughput:0 volume_id:vol-01da4063d55002995 volume_size:8 volume_type:standard]]
+ root_block_device: (known after apply)
- secondary_private_ips: []
+ secondary_private_ips: (known after apply)
- security_groups: []
+ security_groups: (known after apply)
- spot_instance_request_id:
+ spot_instance_request_id: (known after apply)
- tenancy: default
+ tenancy: (known after apply)
- user_data: <nil>
+ user_data: (known after apply)
- user_data_base64: <nil>
+ user_data_base64: (known after apply)~ ec2-launch-template › lt-0731f767e6be2ab94- image_id: ami-006aa762ec87a7afb
+ image_id: ami-0174327c2510b4f8b
- latest_version: 17
+ latest_version: (known after apply)💥 Blast RadiusItems Edges |
|
The action repo is here |
dylanratcliffe
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing

This PR implements a complete Policy-as-Code solution using Open Policy Agent (OPA) with Conftest to automatically enforce security, compliance, and cost controls on Terraform infrastructure changes. Policy violations are automatically detected and reported as custom signals in Overmind with direct links to Terraform Cloud runs.
🎯 What This Implements
1. Security Policies (security-groups.rego)
0.0.0.0/02. S3 Security Policies (s3-security.rego)
Environment,Owner,Project,Name)3. Cost Control Policies (cost-control.rego)
🔄 How It Works
CI/CD Integration
-3Workflow Structure
graph LR A[PR Created] --> B[fmt Job] A --> C[execute Job] C --> D[Terraform Plan] D --> E[Submit to Overmind] E --> F[policy-checks Job] F --> G[Run OPA Policies] G --> H[Submit Violations as Signals]Example Violations Detected
The current terraform-example infrastructure will trigger these policy violations:
Demo Talking Points
🚫 Does It Block Anything?
Non-Blocking by Default
Configurable Enforcement
The action supports a
fail-on-violationsparameter (currently set tofalse) that could be enabled to:🔧 Technical Implementation
Components Added
policy-checksjob in existing workflow🧪 Testing
This implementation has been tested with: