atmos-validation
Atmos Validation Framework
Overview
Atmos provides a built-in validation framework that enforces policies and schema constraints on stack configurations before infrastructure is provisioned. Validation ensures clean, correct, and compliant configurations across teams and environments. Atmos supports three types of native validation:
- JSON Schema -- Validates the structure and types of component configurations
- Open Policy Agent (OPA) -- Enforces custom business rules using Rego policies
- EditorConfig Checker -- Ensures consistent coding styles across files
Validation runs automatically before atmos terraform plan and atmos terraform apply, preventing
misconfigured infrastructure from being provisioned. It can also run on-demand using the
atmos validate component and atmos validate stacks commands.
Validation Commands
atmos validate component
Validates a specific component in a stack against configured validation rules:
# Validate using rules defined in settings.validation
atmos validate component vpc -s plat-ue2-prod
# Validate with explicit schema path and type
atmos validate component vpc -s plat-ue2-prod \
--schema-path vpc/validate-vpc-component.rego \
--schema-type opa
# Validate with OPA and additional module paths
atmos validate component vpc -s plat-ue2-dev \
--schema-path vpc/validate-vpc-component.rego \
--schema-type opa \
--module-paths catalog/constants
# Validate with a timeout
atmos validate component vpc -s plat-ue2-dev --timeout 15
If --schema-path and --schema-type are not provided on the command line, Atmos uses the
settings.validation section from the component's stack configuration.
atmos validate stacks
Validates all stack configurations and YAML syntax:
atmos validate stacks
This command checks:
- All YAML manifest files for syntax errors and inconsistencies
- All imports for correct configuration, valid data types, and valid file references
- Schema validation of all manifest sections using the Atmos Manifest JSON Schema
- Detection of misconfigured or duplicated components in stacks
If the same component is defined in multiple stack manifest files for the same stack with different configurations, Atmos reports it as an error.
Configuring Validation
Schema Base Paths in atmos.yaml
Configure the base paths for validation schemas in atmos.yaml:
# atmos.yaml
schemas:
# JSON Schema validation
jsonschema:
# Supports absolute and relative paths
# Can be set via ATMOS_SCHEMAS_JSONSCHEMA_BASE_PATH env var
base_path: "stacks/schemas/jsonschema"
# OPA/Rego validation
opa:
# Supports absolute and relative paths
# Can be set via ATMOS_SCHEMAS_OPA_BASE_PATH env var
base_path: "stacks/schemas/opa"
# Atmos manifest validation
atmos:
# JSON Schema for validating Atmos manifests themselves
# Can be set via ATMOS_SCHEMAS_ATMOS_MANIFEST env var
manifest: "stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json"
Component Validation Settings
Define validation rules in the settings.validation section of component configurations:
components:
terraform:
vpc:
settings:
validation:
# JSON Schema validation step
validate-vpc-component-with-jsonschema:
schema_type: jsonschema
schema_path: "vpc/validate-vpc-component.json"
description: Validate 'vpc' component variables using JSON Schema
# OPA policy validation step
check-vpc-component-config-with-opa-policy:
schema_type: opa
schema_path: "vpc/validate-vpc-component.rego"
module_paths:
- "catalog/constants"
description: Check 'vpc' component configuration using OPA policy
disabled: false
timeout: 10
Validation Step Properties
Each validation step supports these properties:
| Property | Type | Description |
|---|---|---|
schema_type |
string | jsonschema or opa |
schema_path |
string | Path to the schema file (absolute or relative to base_path) |
module_paths |
list | (OPA only) Additional Rego module paths for imports |
description |
string | Human-readable description of the validation step |
disabled |
boolean | Set to true to skip this step (default: false) |
timeout |
integer | Timeout in seconds for the validation step |
All validation steps must pass for the component to be provisioned. If any step fails, Atmos blocks the operation with the validation error messages.
JSON Schema Validation
JSON Schema validates the structure, types, and required fields of component configurations. Atmos supports the JSON Schema 2020-12 specification.
Writing JSON Schema for Components
Place schema files in the schemas.jsonschema.base_path directory:
{
"$id": "vpc-component",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "vpc component validation",
"description": "JSON Schema for the 'vpc' Atmos component.",
"type": "object",
"properties": {
"vars": {
"type": "object",
"properties": {
"region": {
"type": "string"
},
"ipv4_primary_cidr_block": {
"type": "string",
"pattern": "^([0-9]{1,3}\\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$"
},
"map_public_ip_on_launch": {
"type": "boolean"
}
},
"additionalProperties": true,
"required": [
"region",
"ipv4_primary_cidr_block",
"map_public_ip_on_launch"
]
}
}
}
Input Structure for JSON Schema
The entire component configuration is passed as the JSON document. The schema validates against
the full configuration including vars, settings, env, backend, and other sections.
OPA/Rego Policy Validation
The Open Policy Agent (OPA) provides policy-as-code validation using the Rego language. OPA policies enable complex business rule validation that goes beyond structural schema checks.
Writing OPA Policies for Atmos
All Atmos OPA policies must:
- Use
package atmos - Define
errorsrules that return a set of error message strings (sets are serialized as arrays in OPA query results)
package atmos
import future.keywords.in
# Block public IPs in production
errors[message] {
input.vars.stage == "prod"
input.vars.map_public_ip_on_launch == true
message = "Mapping public IPs on launch is not allowed in 'prod'"
}
# Enforce naming conventions
errors[message] {
not re_match("^[a-zA-Z0-9]{2,20}$", input.vars.name)
message = "Component name must be 2-20 alphanumeric characters"
}
OPA Input Structure
The input object contains the full component configuration as returned by
atmos describe component. Key fields include:
input.vars-- Component variablesinput.settings-- Component settingsinput.env-- Environment variablesinput.backend-- Backend configurationinput.metadata-- Component metadatainput.workspace-- Terraform workspace name
Policy Execution Context
When Atmos executes commands like terraform plan or terraform apply, additional context
is provided to OPA policies:
input.process_env-- Map of environment variables in the current processinput.cli_args-- List of CLI arguments (e.g.,["terraform", "apply"])input.tf_cli_vars-- Map of variables from command-line-varargumentsinput.env_tf_cli_args-- List of arguments fromTF_CLI_ARGSenv varinput.env_tf_cli_vars-- Map of variables fromTF_CLI_ARGSenv var
This enables context-aware policies such as:
package atmos
# Don't allow terraform apply if foo is set to "foo"
errors[message] {
count(input.cli_args) >= 2
input.cli_args[0] == "terraform"
input.cli_args[1] == "apply"
input.vars.foo == "foo"
message = "Cannot apply when 'foo' variable is set to 'foo'"
}
Modular OPA Policies
Atmos supports splitting OPA policies across multiple Rego files. Define reusable constants and helper functions in separate files:
# stacks/schemas/opa/catalog/constants/constants.rego
package atmos.constants
vpc_dev_max_azs_error := "In 'dev', only 2 Availability Zones are allowed"
vpc_name_regex := "^[a-zA-Z0-9]{2,20}$"
Import them in your main policy:
package atmos
import data.atmos.constants.vpc_dev_max_azs_error
import data.atmos.constants.vpc_name_regex
errors[vpc_dev_max_azs_error] {
input.vars.stage == "dev"
count(input.vars.availability_zones) != 2
}
Specify the module paths in the component's validation configuration:
settings:
validation:
check-vpc:
schema_type: opa
schema_path: "vpc/validate-vpc-component.rego"
module_paths:
- "catalog/constants"
If module_paths specifies a folder, Atmos recursively loads all .rego files from that
folder and its subfolders.
Atmos Manifest JSON Schema Validation
Atmos includes an embedded JSON Schema for validating the structure of Atmos manifests themselves (not component vars, but the manifest file format). To override the embedded schema:
# atmos.yaml
schemas:
atmos:
manifest: "stacks/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json"
# Also supports URLs:
# manifest: "https://atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json"
The manifest schema can also be provided via:
- Environment variable:
ATMOS_SCHEMAS_ATMOS_MANIFEST - CLI flag:
--schemas-atmos-manifest
EditorConfig Validation
Atmos supports the EditorConfig Checker for ensuring consistent coding styles. This validates
adherence to rules defined in .editorconfig files across the project.
Validation in CI/CD Pipelines
Running Validation in GitHub Actions
Add a validation step early in your CI/CD pipeline:
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Atmos
uses: cloudposse/github-action-setup-atmos@v2
with:
atmos-version: 1.88.0
- name: Validate All Stacks
run: atmos validate stacks
- name: Validate Specific Components
run: |
atmos validate component vpc -s plat-ue2-dev
atmos validate component vpc -s plat-ue2-prod
Pre-Provisioning Validation
Atmos automatically runs validation before terraform plan and terraform apply. If any
validation policy fails, the operation is blocked:
$ atmos terraform apply vpc -s plat-ue2-prod
Mapping public IPs on launch is not allowed in 'prod'. Set 'map_public_ip_on_launch' variable to 'false'
exit status 1
Best Practices for Validation Policies
- Use JSON Schema for structural validation -- Required fields, type checking, pattern matching
- Use OPA for business logic -- Cross-field validation, environment-specific rules, naming conventions
- Organize OPA modules in a catalog -- Reusable constants, helper functions, shared rules
- Apply different policies per environment -- Stricter rules for production, relaxed for dev
- Set appropriate timeouts -- Prevent slow policies from blocking operations
- Use descriptive error messages -- Include the rule being violated and how to fix it
- Validate early in CI/CD -- Run
atmos validate stacksbefore plan/apply - Version your schemas -- Keep schema files in the same repository as stack configurations
- Test policies against known-good and known-bad configurations -- Ensure policies catch what they should
- Use
disabled: trueto temporarily skip a validation step during migration
Common Validation Patterns
Required Tags
package atmos
errors[message] {
required_tags := ["Environment", "Team", "CostCenter"]
tag := required_tags[_]
not input.vars.tags[tag]
message = sprintf("Required tag '%s' is missing", [tag])
}
Resource Limits by Environment
package atmos
errors[message] {
input.vars.stage == "dev"
input.vars.instance_count > 3
message = sprintf("Dev environment limited to 3 instances, got %d", [input.vars.instance_count])
}
errors[message] {
input.vars.stage == "prod"
input.vars.instance_count < 2
message = sprintf("Prod environment requires at least 2 instances, got %d", [input.vars.instance_count])
}
Naming Convention Enforcement
package atmos
errors[message] {
not re_match("^[a-z][a-z0-9-]*[a-z0-9]$", input.vars.name)
message = sprintf("Name '%s' must be lowercase alphanumeric with hyphens, starting with a letter", [input.vars.name])
}
Blocking Dangerous Operations
package atmos
errors[message] {
count(input.cli_args) >= 2
input.cli_args[0] == "terraform"
input.cli_args[1] == "apply"
input.process_env.ENVIRONMENT == "production"
not input.process_env.DEPLOYMENT_APPROVED
message = "Production deployments require DEPLOYMENT_APPROVED environment variable"
}
Network Security Rules
package atmos
errors[message] {
input.vars.stage == "prod"
cidr := input.vars.allowed_cidr_blocks[_]
cidr == "0.0.0.0/0"
message = "Open CIDR blocks (0.0.0.0/0) are not allowed in production"
}
Rego Syntax Notes
- Backslashes in regex patterns must be double-escaped in Rego strings:
\\.not\. - Use
import future.keywords.infor theinkeyword - The
package atmosdeclaration is required in all Atmos OPA policies - Atmos reads the
errorsoutput -- if it contains any strings, the policy fails
Additional Resources
- For OPA/Rego policy examples and input structure, see references/opa-policies.md
- For JSON Schema validation patterns, see references/json-schema.md