DEV Community

Cover image for Write AWS Config rules using cfn-guard
Joris Conijn for AWS Community Builders

Posted on • Originally published at binx.io

Write AWS Config rules using cfn-guard

AWS Config rules allow you to determine if a resource is compliant or not. Previously when you wanted to do custom checks you needed to write AWS Lambda functions to validate the configuration of a resource. Since Aug 2, 2022 you have the ability to use cfn-guard rules to achieve the same.

Why should I use cfn-guard

Writing a Lambda function is not difficult. But it becomes harder when you add unit testing. When you determine your compliancy status based on Lambda function, you want to ensure that it works as intended. This is the advantage of cfn-guard, you write a rule and you write some tests. These tests are a couple of snippets of yaml and per snippet you define if your rule should: PASS, FAIL or SKIP.

The other advantage of cfn-guard is that you have a single way of writing rules. On Nov 8, 2022 I gave a talk on this topic on the AWS User Group NL. In this talk I highlighted the differences between detective and preventive controls. Using cfn-guard rules in AWS Config is a detective control. But the same language can be used to build preventive controls!

Yes, I said language and not rules

It turns out that the rules written for AWS Config cannot be used to validate AWS CloudFormation templates. They are similar but different!
Where an AWS Config rule has the following structure:

{
  "version": "1.3",
  "arn": "arn:aws:s3:::aws-meetup-2022-11-08-noncompliantbucket-xxxxxxxxxxxxx",
  "resourceType": "AWS::S3::Bucket",
  "resourceId": "aws-meetup-2022-11-08-noncompliantbucket-xxxxxxxxxxxxx",
  "resourceName": "aws-meetup-2022-11-08-noncompliantbucket-xxxxxxxxxxxxx",
  "awsRegion": "eu-west-1",
  "supplementaryConfiguration": {
    "ServerSideEncryptionConfiguration": {
        "rules": [
            { "applyServerSideEncryptionByDefault": {"sseAlgorithm": "aws:kms"} }
        ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

A CloudFormation template has the following structure:

{
    "Resources": {
        "NonCompliantBucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {
                "BucketEncryption": {
                    "ServerSideEncryptionConfiguration": [
                        {
                            "ServerSideEncryptionByDefault": {
                                "SSEAlgorithm": "aws:kms"
                            }
                        }
                    ]
                }
            }
        },
        "OtherResource": { ... }
    }
}
Enter fullscreen mode Exit fullscreen mode

The first thing that you can see is that the AWS Config rule only has the context of the resource it validates. While the CloudFormation template has one or more resources. So you can compare the to locations as followed:

supplementaryConfiguration vs Resources > NonCompliantBucket > Properties

But looking closer you also notice that the structure and naming varies. Meaning you are doomed to maintain 2 types of rules. 1 for AWS Config (Detective) and 1 for CloudFormation (Preventive).

Why should you write a detective and a preventive rule?

The answer is to decrease your feedback cycle. For example, when you only have a detective rule you need to wait until the everything is deployed. Then you need to wait until a compliance issue pops up. When you use a preventive rule you can check this on different levels:

  1. You can run the cfn-guard rules at any time on your local development environment.
  2. You can use a pre-commit hook, this will prevent you from committing non-compliant code.
  3. You can run it during your Continuous Integration step. This prevents merging non-compliant code in your develop/main branches.
  4. You can run it before deployment to testing, acceptance and/or production.

Conclusion

cfn-guard is a great tool to write compliancy checks for both detective and preventive controls. Interested in a working sample? I published my demo material to the Nr18/aws-meetup-2022-11-08 GitHub repository.

Photo by Joshua Miranda

Top comments (0)