Write AWS Config rules using cfn-guard
Tags: cfnguard, awsconfig, compliance, security
Published: 2023-02-09 07:08:44

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](https://aws.amazon.com/about-aws/whats-new/2022/08/build-aws-config-rules-cloudformation-guard/) you have the ability to use [cfn-guard](https://github.com/aws-cloudformation/cloudformation-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](https://www.meetup.com/aws-ams/events/286638453/). 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:

```json
{
  "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"} }
        ]
    }
  }
}
```

A CloudFormation template has the following structure:

```json
{
    "Resources": {
        "NonCompliantBucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {
                "BucketEncryption": {
                    "ServerSideEncryptionConfiguration": [
                        {
                            "ServerSideEncryptionByDefault": {
                                "SSEAlgorithm": "aws:kms"
                            }
                        }
                    ]
                }
            }
        },
        "OtherResource": { ... }
    }
}
```

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.
1. You can use a `pre-commit` hook, this will prevent you from committing non-compliant code.
1. You can run it during your Continuous Integration step. This prevents merging non-compliant code in your develop/main branches.
1. 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](https://github.com/Nr18/aws-meetup-2022-11-08) GitHub repository.

Photo by [Joshua Miranda](https://www.pexels.com/photo/similar-cubes-with-rules-inscription-on-windowsill-in-building-4027658/)