HashiCorp Terraform users who are implementing policy as code with HashiCorp Sentinel have been looking for improved ways to write policies that are broad enough to apply to their entire organizations while also being able to accomodate the detail or needs specific to individual groups within the organization. To help support this need, Sentinel policies now support enforcement decisions based on data from context in which policies are run.

The new tfrun import provides policy authors access to context of the run itself to enforce, or ignore, policy rules based on the environment it’s being evaluated within. Here’s just a few examples of what our customers have asked us to support that is now possible with the latest release:

Tag enforcement

For the sake of consistency and providing a clear audit trail the details of the workspace itself can be enforced upon the resources provisioned within it to make auditability and cost center reporting clearer and consistent for the rest of the organization. In this example the name of the workspace that ultimately provisioned the resources is enforced as a mandatory tag on all resources:

“`
import “tfrun”
import “strings”
import “tfplan”

hasworkspacetag = rule {
all tfplan.resources.aws_instance as _, instances {
all instances as _, instance {
instance.applied.tags contains “workspace” and instance.applied.tags["workspace”] == tfrun.workspace.name
}
}

main = rule {
hasworkspacetag
}
“`

Fine-grained Exceptions

There are occasions where policy maintainers would prefer to skip a policy, or apply only a portion of a policy, based on the workspace evaluating them. In the following example we see how to ensure that our databases are both encrypted at rest and configured with high availability, though we relax the high availability requirement if this is a “dev” workspace (assuming your workspaces are following consistent naming conventions:

“`
import “tfrun”
import “strings”
import “tfplan”

isnotdevelopment = rule {
not strings.has_suffix(tfrun.workspace.name, “-dev”)
}

isencrypted = rule {
all tfplan.resources.aws
dbinstance as _, dbs {
all dbs as _, db {
db.storage
encrypted is true
}
}
}

ishighlyavailable = rule when isnotdevelopment {
all tfplan.resources.awsdbinstance as , dbs {
all dbs as _, db {
db.multi
az is true
}
}
}

main = rule {
isencrypted and ishighly_available
}
“`

In the example above we’ve defined the is_highly_available rule to use the when predicate with our is_not_development rule. This means the content of is_highly_available is only evaluated in the cases where our workspace name does not end with “-dev”. If our workspace name ends with “-dev” then the rule will immediately return true and not actually check if the database is highly available.

Enforcing Cost Controls

It can be difficult to find the right pragmatic balance between allowing teams the agility to provision the infrastructure they need with keeping costs aligned with the expected value of a project. This can then lead to approval workflows that require oversight from an individual or team to determine if changes in cost are reasonable, which in turn can slow delivery and in itself increase the cost of implementation.

A policy as code approach that takes advantage of the cost estimation features of Terraform means organizations can now set guidelines on what is an acceptable change that requires review and then only escalate when a change is in breach of the standard policy. This frees up time in the approval workflow by ensuring time is only spent reviewing genuine escalations, and practitioners responsible for implementation are able to self-service in-policy changes with confidence.

We can implement a policy that limits cost increases with the following:

“`
import “tfrun”
import “decimal”

iswithinbudgetincrease = rule {
decimal.new(tfrun.cost
estimate.deltamonthlycost).less_than(500)
}

main = rule {
iswithinbudget_increase
}
“`

In this example, the tfrun import is used, along with the new decimal import to ensure working with data types that are consistent for dealing with currency. The next part is to access the change in monthly cost that has been estimated for this run ( tfrun.cost_estimate.delta_monthly_cost) and ensure it is less than 500.

By setting the enforcement level on this policy to soft_mandatory we can allow small changes to proceed automatically, while maintaining oversight and an approval workflow for any more expensive changes.

Available now

These examples just scratch the surface of what is possible by using the tfrun data within a policy; a full list of the available attributes is included in the Terraform documentation. These are available to all Terraform Cloud and Terraform Enterprise customers to use within their policies.

We will be expanding the scope of the tfrun import and would love to speak to you if you’ve ideas for additional functionality you’d like to see here.

For more information on Terraform Cloud and Terraform Enterprise or to get started with your free trial, visit the Terraform product page. To learn more about Terraform visit the HashiCorp Learn platform and see it in action.

from Hashicorp Blog