Saturday, October 22, 2022

Build Custom AWS Config rules using Guard DSL

I want to use AWS config to report S3 buckets without public blocking enabled except for some buckets with prefix like www, there is a AWS managed rule which can achieve this with a limitation: the excluded buckets must be provided as exact names separated by comma, regex match is not supported.

 

Previously, to create a custom rule, you would have to define an AWS Lambda function, from June 2022, you can author AWS Config custom rules using Guard DSL without needing to develop AWS Lambda functions.

 

What is Guard DSL?

Guard DSL is open-source policy-as-code domain-specific language (DSL) to write rules and validate JSON- and YAML-formatted data such as CloudFormation Templates, K8s configurations, and Terraform JSON plans/configurations against those rules. It is language developed by CloudFormation Guard project.

 Ignore the word CloudFormation here, Guard DSL is mainly used for validating CloudFormation template, but in the AWS config context, it has nothing to do with CloudFormation.

 

Get started with Guard DSL

Learn Guard DSL syntax

Ignore all object reference name from above document, the names are CloudFormation Objects. For the purpose of AWS config, refer to aws-config-resource-schema 

Sample AWS Config Rule with Guard DSL.

Create AWS Config Rule->Create custom rule using Guard

Scope of changes ->Resource Type(S3 Buckets)

Rule Content: 

rule s3_bucket_is_public when
    resourceType == "AWS::S3::Bucket" configuration.name != /^www/ {
        supplementaryConfiguration.PublicAccessBlockConfiguration.blockPublicPolicy exists
        supplementaryConfiguration.PublicAccessBlockConfiguration.blockPublicAcls exists
        supplementaryConfiguration.PublicAccessBlockConfiguration.restrictPublicBuckets exists
        supplementaryConfiguration.PublicAccessBlockConfiguration.ignorePublicAcls exists
    }

rule s3_bucket_not_public when
    s3_bucket_is_public {
    supplementaryConfiguration.PublicAccessBlockConfiguration {
        blockPublicAcls == true
        blockPublicPolicy == true
        restrictPublicBuckets == true
        ignorePublicAcls == true
    }
}
The rules are evaluated in order, evaluation continues regardless the result of previous rule.
PublicAccessBlockConfiguration block  has  conditions separated by new line, which implies AND
Please note the first rule name is being used as condition in the second rule

- when bucket with www prefix is being evaluated, the result is not_applicable for both conditions.
- when bucket with public blocking enabled is being evaluated, the result is compliant for both conditions
- when bucket without public blocking enabled is being evaluated, 1st rule result is not_compliant, 2nd rule result is not_applicable. effective result is not_compliant