npm.io
1.7.0-beta • Published 2 weeks ago

@aws/cloudformation-validate

Licence
Apache-2.0
Version
1.7.0-beta
Deps
0
Vulns
0
Weekly
0
Stars
6

CloudFormation Validate for Node.js

Validate AWS CloudFormation templates from JavaScript or TypeScript and catch schema violations, security risks, and best-practice findings before deployment — in your editor, build, or CI.

  • Offline — all rules and resource schemas are bundled.
  • Fast — sub-second validation per template.

Installation

Available on npm as @aws/cloudformation-validate.

npm install @aws/cloudformation-validate

Quick start

Engines, models, and validators hold off-heap memory — call .free() when done with each object:

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

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

Each diagnostic identifies the rule, severity, affected resource and property, and source location — see StandardDiagnostic. A complete, runnable project is in examples.

Engine

RegoEngine and CelEngine both implement the Engine interface and are interchangeable — they produce identical diagnostics for the same template and config.

Engine interface
Method Returns Description
validateStandard(template, config?) StandardReport Validates and returns diagnostics without extended context
validateDetailed(template, config?) DetailedReport Validates and returns diagnostics with documentation URLs, rule descriptions, phase tags, and ViolationContext
listRules() RuleInfo[] Returns metadata for every built-in and loaded custom rule
engineName() string "rego" or "cel"
free() void Releases the engine's off-heap memory
EngineConfig

Passed to the constructor. All fields are optional; omitted rule arrays are empty and an omitted schemaValidatorConfig uses only the bundled schemas.

interface EngineConfig {
    customRules?: RuleSource[];                       // engine-native rules (Rego for RegoEngine, CEL for CelEngine)
    guardRules?: RuleSource[];                        // CloudFormation Guard DSL rules — translated internally
    schemaValidatorConfig?: SchemaValidatorConfig;   // schema validation and overlay configuration
}

interface SchemaValidatorConfig {
    additionalSchemas?: SchemaSource[];   // resource provider schemas merged over the bundled schemas
}

type RuleSource = ExternalRuleSource | RuleFile;
type SchemaSource = AdditionalSchemaSource | SchemaFile;

class RuleFile {
    constructor(path: string);   // rule file read from disk; the path becomes the rule source name
}

class SchemaFile {
    constructor(path: string, typeName?: string); // schema file; typeName defaults to the value inside the JSON
}

interface ExternalRuleSource {
    name: string;     // identifier shown in diagnostics (e.g. file path)
    content: string;  // full rule source text
}

interface AdditionalSchemaSource {
    typeName?: string; // omit to use the typeName inside the schema JSON
    schema: string;    // complete resource provider schema JSON
}

Pass a RuleFile to load a rule from disk — the same pattern as TemplateFile for templates — or an ExternalRuleSource when you already have the rule text in memory. SchemaFile does the same for an additional resource provider schema. Its optional constructor typeName may be omitted when the schema JSON contains its own typeName.

The generated AdditionalSchemaSource record exposes typeName as an optional field. Omit it (or leave the SchemaFile constructor argument unset) for an in-memory schema whose JSON already contains its own typeName.

const engine = new CelEngine({
    customRules: [new RuleFile("rules/s3_encryption.json")],
    guardRules: [new RuleFile("rules/compliance.guard")],
    schemaValidatorConfig: {
        additionalSchemas: [new SchemaFile("schemas/aws-lambda-function.json")],
    },
});

ValidateConfig

Controls filtering, severity, parameter overrides, and behavior. All fields optional — omitting the config or passing {} uses defaults.

interface ValidateConfig {
    include?: RuleFilterConfig;
    exclude?: RuleFilterConfig;
    severityLevel?: Severity;
    parameterOverrides?: Record<string, string>;
    pseudoParameterOverrides?: PseudoParameterOverrides;
    strict?: boolean;
    disableBuiltinRules?: boolean;
}
Field Default Description
include {} (all rules) When set, only matching rules produce diagnostics. Empty means include everything.
exclude {} (nothing excluded) Matching rules are suppressed. Applied after include.
severityLevel "INFO" Minimum severity threshold. Diagnostics below this level are dropped. Values: DEBUG, INFO, WARN, ERROR, FATAL.
parameterOverrides {} Override template parameter values during resolution. Keys are parameter logical IDs.
pseudoParameterOverrides all undefined Override CloudFormation pseudo-parameters (AWS::AccountId, AWS::Region, etc.).
strict false When true, WARN-severity diagnostics are upgraded to ERROR.
disableBuiltinRules false When true, all built-in rules (schema validation, Step Functions, engine rules) are skipped; only custom and Guard rules are evaluated.
RuleFilterConfig

Both include and exclude use this structure. All fields are additive — a rule matches if it hits any criterion.

interface RuleFilterConfig {
    ids?: string[];                    // exact rule IDs, e.g. ["E3012", "W3010"]
    categories?: string[];             // category names, e.g. ["security", "best_practices"]
    idRanges?: IdRange[];              // numeric ranges, e.g. { prefix: "E", start: 3000, end: 3099 }
    idPatterns?: string[];             // regex patterns matched against rule IDs
    resourceIds?: ResourceIdFilter[];  // a rule (or every rule) on a logical resource ID
    logicalIds?: LogicalIdFilter[];    // a rule (or every rule) on a named template entity
    resourceTypes?: ResourceTypeFilter[]; // a rule (or every rule) on a resource type
    services?: ServiceFilter[];        // a rule (or every rule) on a service, e.g. "AWS::AutoScaling"
}

