Skip to main content

cfn-typed

CloudFormation templates as typed Python dicts. Resource factories and their TypedDicts are generated from the official CloudFormation registry schemas (1,873 resource types), so a type checker catches typos, wrong types and missing required properties before CloudFormation does. Checked with ty.

Facts first, opinions fenced: the generated types and the permission names are the stable core, and anything that is a judgement (grants, patterns) lives in a place marked as an opinion. The book has a comparison with Troposphere, the AWS CDK and Pulumi.

Read the book for a getting-started guide, a gallery of pattern helpers (a Lambda role, a queue with its dead-letter queue, ...) and a reference page per resource. Install from PyPI: uv add cfn-typed.

import json
import cfn_typed as cfn
from cfn_types import sqs  # generated, see below

template: cfn.Template = {
    "Resources": {
        "DLQ": sqs.queue(),
        "Queue": sqs.queue(
            VisibilityTimeout=180,
            RedrivePolicy={"deadLetterTargetArn": cfn.get_att("DLQ", "Arn"), "maxReceiveCount": 3},
        ),
    },
}
print(json.dumps(template, indent=2))
error[unknown-argument]: Argument `MemorySise` does not match any known parameter of function `function`
error[invalid-argument-type]: Expected `Expr[int]`, found `Literal["30"]`
error[missing-argument]: No arguments provided for required parameters `Code`, `Role`

Generating only what you use

The package ships no resource types. You generate the ones you need into your own project, so the output stays small (four resources is about 44 KB):

cfn-typegen --out cfn_types AWS::SQS::Queue 'AWS::Lambda::*'
cfn-typegen --out cfn_types --template template.json   # types a JSON template uses
cfn-typegen --out cfn_types --all                      # everything, ~5.8 MB, ~4 MB with --no-docs
cfn-typegen --out cfn_types --no-docs AWS::SQS::Queue  # leave out the description docstrings
cfn-typegen search load balancer                       # find a type name

Type names are case-insensitive globs and an unmatched name is an error. The schema zip is downloaded once into ~/.cache/cfn-typegen/; --schemas points at a local copy, and --refresh downloads it again to pick up new AWS resources. Then rerun your generate command. Rerunning replaces earlier generated files in the output directory.

Layout of the generated modules

One module per service. For AWS::Lambda::Function there is lambda_.function(**props) (the factory), lambda_.Function (the resource dict), lambda_.FunctionProps, and one type per nested definition (lambda_.FunctionCode, ...). Python keywords get a trailing _. Factories also take depends_on, deletion_policy, update_replace_policy, condition and metadata as snake_case keywords, so they never collide with a property name.

cfn_typed itself holds the runtime pieces the generated code imports: intrinsics (Ref, GetAtt, ..., and Expr[T] = T | Intrinsic, which every generated property uses), base (Template, Tag, build) and a few helpers. examples/ has a worked SQS + Lambda stack and examples/cfn_types/ is its generated output.

Parameters as variables

cfn.Params declares template parameters (plain or SSM-backed) once and returns the Ref to use, so a shared "defaults" package can expose a VPC id or subnet list as variables. See the book.

JSON or YAML

cfn.to_json(template) and cfn.to_yaml(template) render the same template. The YAML uses short-form intrinsics (!Ref, !GetAtt A.Arn, ...).

Testing

Commit the rendered YAML and let CI check that the code still renders exactly that: cfn_typed.testing.assert_matches_file(template, "rendered/stack.yaml"). Rerun with CFN_TYPED_UPDATE=1 to accept an intended change. See the book. This repo does it for its own examples (examples/rendered/).

Command line

cfn_typed.cli.main(stacks) gives your own script emit, check, diff and ls subcommands: print or write templates, run every check (exit status 1 on a problem), compare with the committed files, and list resources. It is optional and your main() calls it. cfn-typed check template.yaml runs the same subcommands on any template file, with no Python code. check --live also asks AWS about a stack that is already deployed: the rendered template against the running one (--deployed), a change set that would replace or remove a table, bucket, key or distribution (--plan, never executed), and S3 code that is missing (--code). cfn-typed zip checks what is inside a package zip. cfn-typed import --sls turns a Serverless Framework template into cfn_typed_sumo.sls calls (uv add cfn-typed cfn-typed-sumo to migrate a service, and copy sls.py into your own package once it runs smoothly to drop the sumo dependency; see "Ejecting from the Serverless Framework" in the book). See the book.

Permission names

cfn_typed.permissions gives IAM actions names, so Sqs.ReceiveMessage replaces the string "sqs:ReceiveMessage" and a typo is an attribute error. The names are taken from awacs (BSD-2-Clause, credited in NOTICE) for a short list of major services, by scripts/sync-permissions.py; awacs is used only by that script and is not a dependency. Missing a service? Open a pull request (see CONTRIBUTING.md). See the book.

