Approval Policies

Overview

env0 enables applying approval policies for the environments managed using the app.

env0 uses the Open Policy Agent engine for enforcing policies when an environment is deployed.

Open Policy Agent uses rego files to define the required policies. env0 expects the user's files to be within a repository, not necessarily the deployed environment repository.

During the deployment, after the plan and cost estimation steps, a step for policy approval will be run, and the deployment may continue, wait for further approval, or get canceled, according to the output of previous steps and other data such as the type of deployment, users involved, or IaC.

Enable approval policies step

Template approval policies

You can assign multiple approval policies to a single template. In the template settings page, under the advanced section, click the + Add Approval Policy button:

Environments that will be deployed from templates with approval policies, will have their Approve plan automatically checkbox disabled.

Project approval policies

You can assign multiple approval policies to a single project. Those approval policies will be inherited by sub projects.

In the project settings page, go to the POLICIES tab and click the + Add Approval Policy button:

Environments that will be deployed in projects with approval policies or projects with parent projects that have approval policies assigned, will have their Approve plan automatically checkbox disabled. In those cases, the Approve plans automatically for new environments checkbox in project policies settings page will also be disabled.

Repository Configuration

Configure the repository for the repository that contains the rego files for the desired policy. If the files are located within a directory, specify the folder path too.

All the environments under the project will have a deployment step for validating that the plan isn't violating the chosen policy.

📘

Actions that enforce policies

Policies are enforced only when an environment is about to get deployed or destroyed. Tasks, PR plans and other actions are not enforcing policies.

Input by env0

The input env0 generates based on the deployment is of the following structure:

{
  deploymentRequest: {
    type: string;
    triggerName: string;
    revision: string;
  };
  template: {
    type: string;
    repository: string;
  	path: string;
  	revision: string;
  	id: string;
  	name: string;
  };
  costEstimation: {
    totalMonthlyCost: number;
    monthlyCostDiff: number;
  };
  plan: object;
  deployerUser: {
 	  name: string;
    email: string;
    teams: {id: string; name: string;}[]
  };
  approvers: {
 	  name: string;
    email: string;
    teams: {id: string; name: string;}[]
  }[];
  variables: {
    environment: Record<string, string>;
    terraform: Record<string, string>;
    env0: Record<string, string>;
  };
  policyData: any
}
  • deploymentRequest:
    • type: The action that caused the deployment. Can be deploy, destroy, deployResume or destroyResume
    • triggerName: The trigger for the deployment. Can be cd, user, ttl, scheduled, workflow or comment
    • revision: The revision that this specific deployment uses to clone the data from. May be missing if no revision is stated for the deployment or as a default for the template.
  • template
    • id: The template's unique id.
    • name: The template's name.
    • type: The type of the template, i.e. what IaC tool is used to deploy the resources. The value can be one of the following: opentofu - terraform - terragrunt - pulumi - cloudformation - k8s - helm
    • repository: The repository URL of the template.
    • path: The path within the repository to the relevant files.
    • revision: The revision that the repository's code will be cloned from. It may be missing if no revision is set for the template.
  • costEstimation: An object that describes the projected changes in the cost once the changes are approved. Cost estimation must be enabled and the template type supported to have correct values.
  • plan: An object representing the speculated changes that the deployment will cause once approved. Contents are in the same format as the content of the plan phase during the deployment run. note: plan is only supported in OpenTofu, Terraform and Terragrunt environments.
  • deployerUser: An object containing the name, email and teams of the user that created the environment and made the first deployment
  • approvers: An array of users and their teams that approved the changes to the environment
  • variables: The variables used by deployment, divided by type. (e.g. variables.environment.MY_VAR_1
    • .env0 will contain the environment variables automatically added by env0. Listed in Custom Flows.
  • policyData: Any custom data provided by the user (see Adding custom data)

🚧

Supported IaC Frameworks

Currently, only on Terraform and Pulumi deployments we will populate the plan field.

For Pulumi, using version greater than 3.105.0 is required. For deployments of type 'deploy', the plan format is as described here, for 'destroy', the format is the same as the output of pulumi destroy --preview-only --json.

For other IaC tools the object will be empty, and only the other fields should be used.

Adding custom data to the policy input

Additional input can be provided by the user, by supplying the ENV0_POLICY_DATA_PATH environment variable with the path to a JSON file.

  • The file can be in the cloned repository, or created dynamically by a custom flow.
  • The contents of the JSON file will be available in the input under the key policyData.
  • In case there is an error reading the file, the policyData will be undefined

Expected rules format

📘

Rego Files

Your Rego files should be under the env0 package. In addition, Please make sure that your rego files are using "package env0" in order for approval flow to work correctly.

The approval flow expects at least one of these options in the output for the Open Policy Agent If several options are received, the strictest will take place

  • deny: The deployment will be cancelled.

  • pending: The deployment will stop and wait for user approval.

  • warn: The deployment will continue with a warning.

  • allow: The deployment will continue.

    If no rules are met, the default behavior is pending.

When handling multiple approval policies, we will still use the same logic, if one approval policy outputs deny and another outputs pending, the deny will take place and we will cancel the deployment.

Examples

Policies

There are many cases where approval policies may be useful:

  • Requiring more than a certain threshold of approvers
  • Deny any change that its expected cost cross a predefined limit
  • Prevent removing critical resources from an environment
  • Allowing only a sub-set of users to change specific resources within an environment

And the list can go on and on.

Examples may be found in our GitHub repository

Full input example

Env0 will print the full input to the approval flow logs by using ENV0_PRINT_POLICY_INPUT=true environment variable.

{
  "deploymentRequest": {
    "type": "deploy",
    "triggerName": "user",
    "revision": "null-module"
  },
  "template": {
    "id": "some id",
    "name": "template name",
    "type": "terraform",
    "repository": "https://github.com/env0/templates",
    "path": "misc/null-resource",
    "revision": "master"
  },
  "costEstimation": {
    "totalMonthlyCost": 0,
    "monthlyCostDiff": 0
  },
  "plan": {
    ...{ /* OpenTofu/Terraform https://opentofu.org/docs/internals/json-format/#plan-representation */ },
    ...{ /* CloudFormation
             Deploy - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeChangeSet.html
             Destroy - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ListStackResources.html 
         */ 
    },
  },
  "deployerUser": {
    "name": "deployer user",
    "email": "[email protected]",
    "teams": [{"id": "teamId", "name": "deployers team"}]
  },
  "approvers": [
    {
      "name": "Other User",
      "email": "[email protected]",
      "teams": [{"id": "approversTeamId", "name": "approvers team"},
                {"id": "securityTeamId", "name": "security team"}]
    }
  ]
}

Deployment Pending Approval

Here the user's deployment stopped as the Open Policy Agent evaluated one of the rules as pending. Once the deployment is approved twice, this step will be passed and the apply step can start.

🚧

Changing policy during a deployment

Note that changing or removing a policy during a deployment (for example while it's pending approval) is not supported and might result in an error. In such a case, you should cancel the deployment and re-deploy the environment.

📘

Using a specific OPA version

You can choose a specific OPA version to use with the ENV0_OPA_VERSION variable.