Atmos Native AWS CloudFormation Components
Use this skill for native components."aws/cloudformation" stacks. Atmos deploys them through
the AWS SDK for Go v2, without an aws, cfn, sam, or Rain binary. This first aws/*
component and its nested commands are experimental; the top-level aws group stays stable.
Related Skills
| Need | Load |
|---|---|
| Terraform/OpenTofu orchestration (contrast: HCL + state file vs. CFN's own stack/changeset state) | atmos-terraform |
Component architecture, inheritance, catalogs, dependencies.components DAG ordering | atmos-components |
| AWS credentials / identities for the SDK client and per-target auth overrides | atmos-auth |
Lifecycle hooks around diff/apply/delete/drift detect/drift describe/changeset create/changeset execute | atmos-hooks |
| Native CI job summaries | atmos-ci |
!secret values flowing into parameters: | atmos-secrets |
kind: git GitOps delivery target mechanics | atmos-git |
| Local AWS sandbox (Floci) for testing without real credentials | atmos-emulator |
| Migrating off Rain / raw CloudFormation | atmos-migration → references/from-rain.md |
Component Shape
Define CloudFormation stacks under components.aws/cloudformation in stack manifests. Prefer the
unquoted aws/cloudformation: key in YAML examples; a / does not require quoting:
components:aws/cloudformation:vpc:path: template.yaml # file reference, relative to the component's base pathstack_name: "{{ .vars.stage }}-vpc" # explicit; no legacy name-pattern interpolationparameters:CidrBlock: "10.0.0.0/16"AvailabilityZones:- us-east-1a- us-east-1bDbPassword: !secret DB_PASSWORD # secrets flow into parameters, not envcapabilities:- CAPABILITY_IAMtags:team: platformstack_policy:file: stack-policy.json # or an inline `body:` (JSON string or YAML map)role_arn: "arn:aws:iam::123456789012:role/cfn-deploy"termination_protection: truetimeout_in_minutes: 30settings:aws_cloudformation:region: us-east-2provision:backend:enabled: truetargets:artifacts:kind: aws/s3bucket: acme-plat-cfn-artifactsregion: us-east-2gitops:kind: gitrepository: acme/infra-gitopspath: stacks/dev/vpc
CloudFormation components use the same stack sections as other component types — vars, env,
auth, metadata, settings, dependencies, hooks, source/provision, inheritance, and
overrides — plus CloudFormation-specific fields. generate: and plugins: are not supported: a
generate: key on a component, under the aws/cloudformation: type-level section, or in
CloudFormation overrides is a stack-processing error. Use an inline template: instead — Atmos
renders it with Go templates (when templates.settings.enabled: true) and YAML functions, so
per-stack template content needs no generated files.
| Field | Purpose |
|---|---|
template / path (exactly one required) | template is an inline body (string or YAML map) rendered by Atmos Go templates (templates.settings.enabled: true) and YAML functions (!env, !store, !aws.cloudformation.output, ...) before reaching CloudFormation. path is a file reference, read as raw bytes, no templating. Setting both is an error. To pass a CloudFormation dynamic reference through the template renderer, escape the opening braces once: Value: '{{ "{{" }}resolve:ssm:/my/param}}'. |
stack_name | Explicit stack name. Supports Go templates; no legacy name-pattern interpolation. |
parameters | A map of name to value, or an AWS CLI/Rain list of {ParameterKey, ParameterValue} entries (UsePreviousValue: true allowed; also !include of a JSON array). Scalars stringified, lists comma-joined for List<Type>. Other shapes are an error. For a Rain config file use !include rain.yaml .Parameters. |
capabilities | Acknowledged IAM capabilities: CAPABILITY_IAM, CAPABILITY_NAMED_IAM, CAPABILITY_AUTO_EXPAND (macros/SAM). Validated locally; an unknown value fails with the valid set. |
tags | map[string]string tags on the stack — distinct from Atmos's own component tags/--tags. |
stack_policy.file / stack_policy.body (mutually exclusive; setting both is a validation error) | file is a JSON policy path relative to the component's base path, read verbatim. body is an inline policy: a JSON string (used as written) or a YAML map (serialized to JSON). body needs no component directory and is rendered by Atmos templates and YAML functions like an inline template. Atmos installs the policy before UPDATE execution (apply/deploy or explicit changeset execute), and after a successful CREATE or a no-op apply. Policy-setting errors stop pending updates; blocked updates never trigger an automatic override. |
role_arn | The CloudFormation service role, not caller credentials — CreateChangeSet's RoleARN. |
notification_arns | SNS topic ARNs CloudFormation publishes stack events to. |
disable_rollback | Prevents automatic rollback on stack creation/update failure. |
termination_protection | See Delete Safety below. |
timeout_in_minutes | Bounds how long stack creation may run before CloudFormation rolls back. |
source | JIT template provisioning — see Source & Template Management. |
provision | Delivery targets — see Delivery Targets. |
Commands
| Command | Purpose |
|---|---|
atmos aws cloudformation render <component> -s <stack> | Render the template client-side without deploying or validating it through the CloudFormation API. Local or already-provisioned sources render offline without AWS credentials; source provisioning (for example a cold private S3 source) and configured secret or output lookups can still require authentication and network access. |
atmos aws cloudformation validate <component> -s <stack> | Server-side ValidateTemplate — syntax and capability discovery, not a local linter. |
atmos aws cloudformation diff <component> -s <stack> | Creates (or reuses) a changeset and previews the changes an apply would make, then deletes the preview changeset and any owned preview stack placeholder still in REVIEW_IN_PROGRESS. Cleanup failures are returned as errors. plan is an alias. |
atmos aws cloudformation apply <component> -s <stack> | Executes the changeset (ExecuteChangeSet), creating or updating the stack — never a direct CreateStack/UpdateStack call. Streams per-resource stack events live and ends with a rendered Outputs summary. |
atmos aws cloudformation deploy <component> -s <stack> | Alias for apply with --auto-approve defaulted to true. |
atmos aws cloudformation delete <component> -s <stack> | DeleteStack, respecting termination protection — see Delete Safety. |
atmos aws cloudformation output <component> [key] -s <stack> | Renders the deployed stack's Outputs via DescribeStacks, as apply does. With key, prints only that value (pipeable); a missing key lists the available keys. A stack that is not deployed is an error. Alias: outputs. |
atmos aws cloudformation fmt <component> -s <stack> [--check] | Canonically formats the local template in place (comment-preserving YAML round-trip, no shell-out). --check reports without writing and, in bulk runs, checks every template before failing once. See ci-and-listing. |
atmos aws cloudformation list [-s <stack>] | ListStacks, marking each stack managed (matches a component's stack_name in -s, or in any stack without it) or unmanaged. See ci-and-listing. |
All operation commands accept --all, --affected (with --base/--ref/--sha/--repo-path/
--clone-target-ref/--ssh-key/--ssh-key-password), --include-dependents (requires
--affected), and --tags/--labels bulk selection, matching atmos describe affected semantics.
--all/--affected are mutually exclusive with a positional component argument, and so is
--tags/--labels-based selection. atmos aws cfn is a Cobra alias for atmos aws cloudformation
that works with every verb.
Confirmation: direct apply previews the changeset before asking; deploy auto-approves.
delete also asks; publish-only/external targets do not. See
apply flow for cleanup and non-TTY behavior.
Output formats
Formats: json, yaml, hcl, env, dotenv, bash, csv, tsv, table, github;
key modifiers: --flatten, --uppercase. A positional key selects one output.
Masking reads deployed templates and fails closed if sensitivity metadata is unavailable;
--mask=false disables it. Internal lookups keep real values. See
output formats and masking for the full contract.
Changesets
Use changeset create, list, execute, and delete for explicit two-phase deployments.
See changeset operations for confirmation and capability
requirements.
Drift Detection
atmos aws cloudformation drift detect vpc -s dev [--fail-on-drift]atmos aws cloudformation drift describe vpc -s dev
drift detect runs DetectStackDrift/polls DescribeStackDriftDetectionStatus; drift describe
renders the results of the most recent detection (DescribeStackResourceDrifts). --fail-on-drift
exits non-zero when drift is found, for CI gating — drift is not a hard failure by default.
drift describe shows each MODIFIED resource's property differences (path, expected, actual,
type). Drift summaries follow Native CI. Atmos Pro dashboard uploads through
UploadInstanceStatus remain future work.
Delivery Targets (Backend Management)
By default apply/deploy deploy directly to the account/region resolved for the component (see
Region Resolution). A component can declare additional named
provision.targets, selected with --target: aws/s3 (publish-only upload, also used
automatically to package any template over CloudFormation's 51,200-byte inline limit),
git (GitOps commit instead of deploying), and aws/stackset (multi-account/region, see
Stack Sets). "Backend" means the S3 artifact bucket a kind: aws/s3 target
declares — CloudFormation's own stack state is service-managed. Manage it like
atmos terraform backend:
atmos aws cloudformation backend create vpc -s dev
Set provision.backend.enabled: true to auto-provision the bucket on first use instead of running
backend create explicitly. See
references/delivery-targets.md for the full target-kind table,
the backend verb group, auto-provisioning semantics, and today's packaging-scope limitation
(local assets like Lambda zips aren't rewritten, only the template body is uploaded).
Source & Template Management
Point a component at a remote template through the top-level source: section instead of committing
it to your infrastructure repository — the same JIT-vendoring mechanism other component types use:
components:aws/cloudformation:vpc:source:uri: github.com/acme/cfn-templates.git//vpc?ref={{ .Version }}version: 1.2.0path: template.yaml # relative to the vendored directory
A single-file source URI (e.g. a raw https://.../dns.yaml link) is fetched directly and used
as-is — path: isn't needed in that case.
provision.workdir.enabled only applies to a source: (it selects the per-instance download
directory). Setting it on a component without a source: is an error, because CloudFormation does
not copy local components into workdirs.
Inspect and manage vendored sources with the source verb group:
atmos aws cloudformation source pull vpc -s devatmos aws cloudformation source list [vpc] [-s dev]atmos aws cloudformation source describe vpc -s devatmos aws cloudformation source delete vpc -s dev
aws/cloudformation components cannot be vendored through a vendor.yaml manifest
(atmos vendor pull) — only source:-based JIT provisioning, the same restriction native Helm and
Kubernetes components have.
Stack Sets
Multi-account/multi-region orchestration, resolved from a kind: aws/stackset provision target
(accounts, regions, permission_model, administration_role_arn, execution_role_name):
atmos aws cloudformation stackset create vpc -s dev --target=multi-accountatmos aws cloudformation stackset update vpc -s dev --target=multi-accountatmos aws cloudformation stackset delete vpc -s devatmos aws cloudformation stackset instances vpc -s dev
create/update/delete prompt for confirmation (skip with --auto-approve). delete and
instances act directly on stack_name, not the target. See
references/delivery-targets.md for the full target YAML shape
and create-vs-update semantics.
Observability and Deployed-Stack Retrieval
Use tree (deployed nested-stack tree), logs, and watch to inspect stacks and operations; get template and get policy
retrieve deployed state. See operations
for examples and flag behavior.
Delete Safety & Termination Protection
delete maps to DeleteStack, with two safety behaviors:
--retain-resources=<logical-id1>,<logical-id2>passes retained logical IDs through to the API — only valid for aDELETE_FAILEDstack.- Termination protection is checked against the stack's live AWS state, not just local config,
and is never silently disabled. If live protection is enabled,
deletefails with a hint pointing at--disable-termination-protection(callsUpdateTerminationProtectionbefore deleting). Editingtermination_protection: falseand re-applying does not unprotect an already-protected stack —applyonly ever turns protection on. Only the explicit delete flag turns it off.
Auth
Component-level auth: selects an identity exactly like a Terraform component does — see
atmos-auth for identity chaining, FIPS endpoints, and aws/emulator
(Floci) local/no-credentials testing. Per-target provision.targets.<name>.auth overrides let a
deploy target assume a workload account's identity while an artifact-bucket target uses a
shared-services account's identity. role_arn on the component is a separate concept — it's
the CloudFormation service role, not caller credentials; see the Component Shape
table.
atmos.yaml Configuration
components:aws/cloudformation:base_path: components/cloudformation # default
base_path is a project-wide setting. Other CloudFormation fields (template/path,
stack_name, parameters, capabilities, tags, stack_policy, role_arn, notification_arns,
disable_rollback, termination_protection, timeout_in_minutes, source, provision, auth,
dependencies) are configured per stack, not in atmos.yaml.
Native CI Summaries
With ci.enabled: true (and --ci/ATMOS_CI to force a provider), the native plugin writes a job
summary titled after the verb you ran, plus $GITHUB_OUTPUT variables, for diff/plan,
apply/deploy, delete, drift detect, and drift describe. No commit statuses, PR comments, or
artifacts (Terraform-only). See ci-and-listing and
atmos-ci.
Hooks
Seven lifecycle pairs fire hook events: before/after × diff (plan normalizes to diff),
apply (deploy normalizes to apply), delete, drift detect, drift describe,
changeset create, and changeset execute — e.g. before.aws/cloudformation.changeset-create.
Hyphens inside command names are meaningful. The changeset events are not aliases of apply; add
them to a packaging hook's events: list. Every other verb fires none. Hook-firing verbs accept --skip-hooks (no value skips all; --skip-hooks=a,b skips named
hooks) and honor ATMOS_SKIP_HOOKS, as atmos terraform does. See
atmos-hooks for the hooks: block shape.
Secrets
!secret feeds CreateChangeSet parameters, not subprocess env:
(still available to hooks/!exec/templates). Require NoEcho: true: AWS masks parameters in the
console and stack/change-set descriptions, not Outputs, template/resource Metadata, or primary
identifiers. Keep secrets and derived values out of these surfaces, also when using supported
Secrets Manager/SSM secure-string dynamic references to avoid plaintext parameters.
Atmos masks registered values locally and conservatively redacts sensitive deployed outputs at
the presentation boundary; direct AWS responses remain outside this protection. Resolution loses origin, so Atmos cannot reliably reject secret-fed parameters missing NoEcho.
Migrating from Rain or Raw CloudFormation
There is no Rain compatibility layer: a path: template is submitted as written, and one that still
contains !Rain:: directives fails locally with ErrAwsCloudFormationRainDirective and one
replacement hint per directive. Route every directive, config-file, and verb mapping question to
atmos-migration's references/from-rain.md; do not restate the
tables here.
Guidance
- Prefer
path:for templates that live in the component directory; use inlinetemplate:when the body needs Atmos's own{{ }}templating or YAML functions before reaching CloudFormation. CloudFormation has nogenerate:— inline templating replaces it. - Use
dependencies.componentsso--all/--affecteddeploys stacks in the right order — a Terraform component candepends_ona CFN stack and vice versa. - Use
provision.backend.enabled: truefor a zero-friction dev sandbox; use explicitbackend create/updatein shared/production environments to re-apply secure defaults deliberately rather than only on first use. - Referenced local assets (Lambda zips, nested-stack templates) are not packaged automatically —
packaging covers only the template body. Build and upload them with
archive+publishhook steps (before.aws/cloudformation.apply, plus.diffand.changeset-createas needed), derive the key from stack vars, and pass it to the template viaparameters:. - Use the Floci
aws/emulatoridentity (seeexamples/cloudformation/) to develop and test with zero AWS credentials before pointing at a real account.
Region Resolution and Static Dry-Run
The region is the component's settings.aws_cloudformation.region, then the active identity's
region, then the AWS SDK chain; a component env AWS_REGION does not override it. --dry-run
defers YAML functions, templates, source downloads, authentication, and hooks. Details:
region-and-dry-run.