Grants (opinion layer)

cfn_typed.grants has the AWS CDK's permission sets, such as grants.Sqs.Queue.consume_messages.on(queue_arn), returning identity-policy statements. This layer is opinion, not fact, and is less permanent than the generated types and the permission names: it can change or move between releases, so pin the version if you rely on it. Copied from the CDK (Apache-2.0, credited in NOTICE) by scripts/sync-cdk-grants.py.

Intrinsic functions

ref, get_att, sub, join, select, split, find_in_map, if_, get_azs, base64, cidr, import_value, and the condition functions equals, and_, or_, not_, condition_ref build the dicts CloudFormation expects, with typed arguments, and Template["Conditions"] is typed. See the book.

Policy statements

cfn_typed.policy builds IAM statements with principals, conditions and the Not forms (allow, deny, aws(...), arn_like(...), assume_role_policy), and grants become resource-policy statements when you give them a principal. Statements are plain dicts that the type checker checks, whether you use the builders, Statement(...) or a literal. See the book.

cfn-typed-sumo: the fat pattern library

This repository also publishes cfn-typed-sumo, a second package on top of cfn-typed: the generated types for the core services plus ready-made patterns, with nothing to generate first. The lots of pre-generated types make it the quickest way to try things out.

uv add cfn-typed-sumo

cfn-typed is the core, and its API is meant to stay reliable. cfn-typed-sumo is deliberately fat and its API is volatile: patterns and names change between releases, so pin the version. See the book.

Patterns

Helper functions that return a resource or a small fragment (a queue with its dead-letter queue, a Lambda role, ...) are documented in the book, with working code in packages/sumo/src/cfn_typed_sumo/ (the catalog lists every pattern and the resources it creates). Build the book locally with uv run zensical serve.

Type checking notes

Read-only properties (Arn, Id, ...) are left out of the inputs. Shapes whose schema says additionalProperties: false are emitted as PEP 728 closed=True TypedDicts, which is what makes ty reject unknown names.

Known gaps: enums are plain str (no Literal, so newly added values never break you); oneOf constraints between properties are not modelled; arrays are list, which is invariant, so a variable typed list[Tag] needs list[Expr[Tag]].

Development

The repo contains no generated types. The examples and tests need a few, which are generated into examples/cfn_types/ (gitignored) the first time pytest runs, or by hand:

cfn-typegen --out examples/cfn_types AWS::SQS::Queue AWS::Lambda::Function \
    AWS::Lambda::EventSourceMapping AWS::IAM::Role
uv run ty check
uv run pytest
scripts/build-docs.sh        # generate types and reference pages, build the book (needs zensical)

Releasing

Releases are published to PyPI from GitHub with trusted publishing (no token). The version in pyproject.toml stays 0.0.0.dev0; the workflow sets it from the tag.

gh release create v0.1.0 --generate-notes

That runs the tests, builds with uv build and publishes. One-time setup on PyPI: add a trusted publisher for the project cfn-typed (owner vivainio, repository cfn-typed, workflow publish.yml, environment pypi), and create the pypi environment under the repository's Settings, Environments.

Metadata

Release files for cfn-typed 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cfn-typed 0.3.2
File Size Uploaded Provenance Actions
cfn_typed-0.3.2.tar.gz 405.2 kB With provenance Details for cfn_typed-0.3.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for cfn-typed 0.3.2
File Interpreter ABI Platform Actions
cfn_typed-0.3.2-py3-none-any.whl Python 3 none any Details for cfn_typed-0.3.2-py3-none-any.whl

Total release size: 540.4 kB

Release files / cfn_typed-0.3.2.tar.gz

Download URL cfn_typed-0.3.2.tar.gz
Size 405.2 kB
Tags Source
SHA-256 checksum
How to use checksums
b6df7c93c84d30a74dd27ee1810c4141affbde4b1eec87625b9dcbb96f8d84d1
BLAKE2b-256 checksum
How to use checksums
47176ecb83d8e8add86705db91c2c16ba5c1ec68b63168c65f0a0d866f914271
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / cfn_typed-0.3.2-py3-none-any.whl

Download URL cfn_typed-0.3.2-py3-none-any.whl
Size 135.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0e95720413ef5a0e9706cadca8ae9698b491fd2135628eebaf2fccaf7bbe33e3
BLAKE2b-256 checksum
How to use checksums
3341948d2d77aeb0ba254ed65ac6b19d3e973ba1e1d61c592179a35733ed00db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Security for cfn-typed 0.3.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for cfn_typed-0.3.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page