Request access to Scalr IaCP

Open Policy Agent (OPA)

Overview

Policy is one of the most important aspects to scaling cloud adoption. You want to ensure that your users can provision resources as needed and avoid a ticketing/review process that could slow down a deployment process. Adding policy to a pipeline ensures yours users are able to provision resources within a defined set of guardrails reducing security, financial, and operational risk.

Open Policy Agent (OPA) is a code based policy engine allowing users to write policy to check Terraform plans as they come through the Scalr pipeline. OPA is a growing open source community that has already been widely adopted in the Kubernetes community and is the future of policy as code. Scalr guarantees all Terraform plans are checked against OPA policy, in addition to there being different enforcement levels per policy. Scalr also allows for different pipelines/environments/accounts to follow different policies based on customer or business need. A few examples of commonly created policies are:

  • Naming Conventions - Enforce workspace, instance name, and tagging standards.
  • Cost - Avoid unexpected costs.
  • Blast Radius - Avoid changes to critical components (security groups, autoscaling, etc) that could potentially break an application.
  • Compliance Checks - Ensure your deployments following company and compliance standards.
  • Image Selection - Only allow images that have been approved by your organization.
  • And many many more..

The advantage of using policy as code is that there are no limitations to what policies can be created. You do not have to wait on a new release, a feature request, or anything else as you have full control over the types of policies that are written. To learn more about OPA, please visit the following site: Open Policy Agent NEWWIN

OPA policies are stored in VCS repositories and pulled into Scalr, no code is stored directly in Scalr. Learn more about linking with a VCS repository here.

Policy Checking Process

If an OPA policy is created and linked to an environment, this process will be followed:

../_images/policy_diagram.png

At the beginning of the policy stage in the Terraform plan, Scalr prepares all-inclusive input data for policies to evaluate against. It is a JSON object that contains both the Terraform plan and it’s artefacts, as well as the run context data that supports proper policy evaluation.

The JSON has the following structure:

{
   "tfplan": "<terraform plan content>",
   "tfrun": {
       "workspace": {
           "name": "<name>",
           "description": "<description>",
           "auto_apply": false,
           "working_directory": "<working_directory>",
           "tags": {
               "<tag_name>": "<tag_value>"
           },
           "vcs_repo": {
               "identifier": "<org/repo>",
               "display_identifier": "<display_identifier>",
               "branch": "<branch>",
               "ingress_submodules": false
           }
       },
       "cost_estimate": {
           "prior_monthly_cost": 0.0,
           "proposed_monthly_cost": 0.0,
           "delta_monthly_cost": 0.0
       },
       "credentials": {
           "<cloud>": "<cc_id>"
       },
       "source": "<run_source>",
       "created_by": {
           "name": "<name>",
           "full_name": "<full_name>",
           "email": "<email>"
       }
   }
}
  • input.tfplan contains Terraform plan data created with the terraform show -json [planfile] command. It serves as the main input for the OPA evaluation stage.

To learn more about the extent of the tfplan context, please vist the Terraform documentation on this: Terraform JSON Output Format NEWWIN

  • input.tfrun contains a few more keys:

    • Workspace tags

    • Cloud credentials that are linked to the Scalr environments. Cloud names are transformed through mapping to match the ones Terraform is using for providers (“gce” -> “google”, “azure” -> “azurerm”, etc).

    • source: source type of a run. Can have one of the following values:

      • api: The run was kicked off via the Terraform API
      • cli: The run was kicked off via the Terraform CLI
      • configuration-version: The run was kicked off by uploading a new configuration version via the API
      • service-catalog: The run was kicked off by ordering an offering from the service catalog
      • ui: The run was kicked off manually through the UI
      • vcs: The run was kicked off by a merge/commit/pull request webhook from the VCS repository linked to the workspace.
    • created_by: username, full name and email of a user who triggered the run.

    • cost_estimate: this is populated with results of the cost estimate stage of the run.

Creating the OPA Policy

You’ll need to create the OPA policy in a VCS provider, here is example policy name cost-check.rego to deny any deployment that will cost more than $10 per month:

This policy must end with a .rego extension.

package terraform


import input.tfplan as tfplan
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])
}

The policy or policies must then be referenced in a single scalr-policy.hcl file within the same repository, which instructs the Scalr if the policy should be enabled and at what enforcement level. The following enforcement levels are allowed:

  • Hard - The Terraform run is stopped if a violation occurs.
  • Soft - The Terraform run must be approved if a violation occurs.
  • Advisory - A notification occurs if a violation occurs.
version = "v1"

policy "cost-check" {
    enabled = true
    enforcement_level = "hard-mandatory"
}

The syntax for multiple policies in the scalr-module.hcl is as follows:

version = "v1"

policy "cost-check" {
    enabled = true
    enforcement_level = "hard-mandatory"
}

policy "workspace-name" {
    enabled = true
    enforcement_level = "advisory"
}

You should now have two files created:

$ls -1a
.
..
cost-check.rego
scalr-policy.hcl

Push both of these files into the VCS repository and then link them to a Scalr environment in the next section.

Linking the Policy

After creating the policy and linking Scalr to the VCS repository, you can link the policy to an environment . To link the policy in Scalr, you must navigate to the account scope, click on the Scalr icon on the top left, and then “policy engine”:

  • Navigate to the account scope:

    ../_images/acct_level.png
  • Go to the policy engine:

    ../_images/navigate_to_policy.png
  • Click on “new policy group” and select “Open Policy Agent” as the type:

    ../_images/opa_policy.png
  • Click on “new policy”, select VCS repository, and enter in the information for the repository where the OPA policy resides:

    ../_images/opa_vcs.png
  • If everything is setup correctly, the policies will appear with the corresponding enforcement levels:

    ../_images/opa_enforced.png
  • Now that the policy is created, link it to the environment by clicking on “environments”, “policies”, then click on the green link on the right and save:

    ../_images/link_policy.png

Once the policy is applied to the environment you will then see a new tab for it in your runs:

../_images/opa_check.png

OPA Examples

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