Test Sentinel policies
You can test your Sentinel policies using the built-in testing suite to check your policies against all scenarios and edge cases. Testing gives you confidence in your policy and ensures predictable run outcomes when HCP Terraform enforces your policies during Terraform operations.
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.
Prerequisites
For this tutorial, you will need:
Clone example Terraform configuration
In your terminal, clone the example code repository. This repository contains an example Sentinel policy and mock data.
$ git clone https://github.com/hashicorp/learn-sentinel-write-policy
Navigate to the directory.
$ cd learn-sentinel-write-policy
Review Sentinel policy
Tip
To review the policy used in this tutorial and how to use Sentinel mock data when writing Sentinel policies in more detail, review the Write a Sentinel Policy for a Terraform Deployment tutorial.
Open the restrict-aws-instances-type-and-tag.sentinel
file, which contains
the Sentinel policy.
This Sentinel policy defines a main
rule that consists of two other rules defining infrastructure requirements:
- The
mandatory_instance_tags
rule checks that all EC2 instances have aName
tag. - The
instance_types_allowed
rule checks that EC2 instances are of typet2.micro
,t2.small
, ort2.medium
.
If your new or modified EC2 instances do not meet all of these criteria, Sentinel will flag the
run with a FAIL
.
Create passing mock data
The configuration in this repository contains pre-generated Sentinel mock data from a Terraform plan run that satisfies the policy defined. You will use this data as the base for your passing and failing Sentinel test cases.
Copy your known passing mock data to a new file with pass
in the filename.
$ cp mock-tfplan-v2.sentinel mock-tfplan-pass-v2.sentinel
Tip
If you are writing your policy against infrastructure that already exists, that infrastructure may not actually comply with your policy. Run sentinel apply <policy_name>
in your local CLI on unedited import data to identify failing data, and edit the data to create your passing test mock..
Write a passing test case
Sentinel requires that your folder structure
match test/<policy>/*.json
, where <policy>
is the name of your policy file
without the file extension.
Create a new folder named test
with a subdirectory named
restrict-aws-instances-type-and-tag
.
$ mkdir -p test/restrict-aws-instances-type-and-tag
Navigate to the subdirectory.
$ cd test/restrict-aws-instances-type-and-tag
Create a new file named pass.hcl
, then add the following configuration to the
file.
pass.hcl
mock "tfplan/v2" { module { source = "../../mock-tfplan-pass-v2.sentinel" }} test { rules = { main = true }}
This passing test case uses the passing mock data and expects both the
instance_type_allowed
and mandatory_instance_tags
rules to pass.
Create failing mock data
To write a failing test case, you need to create a mock import data file with values outside your criteria, to simulate infrastructure that does not comply with the policy.
Change into your root learn-sentinel-write-policy
directory.
$ cd ../..
Copy the mock-tfplan-v2.sentinel
file to a new file with "fail" in the filename.
$ cp mock-tfplan-v2.sentinel mock-tfplan-fail-v2.sentinel
Open the failing mock data file in your text editor and look for the
resource_changes
collection.
Tip
Open the failing mock data file in a visual editor like VSCode and hide the first collection in the file called planned_values
to find your resource_changes
quickly.
In the resource_changes.aws_instance.ubuntu.change.after
block, change:
instance_type
tot2.large
, andtags
fromName
toNumber
.
resource_changes = { "aws_instance.ubuntu": { "address": "aws_instance.ubuntu", "change": { "actions": [ "create", ], "after": { ## ...- "instance_type": "t2.micro",+ "instance_type": "t2.large", ## ... "tags": {- "Name": "Provisioned by Terraform",+ "Number": "Provisioned by Terraform", }, ## ... }, } }}
Write a failing test case
Change back into your test/restrict-aws-instances-type-and-tag
directory.
$ cd test/restrict-aws-instances-type-and-tag
Create a new file named fail.hcl
, then add the following configuration to the file.
This configuration references the failing mock data and asserts that it should fail the policy.
fail.hcl
mock "tfplan/v2" { module { source = "../../mock-tfplan-fail-v2.sentinel" }} test { rules = { main = false }}
Test your policy in the Sentinel CLI
Change into your root learn-sentinel-policies
directory.
$ cd ../..
Now use the test
command to run the test cases you defined for your policy.
Sentinel automatically loads the test cases in the /test
directory and passes the
subdirectory that matches the policy name to the test
command.
$ sentinel test restrict-aws-instances-type-and-tag.sentinelPASS - restrict-aws-instances-type-and-tag.sentinel PASS - test/restrict-aws-instances-type-and-tag/fail.hcl PASS - test/restrict-aws-instances-type-and-tag/pass.hcl
Both your passing and failing tests return PASS
because both test
cases evaluated to their expected values — the passing scenario evaluated to
true and the failing scenario evaluated to false.
Run the test with the -verbose
flag to get more information about the test.
$ sentinel test -verbose restrict-aws-instances-type-and-tag.sentinelInstalling test modules for test/restrict-aws-instances-type-and-tag/fail.hclInstalling test modules for test/restrict-aws-instances-type-and-tag/pass.hcl PASS - restrict-aws-instances-type-and-tag.sentinel PASS - test/restrict-aws-instances-type-and-tag/fail.hcl trace: restrict-aws-instances-type-and-tag.sentinel:39:1 - Rule "main" Description: Main rule that requires other rules to be true Value: false restrict-aws-instances-type-and-tag.sentinel:32:1 - Rule "instance_type_allowed" Description: Rule to restrict instance types Value: false PASS - test/restrict-aws-instances-type-and-tag/pass.hcl trace: restrict-aws-instances-type-and-tag.sentinel:39:1 - Rule "main" Description: Main rule that requires other rules to be true Value: true restrict-aws-instances-type-and-tag.sentinel:32:1 - Rule "instance_type_allowed" Description: Rule to restrict instance types Value: true restrict-aws-instances-type-and-tag.sentinel:23:1 - Rule "mandatory_instance_tags" Description: Rule to enforce "Name" tag on all instances Value: true
The -verbose
flag returns the steps at which each test passes or fails your criteria.
Next steps
You created test policies and ran test cases using the Sentinel CLI. To learn more about Sentinel, review the following resources:
- Learn how to Generate Mock Policy Data
- Review how to Write a Sentinel Policy
- Learn how to Upload a Sentinel Policy Set to HCP Terraform