Infrastructure code can look correct and still introduce security problems. An Amazon S3 bucket might be created without the required encryption settings, a security group might allow access from anywhere, or a database might be deployed without deletion protection.
These issues are easy to miss when teams review infrastructure changes manually. As the number of CloudFormation templates grows, checking every resource against internal security standards becomes harder.
AWS CloudFormation Guard, commonly called cfn-guard, helps solve this problem by letting teams define infrastructure policies as code. Developers can validate CloudFormation templates against these policies before deploying resources.
This article explains how CloudFormation Guard works, how to write practical rules, and how to integrate policy validation into a development workflow.
What Is AWS CloudFormation Guard?
AWS CloudFormation Guard is a policy-as-code tool for evaluating structured data against rules defined by an organization. It is commonly used to check CloudFormation templates for compliance with security, operational, and governance requirements.
Instead of relying only on code reviews, a team can define rules such as:
- S3 buckets must use approved encryption settings.
- Resources must include required ownership and environment tags.
- Security groups must not expose administrative ports to the entire internet.
- Production databases must have deletion protection enabled.
- Resources must follow approved configuration standards.
When a template violates a rule, Guard reports the failure so the team can correct it before deployment.
The important distinction is that Guard validates configuration data. It does not deploy the infrastructure or automatically repair a noncompliant template.
CloudFormation Guard vs. Other Validation Tools
CloudFormation Guard is most useful when a team needs to enforce its own infrastructure policies consistently.
| Tool | Main purpose |
|---|
| CloudFormation Guard | Enforce organization-specific policies against templates or other supported structured data |
| CloudFormation template validation | Check whether a template is structurally valid for CloudFormation |
| cfn-lint | Identify CloudFormation template errors and potential issues using resource specifications and additional rules |
| AWS IAM Access Analyzer | Help identify certain IAM access and policy risks |
| AWS Config | Evaluate supported configuration rules against resources in an AWS environment |
These tools address different concerns. A template can pass structural validation but still violate an organization's policy. For example, an S3 bucket definition may be syntactically valid while failing an internal requirement for a particular encryption configuration.
Using Guard alongside template validation and deployment-time controls provides stronger coverage than relying on a single check.
Installing CloudFormation Guard
CloudFormation Guard is available as a command-line tool. Install it using a supported method for your operating system, following your organization's software installation requirements.
After installation, check that the command is available:
cfn-guard --version
Keep the tool version consistent across developer machines and CI environments. Differences between versions can cause confusing results when teams use different rule features or command options.
Before writing a large policy set, create a small rule and test it against a known template. This confirms that the installed version, rule syntax, and validation workflow are working as expected.
Creating Your First Guard Rule
Guard rules are written in a separate policy file, commonly using the .guard extension.
For example, create a file named rules.guard:
rule check_s3_bucket_encryption {
Resources.*[
Type == "AWS::S3::Bucket"
].Properties.BucketEncryption.ServerSideEncryptionConfiguration[*].ServerSideEncryptionByDefault.SSEAlgorithm
== "aws:kms"
}
This rule checks the encryption configuration of S3 bucket resources. It requires the selected encryption algorithm to be aws:kms.
The rule is intentionally strict. It does not treat every possible encryption configuration as compliant, and it does not automatically add missing properties to the template.
Before adopting this exact rule in production, test it against representative templates. Guard evaluates the data paths and conditions in the rule, so optional properties, missing values, and templates containing no matching resources need deliberate handling.
A rule that checks a property is not necessarily the same as a rule that requires the property to exist in every applicable resource.
Validating a CloudFormation Template
Suppose your CloudFormation template is stored in template.yaml.
Run the validation command:
cfn-guard validate \
--rules rules.guard \
--data template.yaml
Guard evaluates the template against the supplied rules and reports the result.
If the template violates a rule, review the reported resource path and policy condition. Correct the template or revise the rule if the policy does not accurately represent the intended requirement.
For example, a team may decide that its policy allows both AWS-managed encryption and customer-managed AWS Key Management Service keys. In that case, a rule that permits only aws:kms might need to be adjusted to represent the approved alternatives.
Do not weaken a rule simply because it produces failures. First determine whether the template is noncompliant or the rule does not correctly represent the intended policy.
Enforcing Required Resource Tags
Tags help teams identify resource ownership, environments, applications, and cost centers. A consistent tagging policy is especially useful when many teams share an AWS account.
Consider a policy requiring resources to have an Environment tag.
A rule can check the tag configuration of supported resources. For CloudFormation templates, the exact rule depends on the resource types and their tag representations. Some resources use a Tags list, while others expose different properties or do not support tags in the same way.
A simplified rule pattern for resources with a conventional Tags list is:
rule resources_should_have_environment_tag {
Resources.*[
Type == "AWS::S3::Bucket"
].Properties.Tags[*].Key
CONTAINS "Environment"
}
This pattern checks whether the selected S3 bucket resources include a tag with the required key. It does not check whether the tag has an approved value.
For example, if the organization permits only Development, Staging, and Production, add a separate value check and test it against templates that contain missing tags, empty tag lists, and multiple tag entries.
For broader enforcement, define policies for each relevant resource category rather than assuming all CloudFormation resources use the same tagging structure.
Preventing Risky Security Group Rules
Security groups deserve special attention because a broad ingress rule can expose a service unintentionally.
For example, an SSH rule allowing inbound traffic from 0.0.0.0/0 makes the port reachable from any IPv4 address, subject to other network and service controls.
A policy should identify prohibited combinations of protocol, port range, and source CIDR. The exact rule must account for the CloudFormation representation of SecurityGroupIngress and ingress rules embedded in a security group resource.
A policy review should consider at least these cases:
- Administrative ports exposed to all IPv4 addresses.
- Administrative ports exposed to all IPv6 addresses.
- Rules that permit all protocols.
- Broad access introduced through referenced security groups or other networking resources.
Do not rely on a single check for port 22. Windows administration, databases, internal applications, and other services may also be exposed by overly broad rules.
Where possible, compare the template against an approved set of network access patterns. Use additional AWS controls to enforce network boundaries after deployment.
Handling Missing and Optional Properties
One common mistake is assuming every resource has every property.
CloudFormation templates often omit optional properties and may use intrinsic functions such as Ref, Fn::Sub, and Fn::If. A value may therefore be represented by an expression rather than a literal string.
For example:
Resources:
ApplicationBucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: aws:kms
This resource specifies the encryption configuration directly.
In a different template, the algorithm might depend on a parameter or condition. A rule that expects a literal aws:kms value may not be able to establish compliance from the template alone.
When writing policies, decide how to handle such cases:
- Require literal values where the policy demands a fixed configuration.
- Allow approved parameterized values when the rule can evaluate them reliably.
- Reject unresolved configurations when the organization requires proof of compliance.
- Add deployment-time controls when the final value cannot be established through static template analysis.
Test policies against both compliant and noncompliant examples. Include templates with missing properties and conditional resource definitions so the team understands how the rules behave.
Integrating Guard Into CI/CD
Running Guard manually is useful during development, but automated validation provides more consistent enforcement.
A typical pipeline can perform these checks before deployment:
- Check out the infrastructure repository.
- Install or select a pinned CloudFormation Guard version.
- Validate template syntax and structure.
- Run Guard against the relevant rule files and templates.
- Stop the pipeline if mandatory policies fail.
- Deploy only after the required checks pass.
For example, a pipeline step can run:
cfn-guard validate \
--rules policies/security.guard \
--data infrastructure/template.yaml
Use the correct paths for the repository and keep the policy files under version control.
For larger repositories, organize rules by purpose:
infrastructure/
templates/
application.yaml
database.yaml
policies/
security.guard
tagging.guard
production.guard
This structure separates infrastructure definitions from the policies used to evaluate them.
A production pipeline should also make failures understandable. Developers need to know which resource violated which policy and what configuration is expected. Clear error reporting reduces the temptation to bypass validation.
Testing and Maintaining Policy Rules
Policy files are code and should be reviewed and tested like application code.
A rule can be too strict, too broad, or ineffective because it checks the wrong data path. Testing only one compliant template will not reveal all these problems.
A useful test suite should include:
- A template that satisfies the policy.
- A template that violates the policy.
- A template where the relevant property is missing.
- A template with multiple resources of the same type.
- A template that uses parameters or conditions.
- A template that contains no resources covered by the rule.
CloudFormation Guard provides rule-testing capabilities in addition to template validation. Use the testing command and test-data format supported by the installed Guard version to verify both passing and failing cases.
Review policy changes carefully. A change that makes a rule pass more templates may have weakened enforcement rather than improved compliance.
Common Mistakes to Avoid
Treating Guard as a deployment engine
Guard evaluates data against rules. It does not deploy resources, correct configuration automatically, or replace AWS permissions and runtime controls.
Ignoring resources that do not match a rule
A policy intended to cover every applicable resource must account for missing properties, empty resource collections, and different resource representations. Verify that an absent resource or property does not unintentionally bypass the intended requirement.
Enforcing every policy immediately
Introducing many blocking rules into an existing repository can stop development unexpectedly. Begin with a clear baseline, identify current violations, and agree on how exceptions will be handled before making every policy mandatory.
Allowing permanent exceptions without review
Some resources may have legitimate reasons to differ from standard policy. Document exceptions, identify their owners, and review them periodically instead of silently weakening shared rules.
Relying only on template validation
A template that passes Guard may still fail during deployment or become noncompliant later. Combine policy-as-code checks with CloudFormation validation, appropriate security analysis, AWS permissions, and runtime configuration monitoring.
Best Practices for Production Teams
Use these practices to make CloudFormation Guard effective across multiple projects:
- Store policies in version control alongside infrastructure code or in a centrally maintained policy repository.
- Pin the Guard version used by developer machines and CI pipelines.
- Use small, clearly named rules that represent specific requirements.
- Test rules against both valid and invalid templates.
- Document why each mandatory policy exists.
- Make CI failures actionable by reporting the affected resource and failed condition.
- Review policy exceptions and retire them when they are no longer needed.
- Keep static validation separate from deployment permissions and runtime security controls.
The goal is not to create the largest possible policy file. It is to make important infrastructure requirements repeatable, testable, and difficult to bypass accidentally.
Advantages and Limitations
CloudFormation Guard helps teams apply the same infrastructure standards across repositories and environments. It reduces dependence on manual reviews, supports automated CI/CD checks, and makes policy changes easier to track.
However, its effectiveness depends on the quality of the rules. A policy may miss a risky configuration if it checks the wrong property, ignores an alternate representation, or fails to account for intrinsic functions. Guard also cannot prove that every runtime behavior is safe merely by examining a template.
Teams should treat Guard as one part of a broader infrastructure security process.
Summary
AWS CloudFormation Guard allows teams to express infrastructure requirements as rules and validate CloudFormation templates before deployment. It can help enforce standards for encryption, tagging, network access, and other configuration requirements.
Start with a small set of important policies, test them against representative templates, and integrate validation into CI/CD. Pay particular attention to optional properties, conditional values, and resources that do not match the expected structure.
When policies are clearly defined and consistently enforced, infrastructure reviews become more reliable, and teams can catch many configuration problems before they reach an AWS environment.
Join the conversation! Your thoughts help the community grow.