Skip to content

aws-cloudformation/cloudformation-validate

cloudformation-validate

License Main CI CodeQL

Fast, offline, embeddable validation for AWS CloudFormation templates.

cloudformation-validate parses a CloudFormation template (JSON or YAML) and returns structured diagnostics — schema violations, semantic errors, security concerns, and best-practice suggestions — before you deploy. It runs entirely offline: every rule and resource schema is compiled into the binary, so there is no network access, no credentials, and no runtime fetching.

It ships as a Rust CLI, an embeddable Rust library, a Node.js package (WASM), and a JVM library (Kotlin/Java) — all backed by the same validation core.

Features

  • Offline-first. Rules and AWS resource schemas are baked into the binary. Nothing is fetched at runtime.
  • Structured diagnostics. Every finding carries a stable rule ID, severity, precise source span (line/column), resource path, and an optional suggested fix — designed for IDEs, CI, and agents, not just humans.
  • Two interchangeable engines. A Rego engine and a CEL engine evaluate the same rule set and produce identical results.
  • Custom rules. Extend validation with your own rules in CEL (JSON), Rego, or CloudFormation Guard DSL.
  • Embeddable everywhere. Use it from the CLI, Rust, Node.js, or the JVM.
  • Sub-second validation for typical templates.

How it works

When a template is submitted, cloudformation-validate runs a fixed pipeline:

  1. Parse — read JSON/YAML, resolve intrinsic functions (Ref, Fn::GetAtt, Fn::Sub, Fn::If, …), build a reference graph with cycle detection, and model conditions with a SAT solver, producing a semantic model.
  2. Schema validate — check each resource against the compiled CloudFormation provider schemas, producing Fatal-severity diagnostics for structural violations (type mismatches, missing required properties, invalid enums, pattern and constraint failures).
  3. Evaluate rules — the selected engine (Rego or CEL) evaluates lint rules against the semantic model, producing Error/Warning/Info diagnostics for semantic issues, cross-resource references, security risks, and best practices.
  4. Validate Step Functions — check AWS::StepFunctions::StateMachine definitions (state types, StartAt/Next references, required fields).
  5. Enrich, filter, report — attach rule descriptions and context, apply include/exclude filters and severity gating, sort by source location, deduplicate, and assemble a structured JSON report.

Installation

See INSTALLATION.md for build instructions, prebuilt release artifacts (signed JVM jar, WASM zip, and per-platform cfn-validate CLI binaries), and signature verification.

Quick start

# Validate a single template
cargo run -p cfn-validate -- template.yaml

# Validate every template in a directory (recurses, picks up .yaml/.yml/.json)
cargo run -p cfn-validate -- ./templates/

# Use the CEL engine instead of the default Rego engine
cargo run -p cfn-validate -- template.yaml --engine cel

# Compact output for IDEs/CI
cargo run -p cfn-validate -- template.yaml --format standard

# Only report errors and above
cargo run -p cfn-validate -- template.yaml --level error

# List every available rule and exit
cargo run -p cfn-validate -- --list-rules

# Load custom Guard rules
cargo run -p cfn-validate -- template.yaml --guard-rule-source ./my-rules/

The CLI prints a JSON report to stdout and exits 0 when clean, 1 when errors or fatal diagnostics are found, and 2 on usage errors. For the full option reference, see the cfn-validate README.

Embedding as a library

Rust

Construct an engine and a schema validator once, then validate many templates:

use rego_engine::RegoEngine;
use schema_validator::SchemaValidator;
use validation_engine::{validate_bytes_with_path, EngineConfig, ValidateConfig};

let schema_validator = SchemaValidator::new();
let engine = RegoEngine::new(EngineConfig::default ()) ?;

let bytes = std::fs::read("template.yaml") ?;
let report = validate_bytes_with_path(
    & engine,
    & schema_validator,
    & bytes,
    ValidateConfig::default (),
    "template.yaml".to_string(),
) ?;

for d in & report.diagnostics {
    println!("[{}] {} — {}", d.severity, d.rule_id, d.message);
}

See validation-engine/API.md for the full embedding API.

Node.js

import { RegoEngine, TemplateFile } from "@aws/cloudformation-validate";

const engine = new RegoEngine();
const report = engine.validateStandard(new TemplateFile("template.yaml"));
for (const d of report.diagnostics) {
    console.log(`[${d.severity}] ${d.ruleId}: ${d.message}`);
}
engine.free();

JVM (Kotlin)

import com.amazonaws.cloudformation.validation.*
import java.io.File

val engine = RegoEngine()
val report = engine.validateStandard(File("template.yaml"))
for (d in report.diagnostics) {
    println("[${d.severity}] ${d.ruleId}: ${d.message}")
}

Rules

Bring your own rules in any of three formats — all loadable from the CLI and the library:

  • CEL (.json) — property and data-driven checks, evaluated by the CEL engine.
  • Rego (.rego) — complex cross-resource logic, evaluated by the Rego engine.
  • Guard DSL (.guard) — declarative compliance rules, translated automatically and usable with either engine.

See RULES and CUSTOM_RULES.md for the formats, available context, and examples.

Repository layout

This is a Cargo workspace. The main crates:

Crate Role
cfn-validate cfn-validate CLI and cfn-benchmark binary
validation-engine ValidationEngine trait, orchestration pipeline, Step Functions validation
template-model Template parser, intrinsic resolver, condition SAT solver, reference graph
rules Rule registry, severity model, categories, and diagnostic filtering
diagnostics Shared types: Diagnostic, SourceSpan, ValidationReport, metrics
schema-validator JSON Schema validation against compiled CloudFormation provider schemas
rego-engine Rego-based rule evaluation with custom builtins
cel-engine Native Rust rules plus a CEL interpreter for custom rules
guard-translator Parses Guard DSL into an engine-agnostic intermediate representation
bindings-wasm WASM bindings for Node.js
bindings-jvm JVM bindings (Kotlin/Java) via UniFFI

Security

If you discover a potential security issue, please do not open a public GitHub issue. Report it privately through AWS Vulnerability Reporting instead.

License

Licensed under the Apache License 2.0. See NOTICE for attributions and THIRD-PARTY-LICENSES.txt for third-party license details.