Create AWS Config custom rules by using AWS CloudFormation Guard policies
Created by Andrew Lok (AWS), Kailash Havildar (AWS), Nicole Brown (AWS), and Tanya Howell (AWS)
Code repository: aws-config-custom-rule-cloudformation-guard | Environment: PoC or pilot | Technologies: Security, identity, compliance; Management & governance |
AWS services: AWS CloudFormation; AWS Config |
Summary
AWS Config rules help you evaluate your AWS resources and their target configuration state. There are two types of AWS Config rules: managed and custom. Your can create custom rules with AWS Lambda functions or with AWS CloudFormation Guard
Rules created with Guard provide more granular control than managed rules, and they are typically easier to configure than fully custom Lambda rules. This approach provides engineers and architects the ability to build rules without needing to know Python, NodeJS, or Java, which are required to deploy custom rules through Lambda.
This pattern provides workable templates, code samples, and deployment approaches to help you adopt custom rules with Guard. By using this pattern, an administrator can use AWS Config to build custom compliance rules that have configuration item attributes. For example, developers can use Guard policies against AWS Config configuration items to continuously monitor the state of deployed AWS and non-AWS resources, detect rule violations, and automatically initiate remediation.
Objectives
After reading this pattern, you should be able to:
Understand how Guard policy code interacts with the AWS Config service.
Deploy Scenario 1, which is an AWS Config custom rule that uses Guard syntax to validate compliance for encrypted volumes. This rule verifies that the drive is in use and verifies that the drive type is gp3.
Deploy Scenario 2, which is an AWS Config custom rule that uses Guard syntax to validate Amazon GuardDuty compliance. This rule verifies that GuardDuty recorders have Amazon Simple Storage Service (Amazon S3) Protection and Amazon Elastic Kubernetes Service (Amazon EKS) Protection enabled.
Prerequisites and limitations
Prerequisites
An active AWS account
AWS Config, set up in your AWS account
Limitations
Guard custom rules are only able to query key-value pairs in a target configuration item JSON record
Architecture
You apply the Guard syntax to an AWS Config rule as a custom policy. AWS Config captures the hierarchical JSON of each of the resources specified. The JSON of the AWS Config configuration item contains key-value pairs. These attributes are used in the Guard syntax as variables that are assigned to their corresponding value.
The following is an explanation of the Guard syntax. The variables from the configuration item JSON are used and prepended with a %
character.
# declare variable let <variable name> = <'value'> # create rule and assign condition and policy rule <rule name> when <CI json key> == <"CI json value"> { <top level CI json key>.<next level CI json key> == %<variable name> }
Scenario 1: Amazon EBS volumes
Scenario 1 deploys an AWS Config custom rule that uses Guard syntax to validate compliance for encrypted volumes. This rule verifies that the drive is in use and verifies that the drive type is gp3.
The following is an example of an AWS Config configuration item for scenario 1. There are three key-value pairs in this configuration item that used as variables in the Guard policy: volumestatus
, volumeencryptionstatus
, and volumetype
. Also, the resourceType
key is used as a filter in the Guard policy.
{ "version": "1.3", "accountId": "111111111111", "configurationItemCaptureTime": "2023-01-15T19:04:45.402Z", "configurationItemStatus": "ResourceDiscovered", "configurationStateId": "4444444444444", "configurationItemMD5Hash": "", "arn": "arn:aws:ec2:us-west-2:111111111111:volume/vol-222222222222", "resourceType": "AWS::EC2::Volume", "resourceId": "vol-222222222222", "awsRegion": "us-west-2", "availabilityZone": "us-west-2b", "resourceCreationTime": "2023-01-15T19:03:22.247Z", "tags": {}, "relatedEvents": [], "relationships": [ { "resourceType": "AWS::EC2::Instance", "resourceId": "i-33333333333333333", "relationshipName": "Is attached to Instance" } ], "configuration": { "attachments": [ { "attachTime": "2023-01-15T19:03:22.000Z", "device": "/dev/xvda", "instanceId": "i-33333333333333333", "state": "attached", "volumeId": "vol-222222222222", "deleteOnTermination": true, "associatedResource": null, "instanceOwningService": null } ], "availabilityZone": "us-west-2b", "createTime": "2023-01-15T19:03:22.247Z", "encrypted": false, "kmsKeyId": null, "outpostArn": null, "size": 8, "snapshotId": "snap-55555555555555555", "state": "in-use", "volumeId": "vol-222222222222", "iops": 100, "tags": [], "volumeType": "gp2", "fastRestored": null, "multiAttachEnabled": false, "throughput": null, "sseType": null }, "supplementaryConfiguration": {} }
The following is an example of using Guard syntax to define the variables and rules in scenario 1. In the following example:
The first three lines define the variables by using the
let
command. They are assigned a name and value that is derived from the attributes of the configuration item.The
compliancecheck
rule block adds a when conditional dependency that looks for aresourceType
key-value pair that matchesAWS::EC2::Volume
. If a match is found, the rule proceeds through the rest of the JSON attributes and looks for matches on the following three conditions:state
,encrypted
, andvolumeType
.
let volumestatus = 'available' let volumetype = 'gp3' let volumeencryptionstatus = true rule compliancecheck when resourceType == "AWS::EC2::Volume" { configuration.state == %volumestatus configuration.encrypted == %volumeencryptionstatus configuration.volumeType == %volumetype }
For the complete Guard custom policy that implements this custom rule, see awsconfig-guard-cft.yaml
Scenario 2: GuardDuty compliance
Scenario 2 deploys an AWS Config custom rule that uses Guard syntax to validate Amazon GuardDuty compliance. This rule verifies that GuardDuty recorders have Amazon S3 Protection and Amazon EKS Protection enabled. It also verifies that GuardDuty findings are published every 15 minutes. This scenario could be deployed across all AWS accounts and AWS Regions in an organization (in AWS Organizations).
The following is an example of an AWS Config configuration item for scenario 2. There are three key-value pairs in this configuration item that used as variables in the Guard policy: FindingPublishingFrequency
, S3Logs
, and Kubernetes
. Also, the resourceType
key is used as a filter in the policy.
{ "version": "1.3", "accountId": "111111111111", "configurationItemCaptureTime": "2023-11-27T13:34:28.888Z", "configurationItemStatus": "OK", "configurationStateId": "7777777777777", "configurationItemMD5Hash": "", "arn": "arn:aws:guardduty:us-west-2:111111111111:detector/66666666666666666666666666666666", "resourceType": "AWS::GuardDuty::Detector", "resourceId": "66666666666666666666666666666666", "resourceName": "66666666666666666666666666666666", "awsRegion": "us-west-2", "availabilityZone": "Regional", "resourceCreationTime": "2020-02-17T02:48:04.511Z", "tags": {}, "relatedEvents": [], "relationships": [], "configuration": { "Enable": true, "FindingPublishingFrequency": "FIFTEEN_MINUTES", "DataSources": { "S3Logs": { "Enable": true }, "Kubernetes": { "AuditLogs": { "Enable": true } } }, "Id": "66666666666666666666666666666666", "Tags": [] }, "supplementaryConfiguration": { "CreatedAt": "2020-02-17T02:48:04.511Z" } }
The following is an example of using Guard syntax to define the variables and rules in scenario 2. In the following example:
The first three lines define the variables by using the
let
command. They are assigned a name and value that is derived from the attributes of the configuration item.The
compliancecheck
rule block adds a when conditional dependency that looks for aresourceType
key-value pair that matchesAWS::GuardDuty::Detector
. If a match is found, the rule proceeds through the rest of the JSON attributes and looks for matches on the following three conditions:S3Logs.Enable
,Kubernetes.AuditLogs.Enable
, andFindingPublishingFrequency
.
let s3protection = true let kubernetesprotection = true let publishfrequency = 'FIFTEEN_MINUTES' rule compliancecheck when resourceType == "AWS::GuardDuty::Detector" { configuration.DataSources.S3Logs.Enable == %s3protection configuration.DataSources.Kubernetes.AuditLogs.Enable == %kubernetesprotection configuration.FindingPublishingFrequency == %publishfrequency }
For the complete Guard custom policy that implements this custom rule, see awsconfig-guard-cft-gd.yaml
Tools
AWS services
AWS CloudFormation helps you set up AWS resources, provision them quickly and consistently, and manage them throughout their lifecycle across AWS accounts and Regions.
AWS Config provides a detailed view of the resources in your AWS account and how they’re configured. It helps you identify how resources are related to one another and how their configurations have changed over time.
Other tools
HashiCorp Terraform
is an open source infrastructure as code (IaC) tool that helps you use code to provision and manage cloud infrastructure and resources.
Code repository
The code for this pattern is available in the GitHub AWS Config with AWS CloudFormation Guard
Epics
Task | Description | Skills required |
---|---|---|
(Optional) Select key-value pairs for the rule. | Complete these steps if you are defining a custom Guard policy. If you are using one of the sample policies for scenario 1 or 2, skip these steps.
| AWS administrator, Security engineer |
Create the custom rule. | Using the key-value pairs that you identified previously or using one of the provided sample Guard policies, follow the instructions in Creating AWS Config Custom Policy Rules to create a custom rule. | AWS administrator, Security engineer |
Validate the custom rule. | Do one of the following to validate the custom Guard rule:
| AWS administrator, Security engineer |
Troubleshooting
Issue | Solution |
---|---|
Test the Guard policy outside of AWS Config | Unit testing can be done on your local device or in an integrated development environment (IDE), such as an AWS Cloud9 IDE. To perform unit testing, do the following:
|
Debug an AWS Config custom rule | In your Guard policy, change the |
Related resources
AWS documentation
Creating AWS Config Custom Policy Rules (AWS Config documentation)
Writing AWS CloudFormation Guard rules (Guard documentation)
AWS blog posts and workshops
Introducing AWS CloudFormation Guard 2.0
(AWS blog post)
Other resources
AWS CloudFormation Guard
(GitHub)