// resourceIds / logicalIds / resourceTypes / services each carry an optional ruleId:
// set it to scope the filter to one rule, or omit it for every rule on the target.
interface ResourceIdFilter   { ruleId?: string; resourceId: string; }
interface LogicalIdFilter    { ruleId?: string; logicalId: string; entityType?: EntityType; }
interface ResourceTypeFilter { ruleId?: string; resourceType: string; }
interface ServiceFilter      { ruleId?: string; service: string; }

The service is matched verbatim against the service-provider::service-name prefix of the resource type — its first two ::-delimited segments (e.g. AWS::AutoScaling in AWS::AutoScaling::LaunchConfiguration).

The resourceIds dimension matches only diagnostics attributed to a resource; logicalIds additionally matches diagnostics on parameters, outputs, mappings, conditions, and template rules (for resource diagnostics the two carry the same value). An optional entityType scopes a LogicalIdFilter to entities of one type, so MyThing as a "Parameter" is matched without touching a same-named entity of another type.

PseudoParameterOverrides

Override CloudFormation pseudo-parameters used during intrinsic function resolution. All fields optional — when undefined, the engine uses built-in defaults (e.g. region defaults to us-east-1).

interface PseudoParameterOverrides {
    accountId?: string;         // AWS::AccountId
    notificationArns?: string;  // AWS::NotificationARNs
    partition?: string;         // AWS::Partition
    region?: string;            // AWS::Region (default: "us-east-1")
    stackId?: string;           // AWS::StackId
    stackName?: string;         // AWS::StackName
    urlSuffix?: string;         // AWS::URLSuffix
}

TemplateFile

Wraps a filesystem path. Engines read the file bytes internally.

const template = new TemplateFile("path/to/template.yaml");

TemplateModel

Parses a template into the resolved SemanticModel for direct inspection — the same model the engines evaluate rules against.

const model = new TemplateModel(new TemplateFile("template.yaml"));
Method Returns Description
resources() Record<string, ResolvedResource> All resources with resolved property values
parameters() Record<string, ParameterInfo> Parameter definitions with types, defaults, constraints
outputs() Record<string, ResolvedOutput> Outputs with resolved values and export names
conditions() string[] Condition names defined in the template
transforms() string[] Transform declarations (e.g. AWS::Serverless-2016-10-31)
formatVersion() string \ undefined AWSTemplateFormatVersion value
description() string \ undefined Template description
toDiagnosticModel() DiagnosticModel Full diagnostic model including reference graph, condition implications, and resolution sources
sourceLocation(path) SourceSpan \ null Source line/column span for a JSON path (e.g. Resources/MyBucket/Properties/BucketName)
free() void Releases WASM memory

SchemaValidator

Runs schema validation independently from the rule engines. Checks each resource against compiled CloudFormation provider schemas and produces FATAL-severity diagnostics for structural violations.

const validator = new SchemaValidator();
const diagnostics = validator.validate(new TemplateFile("template.yaml"), "us-east-1");
validator.free();
Method Returns Description
validate(template, region?) StandardDiagnostic[] Schema diagnostics. region defaults to "us-east-1".
listRules() RuleInfo[] Schema rule metadata
schemaCount() number Number of compiled provider schemas
free() void Releases WASM memory

Report Types

StandardReport / DetailedReport
interface StandardReport {
    filePath: string;
    status: "OK" | "ERROR";           // ERROR when the template fails to parse
    version: string;
    metadata: ReportMetadata;
    performance: PerformanceMetrics;
    diagnostics: StandardDiagnostic[];
}

DetailedReport has the same structure but its diagnostics include additional fields: documentationUrl, ruleDescription, phase (PARSE | SCHEMA | LINT), and context (ViolationContext with actualValue, expectedConstraint, resolutionSource, etc.).

StandardDiagnostic
interface StandardDiagnostic {
    ruleId: string;                    // e.g. "E3012", "F1001", "W3010"
    severity: Severity;                // "FATAL" | "ERROR" | "WARN" | "INFO" | "DEBUG"
    message: string;
    source: RuleOrigin;                // "SCHEMA" | "CFN_LINT" | "ENGINE" | "CUSTOM" | "GUARD"
    entity?: Entity;                   // the named template entity the finding targets, if any
    propertyPath?: string;             // e.g. "Properties.BucketName", or section-absolute like "Parameters/MyParam/Type"
    suggestedFix?: string;
    category?: string;
    startLine?: number;
    startColumn?: number;
    endLine?: number;
    endColumn?: number;
    relatedResources?: RelatedResource[];
    conditionScenario?: Record<string, boolean>;  // condition truth assignment that triggers this diagnostic
}

// The named template entity a diagnostic is attributed to. The entity type is the
// singular form of the top-level template section the entity is declared in.
interface Entity {
    logicalId: string;                 // logical ID as declared in the template
    entityType: EntityType;
    resourceType?: string;             // CloudFormation type, when the entity is a resource whose type is known
}

type EntityType = "Resource" | "Parameter" | "Output" | "Mapping" | "Metadata"
                | "Rule" | "Condition" | "Transform" | "FormatVersion" | "Description";

Keywords