v1.38.0
what
- Refactor Atmos components validation with OPA
- Allow creating a catalog of reusable Rego modules, constants and helper functions to be used in OPA policies
- Update docs
why
Atmos supports OPA policies for component validation in a single Rego file and in multiple Rego files.
As shown in the example below, you can define some Rego constants, modules and helper functions in a separate
file stacks/schemas/opa/catalog/constants/constants.rego
, and then import them into the main policy
file stacks/schemas/opa/vpc/validate-infra-vpc-component.rego
.
You also need to specify the module_paths
attribute in the component's settings.validation
section.
The module_paths
attribute is an array of filesystem paths (folders or individual files) to the additional modules for schema validation.
Each path can be an absolute path or a path relative to schemas.opa.base_path
defined in atmos.yaml
.
If a folder is specified in module_paths
, Atmos will recursively process the folder and all its sub-folders and load all Rego files into the OPA engine.
This allows you to separate the common OPA modules, constants and helper functions into a catalog of reusable Rego modules, and to structure your OPA policies to make them DRY.
example
Add the settings.validation
section to the component's config:
components:
terraform:
infra/vpc:
settings:
# Validation
# Supports JSON Schema and OPA policies
# All validation steps must succeed to allow the component to be provisioned
validation:
validate-infra-vpc-component-with-jsonschema:
schema_type: jsonschema
# 'schema_path' can be an absolute path or a path relative to 'schemas.jsonschema.base_path' defined in `atmos.yaml`
schema_path: "vpc/validate-infra-vpc-component.json"
description: Validate 'infra/vpc' component variables using JSON Schema
check-infra-vpc-component-config-with-opa-policy:
schema_type: opa
# 'schema_path' can be an absolute path or a path relative to 'schemas.opa.base_path' defined in `atmos.yaml`
schema_path: "vpc/validate-infra-vpc-component.rego"
# An array of filesystem paths (folders or individual files) to the additional modules for schema validation
# Each path can be an absolute path or a path relative to `schemas.opa.base_path` defined in `atmos.yaml`
# In this example, we have the additional Rego modules in `stacks/schemas/opa/catalog/constants`
module_paths:
- "catalog/constants"
description: Check 'infra/vpc' component configuration using OPA policy
# Set `disabled` to `true` to skip the validation step
# `disabled` is set to `false` by default, the step is allowed if `disabled` is not declared
disabled: false
# Validation timeout in seconds
timeout: 10
Add the following Rego package in the file stacks/schemas/opa/catalog/constants/constants.rego
:
package atmos.constants
vpc_dev_max_availability_zones_error_message := "In 'dev', only 2 Availability Zones are allowed"
vpc_prod_map_public_ip_on_launch_error_message := "Mapping public IPs on launch is not allowed in 'prod'. Set 'map_public_ip_on_launch' variable to 'false'"
vpc_name_regex := "^[a-zA-Z0-9]{2,20}$"
vpc_name_regex_error_message := "VPC name must be a valid string from 2 to 20 alphanumeric chars"
Add the following OPA policy in the file stacks/schemas/opa/vpc/validate-infra-vpc-component.rego
:
# Atmos looks for the 'errors' (array of strings) output from all OPA policies
# If the 'errors' output contains one or more error messages, Atmos considers the policy failed
# 'package atmos' is required in all Atmos OPA policies
package atmos
import future.keywords.in
# Import the constants from the file `stacks/schemas/opa/catalog/constants/constants.rego`
import data.atmos.constants.vpc_dev_max_availability_zones_error_message
import data.atmos.constants.vpc_prod_map_public_ip_on_launch_error_message
import data.atmos.constants.vpc_name_regex
import data.atmos.constants.vpc_name_regex_error_message
# In production, don't allow mapping public IPs on launch
errors[vpc_prod_map_public_ip_on_launch_error_message] {
input.vars.stage == "prod"
input.vars.map_public_ip_on_launch == true
}
# In 'dev', only 2 Availability Zones are allowed
errors[vpc_dev_max_availability_zones_error_message] {
input.vars.stage == "dev"
count(input.vars.availability_zones) != 2
}
# Check VPC name
errors[vpc_name_regex_error_message] {
not re_match(vpc_name_regex, input.vars.name)
}
Run the following commands to validate the component in the stacks:
> atmos validate component infra/vpc -s tenant1-ue2-prod
Mapping public IPs on launch is not allowed in 'prod'. Set 'map_public_ip_on_launch' variable to 'false'
exit status 1
> atmos validate component infra/vpc -s tenant1-ue2-dev
In 'dev', only 2 Availability Zones are allowed
VPC name must be a valid string from 2 to 20 alphanumeric chars
exit status 1