Open Policy Agent

Scalr utilizes Open Policy Agent (OPA) to govern Terraform deployments. OPA is policy-as-code that uses the rego language to evaluate Terraform input data against administrator defined rules. Any data which is in the Terraform JSON can be evaluated as part of the OPA checks. The evaluation returns a result which is then interpreted by the Scalr to determine what course of action to take. To be clear, OPA does not make any decisions regarding a policy, it simply returns a result (true, false, some text) which Scalr then uses to make a decision.

The OPA code is treated similarly to your Terraform code in that it is stored in a VCS provider and managed through a GitOps model. Administrators create, manage, and open pull requests on the policies directly in VCS providers as well as trigger speculative runs to preview the impact of policy changes.

There are two main sections that the policies can evaluate, the tfplan and tfrun. The Terraform input data will be the output of terraform plan (tfplan in rego) and the run time (tfrun in rego) environment data, such as workspace details, username, etc. From this data, OPA can be used to evaluate the attributes of all Terraform providers, resources, data, and anything mentioned in the plan.

Example data - tfplan

The tfplan data is the output from terraform plan in JSON format. There are multiple sections to the plan data to enable checks on planned_values, resource_changes, configuration etc. OPA policies will most often use resource_changes to evaluate changes to attribute values. The structure of tfplan, with details omitted, is shown below.

   "tfplan": {
       "format_version": "0.1",
       "terraform_version": "0.13.4",
       "variables": {

       "planned_values": {

       "resource_changes": [

       "output_changes": {

       "configuration": {

   "tfrun": {

A more complete example of the tfplan data, with an example policy, can be viewed here: tfplan example data.

Example data - tfrun

The tfrun data can be evaluated by OPA to check on data related to the run time environment in Scalr, such as user names, VCS provider details, cloud credentials, cost estimation, and more. The structure of tfrun, with details omitted, is shown below.

 "tfplan": "<terraform plan content>",
 "tfrun": {
   "workspace": {

   "vcs": {

   "cost_estimate": {

   "credentials": {

   "source": "ui",
   "message": "Update",
   "is_destroy": false,
   "is_dry": false,
   "created_by": {


A more complete example of the tfrun data, with an example policy, can be viewed here: tfrun example data.

Using OPA in Scalr

OPA policies are stored in a VCS repository and registered in Scalr as policy groups. The VCS repository contains one or more policy rego files and a scalr-policy.hcl file that sets the enforcement level of each policy:

  • Hard Mandatory - Cannot be overridden
  • Soft Mandatory - Can be overridden by account admins and other authorized roles
  • Advisory - Provides a warning only

Once the policy groups are created, the groups are linked to specific environments to enforce the policies in those environments. The policies are evaluated against every run in every workspace in the linked environments.

Scalr requires that the OPA evaluation returns an array of strings named deny. The presence of any values in the array will be interpreted by Scalr as a policy failure. Thus, in policies used with Scalr there must always be a rule named deny that performs the evaluation. Here is a very simple example that checks the cost of the resources in a Terraform run using the cost estimation data:

package terraform

import input.tfrun as tfrun

deny[reason] {
    cost_delta = tfrun.cost_estimate.delta_monthly_cost
    cost_delta > 10
    reason := sprintf("Plan is too expensive: $%.2f, while up to $10 is allowed", [cost_delta])

An evaluation that detects the cost to be higher than $10 would return a result like this:

  "deny": [
    "Plan is too expensive: $12.00, while up to $10 is allowed"

Creating Policy Groups

A policy group is the collection of one or more OPA policies stored in a repository with a scalr-policy.hcl file declaring if the policies are enabled and what the enforcement level is. One or more policies can be attached to each environment and it is normal to have a common policy shared across all environments as well as environment-specific policies to ease overhead. Common shared policies could include restricting network access, preventing public S3 buckets, allowing specific Terraform modules, and much more. Follow these steps to create a policy group:

  1. Create policy rego files in a VCS repo:
  1. Add a scalr-policy.hcl file to set the enforcement levels and if the policy is enabled or not for each policy file in the repo, as shown in this example. Note the version is required:
version = "v1"

policy "limit_modules" {
    enabled = true
    enforcement_level = "advisory"

policy "workspace_name_convention" {
    enabled = true
    enforcement_level = "advisory"
  1. Create the policy group in Scalr at the account level. To use policy groups it is necessary to create a VCS provider if this has not already been done.
  • Go to the "run policy engine" at the account scope and create a run policy group:
  • Create a new policy group with the VCS details:

Once saved, the policy can be enforced on environments by clicking on "Enforce run policy group":


Policy reports will appears within a few seconds (maybe longer depending on the amount of workspaces) once the policy is enforced.

Policy Reports

Once a policy is created and enforced, it will automatically start checking runs, but from an administrative perspective, you likely want to see the status of the policies across all environments and workspaces. Policy checks give you a single view of the current results of policies across all environments and workspaces. To view this click on “Policy Reports”:


By clicking on the colored summary bar, you will redirected to a detailed and filterable list of all the policies with the results.


Policy Impact Analysis

Scalr provides an impact analysis of future policy changes based on pull requests against the repository linked to the policy. This tells a policy owner if they made an error updating the policy or if there are workspaces that will violate the upcoming policy change and gives them time to contact the workspace owner prior to merging. The results of the analysis are also pushed back to the VCS provider to allow for a GitOps model when managing policies. The analysis does not cause current runs to fail. To create the analysis, create a pull request against the main branch and the reports will start to auto-generate.

Viewing Previews on Workspaces

When a pull request is opened on an existing policy, Scalr will automatically check all existing workspaces for violations and report back after a few minutes. The time will vary depending on the size of the environment it is evaluating:


Clicking on the policy check section will provide details of exactly what has failed, where the workspace is, and who owns it:


This will help the administrator understand the blast radius that the policy could potentially have prior to merging it to main.

Viewing Previews on New Runs

Once the pull request is made, it will be displayed on the policy group screen:


The preview mode can be turned on and off as needed:


In the next run, the workspace owner will see the implemented policy vs the preview policy:


Once the pull request is merged with main, the preview will disappear and the new policy will be applied to all runs.

More Ressources

For examples of OPA policies, please visit our GitHub repository: Open Policy Agent Examples

To learn more about using the terraform plan data with OPA please review our Scalr OPA Blog series, in particular OPA Series Part 3: How to analyze the JSON plan.

To learn more about writing OPA policies for Terraform and Scalr we recommend the following resources:


More of a visual learner? Check out this feature on YouTube.