Sentinel
Simplify policy logic with Sentinel function
In the previous tutorial, you created your first Sentinel policy for HashiCups to validate coffee names and sizes.
In this tutorial, validate the names and sizes of multiple coffees in an order, and use functions to simplify the policy logic.
Tip
You can find the configuration for this tutorial in 02-simplify-functions
branch of the Learn Sentinel Get Started GitHub repository.
Update policy
Now, HashiCups lets users order multiple coffees in an order, and wants to ensure each coffee within the order is valid. You need to update the policy to support evaluating an order with multiple coffees.
Open validate_coffee_order.sentinel
in your text editor, paste in the configuration below, and save the file.
policies/validate_coffee_order.sentinel
# Parameters and variables
param order default { "items": [{ "name" : "Vaulatte", "size" : "medium" } ] }
# Valid coffee names
valid_coffees = [
"HCP Aeropress",
"Packer Spiced Latte",
"Vaulatte",
"Nomadicano",
"Terraspresso",
"Vagrante espresso",
"Connectaccino",
"Boundary Red Eye",
"Waypointiato",
]
valid_sizes = ["small", "medium", "large"]
## Functions
# Validate coffee name
func validate_name(name) {
return name in valid_coffees
}
# Validate coffee size
func validate_size(size) {
return size in valid_sizes
}
## Rules
# Main rule to validate a coffee order
main = rule {
all order.items as item {
validate_name(item.name) and
validate_size(item.size)
}
}
This is a complete Sentinel policy that you can evaluate. The following sections reviews the updated blocks in more detail.
Parameters
The policy now defines an order
param that accepts multiple coffees instead of coffee_name
and coffee_size
. Parameters can accept a variety of data types including strings, numbers, arrays, or maps.
policies/validate_coffee_order.sentinel
param order default { "items": [{ "name" : "Vaulatte", "size" : "medium" } ] }
Functions
Functions in Sentinel are reusable blocks of code that perform specific tasks. They can accept parameters and return values. If your functions return boolean values, you can chain them together to modularize your policy logic. This improves readability and maintainability.
This policy contains two functions, each corresponding to a specific criteria you want to validate.
- The
validate_name
function checks whether the name input is in the list of valid coffee names. - The
validate_size
function checks whether the size input is in the list of valid coffee sizes.
policies/validate_coffee_order.sentinel
func validate_name(name) {
return name in valid_coffees
}
func validate_size(size) {
return size in valid_sizes
}
Rules
The policy defines a single main rule validates each item in the other. It uses the all
expression to iterate over each item in the order. For each item, it calls the validation functions and combines their results with the and
operator. The policy passes only if all items in the order meet all the criteria.
policies/validate_coffee_order.sentinel
# Main rule to validate a coffee order
main = rule {
all order.items as item {
validate_name(item.name) and
validate_size(item.size)
}
}
Update Sentinel configuration
Update the sentinel.hcl
file to verify the new policy with multiple items. Replace the contents of sentinel.hcl
with the following.
sentinel.hcl
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"
}
]
}
}
}
This configuration defines two policy instances:
- The
validate_coffee_order
did not change. It still uses the default parameter values. - The
validate_coffee_order_override
now overrides theorder
param and includes an order with valid coffee names and sizes.
Apply the policy
Apply your policy with the Sentinel CLI. Both policies pass 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 reusable functions in Sentinel policies and handle multiple items in an order using the all
expression. In the next tutorial, you will learn how to create and use modules to share common functionality across multiple policies.
For more information on topics covered in this tutorial, refer to the following documentation: