HashiCorp Sentinel Policies 3rd Gen (Part 2 of 3)

Wang Poh Peng
4 min readFeb 14, 2023

How to write third-generation Sentinel Policies for Terraform (TF) Cloud

Disclaimer: this is a paid feature and offering of TF Cloud, hence information is scarce about Sentinel in the internet, hence I would like to do my part to help people to learn it easier.

Prerequisites:

  1. Terraform Cloud setup with a proper workspace for making infrastructure mocks
  2. Terraform Cloud central configuration to be set to point to a repository of Sentinel Policies

Example UI policy check upon a Terraform Plan run on the TF cloud

You may refer to some of the examples found in this repository

To start off, you need to create a repository to create mock data for testing infrastructure as code. For e.g an EBS Volume

resource "aws_ebs_volume" "example" {
availability_zone = "ap-southeast-1"
size = 40
encrypted = true

tags = {
managed_by = "mock_infra"
environment = "Staging"
Project = "EcsEc2"
}
}

With that, in a folder where the Terraform code is linked to a workspace, run terraform plan . A link will be generated from the Terminal to bring you to the TFC UI. With that, at the bottom left hand corner of the page’s “Plan Finished”, you would find a button called “Download Sentinel Mocks”

A tar file will be downloaded, the file looks something run-asdfasf123-sentinel-mocks.tar.gz. After we unzip the file, this is the file we need to look for: mock-tfplan-v2.sentinel

All sentinel policy checking is done against the plan data found in this file. We use this file to create pass and fail cases.

Writing the Sentinel Policy and its repository

First, we need to be the admin for TFC and set the sentinel policy checking to point to a repository.

This repository would then contain a main sentinel.hcl file. We can also clone this repository from https://github.com/hashicorp/learn-sentinel-policies

The repository structure consists of the main policies in the root directory and the main sentinel.hcl file to determine which policies to enforce and what enforcement level. Eg. below

policy "ebs-volume-must-be-encrypted" {
source = "./ebs-volume-must-be-encrypted.sentinel"
enforcement_level = "advisory"
}

We will need to add sentinel modules which provides helper functions in navigating through the Terraform Plan data:

module "tfplan-functions" {
source = "./common-functions/tfplan-functions/tfplan-functions.sentinel"
}

module "tfstate-functions" {
source = "./common-functions/tfstate-functions/tfstate-functions.sentinel"
}

module "tfconfig-functions" {
source = "./common-functions/tfconfig-functions/tfconfig-functions.sentinel"
}

module "aws-functions" {
source = "./aws-functions/aws-functions.sentinel"
}

Here I provide an example of enforcing the EBS volumes to be encrypted

ebs-volume-must-be-encrypted.sentinel

# This policy uses the Sentinel tfplan/v2 import to require that
# all EBS volumes should be encrypted

# Import common-functions/tfplan-functions/tfplan-functions.sentinel
# with alias "plan"
import "tfplan-functions" as plan

# Get all EBS Volumes
allEBSVolumes = plan.find_resources("aws_ebs_volume")

# Get all Launch Templates
allLaunchTemplates = plan.find_resources("aws_launch_template")

# Filter to EBS volumes that are not encrypted
# Warnings will be printed for all violations since the last parameter is true

nonEncryptedEBSVolumes = plan.filter_attribute_is_not_value(allEBSVolumes,
"encrypted",
true, true)

nonEncryptedEBSVolumesInLaunchTemplates = plan.filter_attribute_is_not_value(allLaunchTemplates,
"block_device_mappings.0.ebs.0.encrypted",
"true", true)

# Main rule
validated = length(nonEncryptedEBSVolumes["messages"]) is 0 and length(nonEncryptedEBSVolumesInLaunchTemplates["messages"]) is 0
main = rule {
validated is true
}

Testing the policy

We will first need to create a test folder in the root repository, followed by a folder having the same name as the policy ebs-volume-must-be-encrypted

Within this folder again we create a folder called test-data
- This is where we store the Sentinel mocks provided at the first steps shown above (we can copy all the sentinel mock files into it)

Inside ebs-volume-must-be-encrypted folder, we write the test cases. For e.g.

fail.hcl and pass.hcl

These test cases files look similar to the main sentinel file determined at the root level but using the test keyword instead. Example below of fail.hcl:

module "tfplan-functions" {
source = "../../common-functions/tfplan-functions/tfplan-functions.sentinel"
}

module "tfconfig-functions" {
source = "../../common-functions/tfconfig-functions/tfconfig-functions.sentinel"
}

module "aws-functions" {
source = "../../aws-functions/aws-functions.sentinel"
}

mock "tfplan/v2" {
module {
source = "./test-data/mock-tfplan-fail.sentinel"
}
}

mock "tfconfig/v2" {
module {
source = "./test-data/mock-tfconfig.sentinel"
}
}

test {
rules = {
main = false
}

pass.hcl


module "tfplan-functions" {
source = "../../common-functions/tfplan-functions/tfplan-functions.sentinel"
}

module "tfconfig-functions" {
source = "../../common-functions/tfconfig-functions/tfconfig-functions.sentinel"
}

module "aws-functions" {
source = "../../aws-functions/aws-functions.sentinel"
}

mock "tfplan/v2" {
module {
source = "./test-data/mock-tfplan-pass.sentinel"
}
}

mock "tfconfig/v2" {
module {
source = "./test-data/mock-tfconfig.sentinel"
}
}

test {
rules = {
main = true
}
}

If you observe you would see that only the main value and the tfplan/v2 ‘s source attribute being different.

If your mock data has the EBS volume encrypted, then the plan data would be in the pass.hcl reference. Either we can manually modify the plan data, or we can use the mock infra repo’s code to generate another plan data that fails the policy check to be used for fail.hcl reference.

With all the files above in place. Sentinel Policy checking would automatically be activated on each terraform plan that runs on TFC.

With this, I conclude the part two of the series, in the next part I will share more about publishing the policies to the public registries.

I welcome feedback on sharing more examples on Sentinel Policy writing. Thanks for reading!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Wang Poh Peng
Wang Poh Peng

Written by Wang Poh Peng

Technology Enthusiast & Culture Explorer

No responses yet

Write a response