terraform

Expanding the tfrun import for Sentinel in Terraform Enterprise and Cloud

Last November we announced the release of the tfrun import for Sentinel in Terraform Enterprise and Cloud. The release of the new tfrun import provided customers with an improved policy authoring workflow and the flexibility to author policies that could be applied to an entire organization and reduce the need for policy duplication. Since then we have had a steady flow of feedback from customers covering different use cases that prompted us to extend the list of attributes exposed by the tfrun import.

As an example, the newly expanded tfrun import now provides policy authors with context related to the name of the Terraform Cloud organization, the date and time a run was created, the message that was provided as part of the run, as well as many other attributes.

The following diagram contains all newly exposed attributes:

tfrun
├── created_at (string)
├── message (string)
├── speculative (boolean)
├── is_destroy (boolean)
├── variables (map of keys)
├── organization
│   └── name (string)
├── workspace
│   ├── name (string)
│   ├── description (string)
│   ├── auto_apply (bool)
│   ├── working_directory (string)
│   └── vcs_repo (map of keys)
└── cost_estimate
    ├── prior_monthly_cost (string)
    ├── proposed_monthly_cost (string)
    └── delta_monthly_cost (string)

Here are some of the use cases that our customers have asked us to support in the tfrun import:

»Maintenance Window Enforcement

In most enterprise organizations it is common practice to designate a routine maintenance window to allow technical staff to perform preventive maintenance that may cause disruption of service. In this example, we are using the time import to load the timespace of the Terraform Run, and use the weekday_name method to determine if the change will be performed on a day that has been designated for routine maintenance. The values of the maintenance_days are provided using a Sentinel parameter:

import "tfrun"
import "time"

param maintenance_days default ["Friday", "Saturday", "Sunday"]

tfrun_created_at = time.load(tfrun.created_at)

supported_maintenance_day = rule { 
    tfrun_created_at.weekday_name in maintenance_days
}

main = rule {
    supported_maintenance_day
}

Note: The above is a pretty extreme example and only really applies to environments that require really high levels of service availability. You could also use the time import to restrict maintenance between 6 PM and 6 AM etc. For more information, refer to the time import documentation.

»Policy Evaluation by Organization Name

Customers sometimes have a need to maintain a single source of policies, but need the flexibility to apply them to Terraform organizations in different ways. As an example, one may wish to apply all policy rules in production but may not wish to do so in a development environment.

Building on the previous example let's take a look at how this can be achieved using the when predicate on the supported_maintenance_day. As you can see in the example below we are using a rule expression to evaluate the value of tfrun_organization_name. If the value is "hashicorp" then the Sentinel rule is evaluated.

import "tfrun"
import "time"

param maintenance_days default ["Friday", "Saturday", "Sunday"]

tfrun_created_at = time.load(tfrun.created_at)
tfrun_organization_name = tfrun.organization.name

supported_maintenance_day = rule when tfrun_organization_name is "hashicorp" { 
    tfrun_created_at.weekday_name in maintenance_days
}

main = rule {
    supported_maintenance_day
}

Note: We could also use the contains or matches operators to check for the existence of a string value. For instance, if the organization name is “hashicorp-staging”, we could check for “staging” as follows:

supported_maintenance_day = rule when tfrun_organization_name contains "staging" { 
    tfrun_created_at.weekday_name in maintenance_days
} 

»Prevent Outputs from Disclosing Sensitive Values

Many organizations use Terraform to manage their infrastructure, and therefore it’s guaranteed that customers will be using sensitive information within the provisioning workflow. Terraform often requires privileged access credentials as well as other sensitive information to perform its function. This information is usually provided to Terraform as an input variable. The way we protect this data in Terraform Cloud is usually by marking certain input variables as sensitive and by letting the platform take care of storing and encrypting the data.

With the new changes we have made to the tfrun import, you can now take advantage of the variables attribute to prevent unintentional data disclosure via output values. In the example below, we are using the sensitive flag of all user-defined variables to determine whether Terraform is allowed to expose sensitive information using a Terraform output value.

import "tfrun"
import "tfconfig"
import "strings"

sensitive_tfrun_variables = filter tfrun.variables as var, value { value.sensitive is true }
print(keys(sensitive_tfrun_variables))

get_output_references = func() {
    output_references = []

    for values(tfconfig.outputs) as output {
        references = filter output.references as value { value contains "var" }

        for references as reference {
            append(output_references, strings.split(reference, ".")[-1])
        }
    }
    return output_references
}

check_output_variables_by_sensitivity = func(output_variables) {
    result = false
  for output_variables as output_variable {
        if output_variable in keys(sensitive_tfrun_variables) {
            print(
                "Variable",
                output_variable,
                "is configured as a sensitive variable and cannot be exposed as a Terraform output")
            return result
        } else {
            result = true
        }
    }
    return result
}

deny_secure_output_variables = rule {
    check_output_variables_by_sensitivity(get_output_references())
}

main = rule {
    deny_secure_output_variables
}

»Available Now

These examples are only scratching the surface of what can be achieved by using the Sentinel tfrun import within Sentinel policies. A full list of the available attributes is included in the tfrun import documentation. These new attributes are available to all Terraform Cloud and Terraform Enterprise customers to use within their policies.

If you have any thoughts on how we can further expand the tfrun import or any Sentinel import for that matter, please get in touch as we are always interested in hearing from you and uncovering new use cases.

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.

Sign up for the latest HashiCorp news

By submitting this form, you acknowledge and agree that HashiCorp will process your personal information in accordance with the Privacy Policy.