Skip to content

Instantly share code, notes, and snippets.

@atheiman
Last active December 4, 2024 01:18
Show Gist options
  • Save atheiman/4a7a4dd48291a5aa453c44748c7b7c57 to your computer and use it in GitHub Desktop.
Save atheiman/4a7a4dd48291a5aa453c44748c7b7c57 to your computer and use it in GitHub Desktop.
AWS Config custom policy rule using Guard to evaluate tag compliance. Deployed as an OrganizationConfigRule w/ Terraform
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}
resource "aws_config_organization_custom_policy_rule" "required_tags" {
name = "required-tags"
description = "Evaluate tag compliance using custom Guard policy rule"
# Resource types: https://docs.aws.amazon.com/config/latest/developerguide/resource-config-reference.html
resource_types_scope = [
"AWS::EC2::Instance",
"AWS::RDS::DBCluster",
"AWS::RDS::DBInstance",
"AWS::S3::Bucket",
]
trigger_types = [
"ConfigurationItemChangeNotification",
"OversizedConfigurationItemChangeNotification",
]
policy_runtime = "guard-2.x.x"
policy_text = <<-EOF
rule tags_Application_exists {
tags["Application"] exists
<< Tag "Application" value must not be empty >>
}
rule tags_Application when tags_Application_exists {
tags["Application"] !empty
<< Tag "Application" value must not be empty >>
}
rule tags_Owner_exists {
tags["Owner"] exists
<< Tag "Owner" value must be a valid "example.com" email address >>
}
rule tags_Owner when tags_Owner_exists {
tags["Owner"] == /^[\w_][email protected]$/
<< Tag "Owner" value must be a valid "example.com" email address >>
}
rule tags_Environment_exists {
tags["Environment"] exists
<< Tag "Environment" value must be "nonprod" or "prod" >>
}
rule tags_Environment when tags_Environment_exists {
tags["Environment"] == /^(nonprod|prod)$/
<< Tag "Environment" value must be "nonprod" or "prod" >>
}
EOF
}

The cfn-guard cli includes commands to experiment with cloudformation-guard rules locally. To use the tool specifically for Config rule testing:

  1. Create rule.guard with your rule code
  2. Create resource.json with a Config resource json to evaluate against (you can copy this from a resource in the Config console)
  3. Use the cfn-guard validate command to show which rules PASS and which FAIL
cfn-guard validate -r ./rule.guard -d ./resource.json --verbose

There is also a unit testing framework in Guard that uses a rule.guard file and a test.yml file specifying your tests. Here is a short test.yml example:

# test.yml

- name: TagsTest
  input:
    # `input` is a yaml-formatted, trimmed-down version of a Config resource.
    # We only care about the `.tags` top-level property in this test case.
    tags:
      Owner: austin
      Environment: qa
  expectations:
    rules:
      tags_Application_exists: PASS # PASS | FAIL
      tags_Application: PASS
      tags_Owner_exists: PASS
      tags_Owner: PASS
      tags_Environment_exists: PASS
      tags_Environment: PASS

Use the cfn-guard test to execute your tests to show which rules are passing and which are failing:

cfn-guard test --rules-file ./rule.guard --test-data ./test.yml --verbose
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment