Scan Terraform with OPA
Tags: opa, iac, terraform, compliance
Published: 2022-06-02 13:42:45

Recently, I started working on compliance projects, and it became necessity to discover any tool which can show the written IAC Terraform code is compliant to certain standards such as CIS, SOC2 etc. And There I got introduced to regula, and my journey started in the world of compliance.

In this blog will take about with is Open agent policy ? What is Rego? And how they can be used with regula to generate report.

**What is OPA?**
The Open Policy Agent (OPA, pronounced “oh-pa”) is an open source, general-purpose policy engine that unifies policy enforcement across the stack.OPA provides a high-level declarative language that lets you specify policy as code and simple APIs to offload policy decision-making from your software. You can use OPA to enforce policies in microservices, Kubernetes, CI/CD pipelines, API gateways, and more.

To understand this better, we need to understand rego.

**Introduction to Rego**
Rego was inspired by Datalog, which is a well understood, decades old query language. Rego extends Datalog to support structured document models such as JSON.

Rego queries are assertions on data stored in OPA. These queries can be used to define policies that enumerate instances of data that violate the expected state of the system.

**Why use rego**

- 1. Easy to read and write.
- 2. Powerful support for referencing nested document
- 3. declarative

**Regula**
Regula is a tool that evaluates infrastructure as code files for potential AWS, Azure, Google Cloud, and Kubernetes security and compliance violations prior to deployment.

Regula supports the following file types:

CloudFormation JSON/YAML templates
Terraform HCL code
Terraform JSON plans
Kubernetes YAML manifests
Azure Resource Manager (ARM) JSON templates (in preview)
Install regula

Download the Regula archive for your platform from the Releases page.
Extract the downloaded archive.
Move the extracted regula binary to somewhere in your PATH:
Also, one can use` Homebrew`
**Mac:**
```
#brew install regula
```
**Linux:**
```
#sudo mv regula /usr/local/bin
OR
#brew install regula
```
**Windows cmd:**
```
md C:\regula\bin 
move regula.exe C:\regula\bin 
setx PATH "%PATH%;C:\regula\bin"
```
Now, let’s jump into the main scenario of this blog. In today’s world, we are using IAC to write and deploy our IAC to cloud environment. But, for most of the cases we need to check whether our code is compliant and has all parameters secured before deploying over cloud, here comes OPA to help.

Let write some terraform script. Here, we are creating AWS ec2 instance with certain details.
```
resource "aws_instance" "instance" {
  ami                         = "ami-0ddb956ac6be95761"
  instance_type               = "t2.small"
  key_name                    = "key-pair-name"
  vpc_security_group_ids      = "sg-name
  subnet_id                   = "subnet-xxxxxxx"
  associate_public_ip_address = true

  root_block_device {
    volume_size           = 50
    delete_on_termination = true
  }

  tags = {
    Name = "demo-server"
  }
}
```
Let, compare above terraform code with OPA rule, to write a rule we need to define a rule with file extension rego

```
package rules.tf_aws_ec2_instance_no_public_ip

__rego__metadoc__ := {
   "id": "POLICY_ID01",
   "title": "Ensure instance have no public IP associated",
   "description": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
   "custom": {"severity": "Low"},
}

resource_type := "aws_instance"

default allow = false

allow {
   input.associate_public_ip_address == false
}
```
let’s go through the above rule,

package :- Packages group the rules defined in one or more modules into a particular namespace. Because rules are name-spaced, they can be safely shared across projects.
rego__metadoc :- It enhances rule or policy reporting, with details like id , title description custom severity etc. refer.
resource_type :- the resource you are looking at in terraform.
Above rule will check if associate_public_ip_address is set to false is so, Then it will all the scan to pass. If not, it will prompt an error like below.

Run regula command against the main.tf file.
```
#regula run main.tf
POLICY_ID01: Ensure instance have no public IP associated [Low]
[1]: aws_instance.demo_instance
       in main.tf:1:1
```
If required, you can get this output in JSON format as well.
```
#regula run main.tf -f json
"rule_id": "POLICY_ID01",
      "rule_message": "",
      "rule_name": "tf_aws_ec2_instance_no_public_ip",
      "rule_raw_result": false,
      "rule_result": "FAIL",
      "rule_severity": "Low",
      "rule_summary": "Ensure instance have no public IP associated",
      "source_location": [
        {
          "path": "main.tf",
          "line": 1,
          "column": 1
        }
      ]
    },
```
You can also run regula with tf_plan file. For that, we need to run plan and exact plan output file.
```
#terraform plan -out="plan.tfplan"
#terraform show -json plan.tfplan > plan.json
```
once you have plan.json a file in JSON format, you can compare it with regula. The output will be the same.

```
#regula run plan.json
```
## Conclusion

It is very important to use IAC to make your deployment faster and robust. But, at the same time it’s also import to check whether it's compliant with standards or not and OPA is a good solution to help you get compliant & and one can mold it as per their use case.

## Reference
OPA — https://www.openpolicyagent.org/docs/latest/
regula — https://regula.dev/