Search code examples
amazon-s3terraformopen-policy-agentrego

OPA eval command


I am very new to OPA but testing something very simple. I would like to create a policy to ensure my s3 is not public.

my simple TF file:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "4.64.0"
    }
  }
}

provider "aws" {}

resource "aws_s3_bucket" "test" {
  bucket = "test"
  # acl    = "private"
  acl = "public-read"

  tags = {
    Name = "test"
  }
}

My rego file, got it from https://github.com/Scalr/sample-tf-opa-policies/blob/master/aws/enforce_s3_private.rego

# Check S3 bucket is not public

package terraform

import input.tfplan as tfplan

deny[reason] {
    r = tfplan.resource_changes[_]
    r.mode == "managed"
    r.type == "aws_s3_bucket"
    r.change.after.acl == "public"

    reason := sprintf("%-40s :: S3 buckets must not be PUBLIC", 
                        [r.address])
}

MY TF commands to get the plan and json to test the rego policy:

terraform init
terraform plan --out -no-color tfplan.output
terraform show -json tfplan.output | jq ".resource_changes | map ({(.type|tostring) : .}) | add" > tfplan.json

Now I would like to test my rego policy and bumping here as the terminal hangs. I don't know if I am using the right command or if my rego policy is missing something:

opa eval --data s3-validate.rego --input tfplan.json --stdin 

I would appreciate some help.


Solution

  • I have made a simplified example here based on your example. The input file doesnt really matter in this example.

    package terraform
    
    import input.tfplan as tfplan
    
    deny[reason] {
        r = [{"name": "foo", "a": 1}, {"name": "bar", "a": 2}][_]
        r.a > 1
        reason := sprintf("%-40s :: S3 buckets must not be PUBLIC",
                            [r.name])
    }
    

    In this example I have two results and I want to capture any that have the attribute greater than 1.

    Now your question you have stated eval. This is used when you want to evaluate things. So we can do that with

    
    $ opa eval --data example.rego --input input.json "data.terraform.deny"
    {
      "result": [
        {
          "expressions": [
            {
              "value": [
                "bar                                      :: S3 buckets must not be PUBLIC"
              ],
              "text": "data.terraform.deny",
              "location": {
                "row": 1,
                "col": 1
              }
            }
          ]
        }
      ]
    }
    

    However generally when running policy you would want to use exec

    
    $ opa exec --bundle . --decision "terraform/deny" input.json
    {
      "result": [
        {
          "path": "input.json",
          "result": [
            "bar                                      :: S3 buckets must not be PUBLIC"
          ]
        }
      ]
    }
    

    Since I am not sure what your intention is here I have listed both. You can read more on terraform examples https://www.openpolicyagent.org/docs/latest/terraform/#4-evaluate-the-opa-policy-on-the-terraform-plan