Open Policy Agent policies -s3 opa terraform example

The Open Policy Agent (OPA) is an open source high-level declarative language that let’s you specify policy as code and simple APIs to offload policy decision-making from your software. In this article we are going to review s3 opa terraform example

OPA can be used during deployment of your IaC code or CICD pipeline. refer to OPA documentation for more information.

Let’s look into AWS a S3 example and how Open Policy Agent API can help validating infrastructure code before deploying the resources.

Complete terraform code for this project ( S3, RDS policies) can be found on this github project

In this example we will create terraform code for simple S3 bucket and during deploying of the resource , we want to make sure the following requirements are met. you can easily further enhance the validations as per your requirements.

  • Minimum tags are required
  • bucket region should be in eu-central-1 
  • bucket acl property should be private unless it is a website bucket 
  • bucket should be encrypted with AES256/KMS 
  • bucket logging should be enabled 

Terraform S3 code.

resource "aws_kms_key" "mykey" {
   description             = "This key is used to encrypt bucket objects"
   deletion_window_in_days = 10
   tags = {
    Name        = "My KMS Key"
    Environment = "Sandbox"
    Owner       = "Narendra Yala"

resource "aws_s3_bucket" "b" {
  bucket = "my-tf-test-bucket-1234"
  acl    = "private"
  tags = {
    Name        = "My S3 test bucket"
    Environment = "Sandbox"
    Owner       = "Narendra Yala",
    DataType    = "Test files"  
    "app-name"    = "test app"
  logging {
    target_bucket = "my-tf-test-bucket-1"
    target_prefix = "s3logs/us-east-1/"

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        kms_master_key_id = "${aws_kms_key.mykey.arn}"
        sse_algorithm     = "aws:kms"

opa aws example – s3 rego code:

First step is to declare weights, resource type ( that AWS resources we are validating) and minimum tags required & minimum accepted blast radius.

# acceptable score for automated authorization
blast_radius = 5

# weights assigned for each operation on each resource-type
weights = {
    "aws_autoscaling_group": {"delete": 100, "create": 10, "modify": 1},
    "aws_s3_bucket": {"acl": 10, "ssl": 10, "logs": 5, "sse": 10, "tags": 10, "region":10, "logging":10}

# Consider exactly these resource types in calculations
resource_types = {"aws_s3_bucket"}

#at least Name and Environment tags are required.
minimum_tags = {"Name", "Environment"}

Below is the validation methods that parses the tfplan.json output file and validates acl public property requirement against output file.

This method also calculates weight of error and adds to “num” variable. it will be useful if you want to set minimum acceptable score (blast_radius) and compare it with total score and can fail the the deployment if the score is above blast_radius value.

# S3 acl property , bucket ACL can't be public unless its is a website hosting bucket.
s3_acl_change[resource_type] = num {
    some resource_type
    all := resources[resource_type]
    modifies := [res |  res:= all[_]; res.change.after.acl == "public"; != null]
    num := count(modifies)

below code prints validation errors to console using violations = data.terraform.analysis.violation” property, we will look into this command later at the end.

violation["bucket acl property should be private unless it is a website bucket "] {
   s3_acl_change[resource_types[_]] > 0

Setting up opa on windows environment.

  • Download opa.exe file and saves it to C:\tools
  • Go to environent variables and edit Path variables under User Variables.
  • Add C:\tools\ to Path
  • Open windows command prompt and run opa version command to make sure opa is successfully configured.
opa terraform example

These are the Terraform commands to run the opa terraform example code. using the command prompt go to project’s root folder and start executing below opa and terraform commands as needed.

1. terraform init
2. terraform plan --out tfplan.binary
3. terraform show -json tfplan.binary > tfplan.json
# command to find the score 
4. opa eval --format pretty --data s3-validate.rego --input tfplan.json "data.terraform.analysis.score"
# command to find true / false flag.
5. opa eval --format pretty --data s3-validate.rego --input tfplan.json "data.terraform.analysis.authz"
# command to get list of errors, in this scenario you have to provide the rego file name as well
6. opa eval -f pretty --explain=notes  --data rds-validate.rego --input tfplan.json "authorized = data.terraform.analysis.authz; violations = data.terraform.analysis.violation"

Here is an example of violations command result. – command # 6

| authorized | violations |
| false | [“missing required tags”] |

Run command #5 to find the validation result (true / false)

Run command #4 to simply find the validation score.

If you are looking to automate the opa validations as part of your CICD process, look into this article which uses opa s3 , Docker images and Gitlab CICD pipelines.


Leave a Reply

Your email address will not be published. Required fields are marked *