Skip to content

CloudFormation Metadata Context validation - #307

Open
satyakigh wants to merge 5 commits into
mainfrom
contxt
Open

satyakigh wants to merge 5 commits into
mainfrom
contxt

Conversation

@satyakigh

@satyakigh satyakigh commented Aug 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds validation of the CloudFormation Metadata Context attribute (Metadata.com.aws.cloudformation.Context) on the template and on each resource, as three rules evaluated identically by every engine selector.

Three new rules. I4010 reports a template or architecture-relevant resource that has no Context block. W4011 reports a Context block that has no why and no low-confidence trust declaration (trust.conf: low). W4012 reports a Context block that does not match the Metadata Context schema. All three are BestPractice rules registered with CfnLint origin in rules/src/registry.rs: cfn-lint 1.57.2 reserves these numbers for the same checks (ContextMissing.py, ContextMissingWhy.py, ContextSchemaViolation.py).

One shared check. The check is a post-engine pass in validation-engine/src/context_check.rs, invoked from engine.rs after rule evaluation, so rego, cel, and composite produce the same findings by construction. A resource with a usable Type must carry its own block unless its type is one of the subordinate types that attach to another resource (AWS::IAM::Policy, AWS::Lambda::Permission, AWS::Logs::LogGroup, AWS::Logs::LogStream, AWS::S3::BucketPolicy, AWS::SNS::TopicPolicy, AWS::SQS::QueuePolicy), a ::MODULE, or AWS::CDK::Metadata; CDK framework helper resources (log-retention and custom-resource provider handlers) are skipped by logical ID. A block carried by an exempt resource is still validated by W4011 and W4012. The template-level block is required once two or more resources lack their own. Missing resources are reported as one I4010 finding anchored at the first missing resource, listing every missing resource as LogicalId (Type) and attaching the rest as related_resources with their own spans; schema violations produce one W4012 finding per violated field, located at that field. The checks run on every template, including CDK-synthesized ones; the CDK gate still drops only its existing template-authoring rules (I1022, W3010).

Published schema, embedded. data-source/handwritten/metadata_context_schema.json is the Metadata Context schema v1 from the CloudFormation template reference, copied verbatim and embedded through data-source/build.rs as METADATA_CONTEXT_SCHEMA. A unit test fails if a future revision of the schema introduces a keyword the validator does not interpret.

Snapshots exclude the three rules. I4010 fires on nearly every corpus template, so persisting it would rewrite every snapshot entry. resources::exclude_snapshot_rules removes I4010, W4011, and W4012 from the persisted report and from the snapshot harness's in-process report, after the rego/cel/composite parity comparison, which still covers them. All 718 pre-existing snapshot entries are byte-identical to main; the only additions are the six new fixtures. The rules' behavior is pinned by those fixtures and the context_metadata integration test instead.

Related issue

None.

Validation

  • cargo fmt --all -- --check and cargo clippy --locked --all-targets --workspace -- -D warnings: clean.
  • cargo test -p cloudformation-validate-validation-engine: 259 pass, including 16 context_check unit tests and the CDK-gate test. cargo test -p cfn-validate --test context_metadata: 6 pass (YAML and JSON fixtures through all three selectors). cargo test -p cfn-validate --test snapshot_tests: 15 pass. cargo test -p resources --lib: 9 pass. cargo test -p cloudformation-validate-rules: 79 pass (rule count 311). cargo test -p cloudformation-validate-template-model: 813 pass. cargo test -p cloudformation-validate-data-source: 74 pass.
  • Engine parity: cargo run --release -p resources --example generate_validation_reports over the full corpus (724 templates) verifies rego == cel == composite before the exclusion is applied, so the Context rules are included in the comparison. cfn-validate --engine rego|cel|composite on each new fixture gives identical rule ID, severity, location, and message.
  • cfn-lint 1.57.2 (--include-experimental --include-checks I): identical firing and location on every new fixture, and across the whole corpus for W4011 and W4012 (zero extra, zero missing). For I4010 the only differences are 32 templates where the existing transform-error gate suppresses everything except E0001, and bad/I4010_cdk_synthesized_missing_context.json, where cfn-lint skips CDK templates by design and this engine reports.

Validation behavior changes

Expected behavior comes from the Metadata Context attribute documentation and its published schema: TemplateContext admits arch, must, ref, owner; ResourceContext admits why, must, mutable, mutability, trust, deps, with why defined as the rationale and trust.conf recording confidence in it; both reject additional properties.

Accepted: good/metadata_context_complete.yaml carries conforming blocks on the template and every resource and produces no Context finding.

Rejected: bad/I4010_context_missing.yaml and bad/I4010_context_missing.json (template and resource blocks absent; subordinate types not listed), bad/I4010_cdk_synthesized_missing_context.json (synthesized template; the AWS::CDK::Metadata record is not listed), bad/W4011_context_missing_why.yaml (conf: low excuses the omission, medium and high do not, a subordinate type that supplies a block is held to it), bad/W4012_context_schema_violation.yaml (wrong field types, unrecognized enum values, missing required trust.src and ref[].at, fields at the wrong level, undefined fields, a block that is not a mapping; one finding per violation).

Checklist

  • For validation behavior changes, expected behavior is supported by CloudFormation evidence and all three engine
    selectors agree.
  • My code adheres to the CONTRIBUTING GUIDE and DESIGN GUIDELINES.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant