Sentinel
Centralize and share policy components with Sentinel modules
In the previous tutorial, you incorporated reusable functions to simplify and abstract the logic in your policy.
In this tutorial, you will create and use modules to share common functionality across multiple policies.
Tip
You can find the configuration for this tutorial in 03-reuse-modules
branch of the Learn Sentinel Get Started GitHub repository.
Create a module
Sentinel modules are reusable components that let you package and share common logic, data structures, and functions across multiple policies. You can use modules to make your policies more readable and maintainable. As your policy requirements grow, modules help you manage complexity by allowing you to break down large policies into smaller, more manageable pieces.
You will create a module that contains all the helper variables and functions for HashiCups. While you can structure your Sentinel modules in any way, we recommend the following file structure.
Create a helper
module sub-directory in a new import/modules/
directory.
$ mkdir -p import/modules/helper
Next, create a module file for HashiCups.
$ touch imports/modules/helper/hashicups.sentinel
Open imports/modules/helper/hashicups.sentinel
in your text editor, paste in the configuration below, and save the file.
imports/modules/helper/hashicups.sentinel
# Variables
valid_coffees = [
"HCP Aeropress",
"Packer Spiced Latte",
"Vaulatte",
"Nomadicano",
"Terraspresso",
"Vagrante espresso",
"Connectaccino",
"Boundary Red Eye",
"Waypointiato",
]
valid_sizes = ["small", "medium", "large"]
# Functions
func validate_name(name) {
return name in valid_coffees
}
func validate_size(size) {
return size in valid_sizes
}
This module contains the valid_coffees
and valid_sizes
variables, as well as the validate_name
and validate_size
functions that you previously defined in our policy.
Update policy
Now, update your validate_coffee_order.sentinel
policy to use the new module. Replace the contents of policies/validate_coffee_order.sentinel
with the following.
policies/validate_coffee_order.sentinel
import "hashicups"
# Parameters and variables
param order default { "items": [{ "name" : "Vaulatte", "size" : "medium" } ] }
# Main rule to validate a coffee order
main = rule {
all order.items as item {
hashicups.validate_name(item.name) and
hashicups.validate_size(item.size)
}
}
Notice how the policy is streamlined. Since the policy imports the hashicups
module, the policy no longer needs the variable definition and formulas. The main rule now uses hashicups.validate_name
and hashicups.validate_size
.
Update Sentinel configuration
To use the new module, you also need to update the Sentinel configuraiton file. Replace its contents with the following.
sentinel.hcl
import "module" "hashicups" {
source = "./imports/modules/helper/hashicups.sentinel"
}
policy "validate_coffee_order" {
source = "./policies/validate_coffee_order.sentinel"
}
policy "validate_coffee_order_override" {
source = "./policies/validate_coffee_order.sentinel"
params = {
order = {
items = [
{
name = "Terraspresso"
size = "medium"
},
{
name = "Connectaccino"
size = "large"
}
]
}
}
}
Apply the policy
Apply your policy with the Sentinel CLI. Both policies pass with the modules as expected.
$ sentinel apply
Pass - validate_coffee_order.sentinel
Pass - validate_coffee_order_override.sentinel
Next steps
In this tutorial, you learned how to create a Sentinel module to centralize common variables and functions, and updated the policy file to use the modules. In the next tutorial, you will learn how to use static imports to reference external data in your Sentinel policies.
For more information on topics covered in this tutorial, refer to the following documentation: