Ensuring Compliance with Custom AWS Config Rules
Tags: aws, security, compliance, optimization
Published: 2023-08-14 07:23:13

In today's data-driven world, ensuring compliance with industry regulations and internal policies has become a top priority for organisations. While many organisations implement standard compliance measures, custom Config Rules offer a more tailored approach to meet specific requirements. In this blog post we will discuss the importance of custom Config Rule for compliance and provide examples of custom Config Rules using AWS CloudFormation Guard 2.0 and Lambda.

Why Custom Config Rules are Important for Compliance
----------------------------------------------------

Basic security and governance are provided by standard compliance measures, protecting organizations with a minimum level of security. But businesses operate in different environments, each with unique characteristics. One-size-fits-all compliance frameworks may not meet specific requirements, possibly leaving vulnerabilities unattended. This is where personalised Config Rules come into play, offering bespoke solutions that match an organisation's unique requirements.

*   **Accurate Management of Risks**: Personalised Config Rules allow organisations to precisely address potential risks and vulnerabilities that are specific to their operations. When adjusting compliance efforts to their specific context, businesses can effectively reduce threats and improve their security status.
*   **Alignment to standards in the industry**: Many fields have unique rules and standards that extend beyond standard compliance frameworks. Organisations can adjust custom Config Rules to satisfy these industry-specific demands without violating complying to broader regulations.
*   **Adjusting to Change**: The business world changes constantly, and as organisations develop, so do the risks they face. Tailored setup regulations can be modified and improved with ease to incorporate changes in technology, operations, and regulations, thereby guaranteeing consistent enforcement in a flexible setting.

![Blog Content](https://globaldatanet.com/images/cms/928404bb5cc8cf2a2c577dd5d539abd540820299-265x245.webp)

AWS CloudFormation Guard 2.0: Empowering Custom Config Rules
------------------------------------------------------------

  
AWS CloudFormation Guard 2.0 is a powerful tool that helps organizations adhere to compliance requirements with custom Config Rules. This open-source project provides a language that facilitates developers and security teams to establish and enforce compliance rules for infrastructure-as-code. With a user-friendly syntax, CloudFormation Guard 2.0 enables organizations to efficiently and clearly define their compliance requirements.

### **Examples of Custom Config Rules with CloudFormation Guard 2.0**

#### GuardDuty Settings

The following CloudFormation snippet for a custom Config Rule using AWS CloudFormation Guard 2.0, checks whether GuardDuty has S3 protection enabled, Kubernetes protection enabled and Findings are published every 15 minutes.

      CustomGuardDutySettings:
        Type: AWS::Config::ConfigRule
        Properties: 
          ConfigRuleName: GuardDutySettings
          Description: Compliant if GuardDuty has S3 protection enabled, Kubernetes protection enabled AND Findings are published every 15 minutes.
          Scope:
            ComplianceResourceTypes: 
              - "AWS::GuardDuty::Detector"
          Source:
            Owner: CUSTOM_POLICY
            CustomPolicyDetails:
              EnableDebugLogDelivery: "True"
              PolicyRuntime: guard-2.x.x
              PolicyText: |
                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
                        }
            SourceDetails: 
            - 
              EventSource: "aws.config"
              MessageType: "ConfigurationItemChangeNotification"


#### Apache Kafka (MSK) Broker Encryption at rest

The following CloudFormation snippet for a custom Config Rule using AWS CloudFormation Guard 2.0, creates a Config Rule to check whether Amazon Managed Streaming for Apache Kafka (MSK) data volume is encrypted.

      CustomMskBrokerEncryptionAtRest:
        Type: AWS::Config::ConfigRule
        Properties:
          ConfigRuleName: CUSTOM-MSK-BROKER-ENCRYPTION-AT-REST
          Description: Checks whether MSK has at the broker volume encryption at rest active
          Scope:
            ComplianceResourceTypes:
              - "AWS::MSK::Cluster"
          Source:
            Owner: "CUSTOM_POLICY"
            CustomPolicyDetails:
              EnableDebugLogDelivery: false
              PolicyRuntime: guard-2.x.x
              PolicyText:
                !Sub |
                rule check_resource_type {
                    resourceType == "AWS::MSK::Cluster"
                }
                rule check_broker_encryption_at_rest when check_resource_type {
                  let kmsKey = configuration.EncryptionInfo.EncryptionAtRest.DataVolumeKMSKeyId
                  %kmsKey == /arn:aws:kms:\w+(?:-\w+)+:\d{12}:key\/(?:[-a-z0-9]+)/
                }
            SourceDetails:
              -
                EventSource: aws.config
                MessageType: ConfigurationItemChangeNotification


### Limitations of AWS CloudFormation Guard 2.0 when using it for custom Config Rules:

