When writing a Sentinel policy, you can validate your policy's restrictions against Sentinel imports, which access mock data. Sentinel can use several types of imports from the HCP Terraform API: configuration, plan, state, and run.
Note
HCP Terraform Free Edition includes one policy set of up to five policies. In HCP Terraform Plus Edition, you can connect a policy set to a version control repository or create policy set versions via the API. Refer to HCP Terraform pricing for details.
In this tutorial, you will review a Sentinel policy and test it in the Sentinel CLI using pre-generated mock import data. The example policy enforces EC2 instance type and tag restrictions.
For this tutorial, you will need:
In your terminal, clone the example code repository. This repository contains an example Sentinel policy and a tfplan/v2
Sentinel mock import.
$ git clone https://github.com/hashicorp-education/learn-sentinel-write-policy
Navigate to the directory.
$ cd learn-sentinel-write-policy
You will use the tfplan/v2
import type to test your policy. This import type provides access to Terraform plan data, which represents the changes that Terraform needs to make to infrastructure to match the written configuration. The tfplan
import lets you determine if the proposed changes satisfy your policy criteria.
Open the file named mock-tfplan-v2.sentinel
in your text editor. Find the resource_changes
collection. This Terraform data is a key/value collection for all of the proposed resource changes required by your configuration. The data below is truncated, but your file should contain this collection with these values.
mock-tfplan-v2.sentinel
terraform_version = "1.0.1"
## ...
resource_changes = {
"aws_instance.ubuntu": {
"address": "aws_instance.ubuntu",
"change": {
"actions": [
"create",
],
"after": {
"ami": "ami-0fb1e27304d83032f",
"credit_specification": [],
"disable_api_termination": null,
"ebs_optimized": null,
"get_password_data": false,
"hibernation": null,
"iam_instance_profile": null,
"instance_initiated_shutdown_behavior": null,
"instance_type": "t2.micro",
"monitoring": null,
"source_dest_check": true,
"tags": {
"Name": "Provisioned by Terraform",
},
"timeouts": null,
"user_data": null,
"user_data_base64": null,
"volume_tags": null,
},
## ...
},
"deposed": "",
"index": null,
"mode": "managed",
"module_address": "",
"name": "ubuntu",
"provider_name": "registry.terraform.io/hashicorp/aws",
"type": "aws_instance",
},
## ...
}
Terraform captures the attributes of any created or modified resource in the plan. You can use this data in your Sentinel policies to verify that the policy appropriately restricts resources or attributes.
When testing a policy, select the appropriate import for your policy's restrictions. For example, you can use a tfrun
import to test a policy that restricts resources based on cost estimation. You can use a tfconfig/v2
import to test a policy that limits the number of providers to use in configuration.
Now open the sentinel.hcl
file and review the configuration.
mock "tfplan/v2" {
module {
source = "mock-tfplan-v2.sentinel"
}
}
This defines a new mock named tfplan/v2
containing the data from the mock-tfplan-v2.sentinel
file. Your Sentinel policy will import this mock to test the policy.
Sentinel tests your requirements against your imported data, resulting in a Pass
or Fail
. When writing policies, you can use variables to store values and operators to compare logical expressions.
Open the restrict-aws-instances-type-and-tag.sentinel
file, which contains the Sentinel policy.
This Sentinel policy enforces the following infrastructure requirements:
Name
tag.t2.micro
, t2.small
, or t2.medium
.If your EC2 instances do not meet all of these criteria, Sentinel will flag the run with a FAIL
.
restrict-aws-instances-type-and-tag.sentinel
# Imports mock data
import "tfplan/v2" as tfplan
# Get all AWS instances from all modules
ec2_instances = filter tfplan.resource_changes as _, rc {
rc.type is "aws_instance" and
(rc.change.actions contains "create" or rc.change.actions is ["update"])
}
# Mandatory Instance Tags
mandatory_tags = [
"Name",
]
# Allowed Types
allowed_types = [
"t2.micro",
"t2.small",
"t2.medium",
]
# Rule to enforce "Name" tag on all instances
mandatory_instance_tags = rule {
all ec2_instances as _, instance {
all mandatory_tags as mt {
instance.change.after.tags contains mt
}
}
}
# Rule to restrict instance types
instance_type_allowed = rule {
all ec2_instances as _, instance {
instance.change.after.instance_type in allowed_types
}
}
# Main rule that requires other rules to be true
main = rule {
(instance_type_allowed and mandatory_instance_tags) else true
}
This Sentinel policy can be divided into seven sections.
The import
statement imports the mock data, defined in sentinel.hcl
. This mock data simulates a Terraform plan that provisions an EC2 instance.
The ec2_instances
variable filters the mock data for EC2 instances that the plan will create or modify.
Sentinel determines the specific resources or data to evaluate from the import based on a filter expression
. In the above policy, ec2_instances
uses a filter
expression. The expression returns a map of tfplan.resource_changes
: a selector that searches the tfplan
data collection for a field called resource_changes
for EC2 instances created or updated in the plan data.
The mandatory_tags
variable contains the list of required tags.
The allowed_types
variable contains the list of permitted EC2 instances types.
The mandatory_instance_tags
rule ensures that EC2 instances have a Name
tag. The rule loops through the filtered ec2_instances
and verifies that all EC2 instances have the tags defined in the mandatory_tags
variable.
Tip
You can open mock-tfplan-v2.sentinel
and verify that instance.change.after.tags
contains the Name
tag. This allows you to determine which attributes are available for testing. Notice that instance
corresponds to each item in the filtered ec2_instances
variable.
mock-tfplan-v2.sentinel
resource_changes = {
"aws_instance.ubuntu": {
"address": "aws_instance.ubuntu",
"change": {
## ...
"after": {
## ..
"tags": {
"Name": "Provisioned by Terraform",
},
## ..
}
## ...
},
## ...
},
}
The instance_type_allowed
rule ensures that EC2 instances are t2.micro
, t2.small
, or t2.medium
. The rule loops through the filtered ec2_instances
and checks whether the instance's instance_type
is in
the allowed_types
.
The main
rule evaluates both the mandatory_instance_tags
and instance_type_allowed
rules. If both are true, Sentinel allows the policy to pass. The Sentinel policy divides rules this way to keep the main rule short and allows you to evaluate your policy based on multiple rule criteria.
Now, use the apply
command to test your policy against the mock data and ensure your policy performs as expected.
$ sentinel apply restrict-aws-instances-type-and-tag.sentinel
Pass - restrict-aws-instances-type-and-tag.sentinel
The execution passed because the infrastructure changes in your plan data satisfy your policy criteria.
You reviewed the parts of a Sentinel policy and used mock data to validate a policy. To learn more about Sentinel, review the following resources:
import
types.RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4