ops0ops0

Create a Policy and Block a Deployment

Write a security policy in OPA/Rego, attach it to an IaC project, and watch it block a non-compliant Terraform deployment before anything reaches your cloud.


Scenario

Your team is deploying S3 buckets but some are being created without server-side encryption. You want to:

  • Write a policy that requires all S3 buckets to have encryption enabled
  • Attach it to your IaC projects
  • Have it automatically block any deployment that violates the rule

Prerequisites

At least one IaC project created in ops0
can_policies IAM permission (admin role has this by default)

Step 1: Create a Policy Group

Policy groups organize related policies and get attached to projects as a unit.

1Click Policies & Compliance in the left sidebar
2Click New Policy Group
3Name it S3 Security Policies
4Set Group Type to IaC
5Click Create Group

Step 2: Write the Policy

1Inside the group, click New Policy
2Fill in the policy details
FieldValue
NameRequire S3 Encryption
DescriptionAll S3 buckets must have server-side encryption enabled
CategorySecurity
SeverityCritical

Policy content (OPA/Rego):

package main

deny[msg] {
  input.resource.type == "aws_s3_bucket"
  not has_encryption(input.resource)
  msg := sprintf(
    "S3 bucket '%v' must have server-side encryption enabled. Add an aws_s3_bucket_server_side_encryption_configuration block.",
    [input.resource.name]
  )
}

has_encryption(resource) {
  resource.values.server_side_encryption_configuration[_].rule[_].apply_server_side_encryption_by_default[_]
}

Click Save Policy.


Step 3: Add the Policy to the Group

1In the group view, click Add Policy
2Select the policy you just created
3Click Add

Step 4: Attach the Group to an IaC Project

1In the group, click Attach to Projects
2Select the IaC project(s) to attach
3Make sure Enabled is toggled on
4Click Save

The policy group is now active on that project. Every future deployment will be checked against it.


Step 5: Trigger a Violation

To see the policy in action, try deploying an S3 bucket without encryption:

# This will be BLOCKED by the policy
resource "aws_s3_bucket" "insecure" {
  bucket = "my-insecure-bucket"
}

Run a Plan on this code. When you try to apply, the policy engine evaluates the plan JSON and returns:

Policy Check: FAILED

  ✗ CRITICAL  Require S3 Encryption
    Resource:    aws_s3_bucket.insecure
    Message:     S3 bucket 'insecure' must have server-side encryption enabled.
                 Add an aws_s3_bucket_server_side_encryption_configuration block.
    Remediation: Add server_side_encryption_configuration block to resource

Deployment BLOCKED — critical violations must be resolved before applying.

The apply does not proceed. Nothing is created in AWS.


Step 6: Fix the Code and Redeploy

Add the encryption configuration:

resource "aws_s3_bucket" "secure" {
  bucket = "my-secure-bucket"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "secure" {
  bucket = aws_s3_bucket.secure.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

Run the plan again. This time the policy check passes and you can apply.


View Compliance Status

Go to Policies & Compliance → Compliance to see:

  • Compliance score across your organization
  • Policy groups and their attachment status
  • Recent violations — which deployments were blocked and why
  • Trend — violation rate over the past 30 days

Violation Severity Behavior

SeverityBehavior
CriticalDeployment blocked — cannot proceed
HighWarning shown — engineer must acknowledge before applying
MediumInfo message logged — deployment continues
LowInfo message logged — deployment continues

Next Steps


Troubleshooting

Policy not triggering on deployments
Verify the policy group is attached to the correct project and the Enabled toggle is on. Policy checks only run on new deployments — they don't retroactively affect past ones.
Rego syntax error on save
ops0 validates Rego syntax on save. Common issues: missing package declaration, incorrect string interpolation with sprintf, or forgetting to import builtins. The error message points to the problematic line.
Policy fires on compliant resources
The Rego rule may be too broad. Test the policy with a sample plan JSON using OPA playground (play.openpolicyagent.org) before attaching it to projects. Check that your has_encryption helper correctly traverses the Terraform plan structure.