*   **Simplicity:** CloudFormation Guard 2.0 has been developed to be simple and straightforward when defining compliance rules. However, this simplicity can be a disadvantage when handling complex compliance requirements that include complicated logic, multiple conditions or dependencies on resources.
*   **Flexibility of rules:** The flexibility of the rule definitions in CloudFormation Guard 2.0 is somewhat limited when compared to more comprehensive programming languages. If you need to implement complex calculations or evaluations for advanced rules, you may find the syntax of CloudFormation Guard 2.0 restrictive.
*   **Dynamic data retrieval is not possible:** CloudFormation Guard 2.0 can't fetch data from external sources or make API calls to gather information for rule evaluations. This limitation makes it difficult to create rules that depend on real-time data from APIs or external sources, especially when compliance mandates it.
*   **AWS Config Limitation:** It should be noted that while AWS CloudFormation Guard offers support for array and regex functionalities, AWS Config may currently lack the capability to evaluate all of them.

### **Example of Custom Config Rule using Lambda**

The following CloudFormation snippet for a custom Config Rule backed by AWS Lambda, checks whether any resource tag contains an phone number or an email.

      DsgvoConfigRuleFunction:
        Type: AWS::Lambda::Function
        Properties:
          FunctionName:
            Fn::Sub: DsgvoConfigRuleFunction-${AWS::Region}
          Description: Checks for Email and Phone in Ressource Tags
          Code:
            ZipFile: |-
              import json
              import boto3
              import re
              import os
              
              def find_violation(current_tags):
                  violation = ""
                  for tag in current_tags:
                      if tag['value'] != "":
                          phoneregex = r"(^\+49+[0-9]*|^49+[0-9]*|^01+[0-9]*|^\+01+[0-9]*)"
                          if re.match(phoneregex, tag['value']):
                              violation += f"- found phone number in Tag: {tag['key']} "
                          emailregex = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
                          if re.match(emailregex, tag['value']):
                              violation += f" - found E-mail address in Tag: {tag['key']} "
                  return  violation
              
              def evaluate_compliance(configuration_item):
                  if configuration_item["configurationItemStatus"] == "ResourceDeleted" or os.environ['AWS_DEFAULT_REGION'] != configuration_item["awsRegion"]:
                      return {
                          "compliance_type": "NOT_APPLICABLE",
                          "annotation": "The configurationItem was deleted and therefore cannot be validated."
                      }
                  violation = None
                  current_tags = configuration_item["configuration"].get("tags")
                  if current_tags != None or current_tags == "":
                      violation = find_violation(current_tags)
                  if violation:
                      return {
                          "compliance_type": "NON_COMPLIANT",
                          "annotation": violation[:255]
                      }
              
                  return {
                      "compliance_type": "COMPLIANT",
                      "annotation": "The tags of this resource are DSGVO compliant."
                  }
              
              def handler(event, context):
                  invoking_event = json.loads(event["invokingEvent"])
                  configuration_item = invoking_event["configurationItem"]
                  result_token = "No token found."
                  if "resultToken" in event:
                      result_token = event["resultToken"]
              
                  
                  evaluation = evaluate_compliance(configuration_item)
              
                  config = boto3.client("config")
                  config.put_evaluations(
                      Evaluations=[
                          {
                              "ComplianceResourceType":
                                  configuration_item["resourceType"],
                              "ComplianceResourceId":
                                  configuration_item["resourceId"],
                              "ComplianceType":
                                  evaluation["compliance_type"],
                              "Annotation":
                                  evaluation["annotation"],
                              "OrderingTimestamp":
                                  configuration_item["configurationItemCaptureTime"]
                          },
                      ],
                      ResultToken=result_token)
    
          Handler: index.handler
          Runtime: python3.11
          Role:
            Fn::GetAtt:
              - DsgvoConfigRuleRole
              - Arn
          Timeout: 60
      CustomDsgvoTags:
        Type: AWS::Config::ConfigRule
        Properties:
          ConfigRuleName: CUSTOM-DSGVO-TAGS
          Description: Checks whether no sensitive data from employees are added into Tags are set
          Source:
            Owner: "CUSTOM_LAMBDA"
            SourceDetails:
              -
                EventSource: aws.config
                MessageType: ConfigurationItemChangeNotification
            SourceIdentifier: !Sub 'arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:DsgvoConfigRuleFunction-${AWS::Region}'


Conclusion
----------

In the time of data-based operations, it's important to have both compliance and customisation working together effectively. Although standard compliance measures are important, it is better for companies to have custom Config Rules that suit their unique needs and mitigate specific risks. AWS CloudFormation Guard 2.0 shines as a tool that empowers organizations to implement and enforce custom compliance rules seamlessly. However if you want to implement more complex checks you need to use Custom Config Rules backed by Lambda. Organizations can confidently move towards a secure and compliant future in the data-driven world by using custom Config Rules.