AWS Cloud Operations Blog

AWS Config Rule Development Kit library: Build and operate rules at scale

AWS would like to introduce you to the RDKLib, an open source Python library you can use to build, develop, and deploy custom AWS Config rules at scale.

RDKLib works with the AWS Config Rule Development Kit. It is designed to work at the AWS Lambda layer, so you can use the library without needing to include it in your deployment package.

In this blog post, I show you how to use the RDK to build a custom AWS Config rule and then deploy it with the RDKLib.

Prerequisites

Before you follow along with the solution in this post:

Create a rule using the RDK

Use rdk create <rulename> –runtime <runtime> to create a local rule folder that contains your initial rule code, along with some helper code. To use RDKLib, the runtime of your RDK rule must be set to python3.6-lib. 

  • For a periodic trigger:
rdk create YOUR_RULE_NAME --runtime python3.6-lib --maximum-frequency TwentyFour_Hours
  • For a configuration change trigger (for example, an EC2 instance)
rdk create YOUR_RULE_NAME --runtime python3.6-lib --resource-types AWS::EC2::Instance

Note: When you build AWS RDK rules, the evaluation can report back on valid AWS resource types only (for example, AWS::EC2::Instance).

For examples and information about options available for each of the arguments, see the RDK GitHub repo.

Now, I show you how to create a rule to check whether AWS Security Hub is enabled for an AWS account. This is a periodic rule with a frequency of 24 hours. I have already created the code snippets you will need, you can download the files from this Github repository.

Download the Rule and Edit According to your environment

As shown below, the contents of the rule folder include parameters.json and SECURITYHUB_ENABLED.py

By default, the Lambda functions attempt to assume the AWSServiceRoleForConfig role, which is not allowed. If you are using the default service role with AWS Config, you must create a role with the AWS_ConfigRole managed policy. The role must have a trust relationship with AWS Config and all roles under the /rdk/ path to assume the role. (IAM roles for Lambda functions deployed through the RDK are created under this path.)

Here is the trust policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "config.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringLike": {
          "aws:PrincipalArn": "arn:aws:iam::123456789012:role/rdk/*"
        }
      }
    }
  ]
}

Now update the parameters.json file to add the input parameter for the execution role name and its value.

{
  "Version": "1.0",
  "Parameters": {
    "RuleName": "SECURITYHUB_ENABLED",
    "SourceRuntime": "python3.6-lib",
    "CodeKey": "SECURITYHUB_ENABLED.zip",
    "InputParameters": "{\"ExecutionRoleName\": \"YOUR_ROLE_NAME\"}",
    "OptionalParameters": "{}",
    "SourcePeriodic": "TwentyFour_Hours"
  },
  "Tags": "[]"
}

Install the RDKLib layer

You can use the console or the AWS CLI to install the RDKLib layer.

Install the RDKLib layer using the AWS Management Console.

  1. Open the AWS Lambda console.
  2. Select Create function.

      3. On the Create function page, select Browse serverless app repository, and in the search field, enter rdklib.

  1. Review the function details and then deploy it.

  1. On the Layers page, copy the ARN of the Lambda layer. As shown in figure 6, you can see the Layer Name, Version, Version ARN and Runtimes on this page.

 

Install the RDKLib layer using the AWS CLI.

  1. Run the following command to create the changeset.
aws serverlessrepo create-cloud-formation-change-set --application-id arn:aws:serverlessrepo:ap-southeast-1:711761543063:applications/rdklib --stack-name RDKlib-Layer

It returns the following output:

{
    "ApplicationId": "arn:aws:serverlessrepo:ap-southeast-1:711761543063:applications/rdklib",
    "ChangeSetId": "arn:aws:cloudformation:us-east-1:123456789012:changeSet/a3d536322-585e-4ffd-9e2f-552c8b887d6f/ffe7ff5c-ab38-4ab9-b746-9c1617ca95c1",
    "SemanticVersion": "0.1.0",
    "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/serverlessrepo-RDKlib-Layer/365436a0-a58a-11ea-9b04-12ae8fb95b53"
}

      2. Execute the changeset.

Copy/paste the full change-set ARN to customize the following command (ChangeSetId from the output generated in the previous step)

aws cloudformation execute-change-set --change-set-name NAME_OF_THE_CHANGE_SET
  1. Run the following command to return all the associated resources that are part of the stack deployed in the previous step.
aws cloudformation describe-stack-resources --stack-name serverlessrepo-RDKlib-Layer

It returns the following output:

{
    "StackResources": [
        {
            "StackName": "serverlessrepo-RDKlib-Layer",
            "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/serverlessrepo-RDKlib-Layer/365436a0-a58a-11ea-9b04-12ae8fb95b53",
            "LogicalResourceId": "RdklibLayercf22317faf",
            "PhysicalResourceId": "arn:aws:lambda:us-east-1:123456789012:layer:rdklib-layer:1",
            "ResourceType": "AWS::Lambda::LayerVersion",
            "Timestamp": "2020-06-03T11:26:30.501Z",
            "ResourceStatus": "CREATE_COMPLETE",
            "DriftInformation": {
                "StackResourceDriftStatus": "NOT_CHECKED"
            }
        }
    ]
}
  1. Copy the ARN of the Lambda layer from the output generated in the previous step.

 “PhysicalResourceId” key (that is, arn:aws:lambda:YOUR_REGION:YOUR_ACCOUNT:layer:rdklib-layer:1).

Deploy your rule with the RDKLib layer

Navigate to the directory where your rule folder is stored. It should look like this:

ls
SECURITYHUB_ENABLED
ls -ahR SECURITYHUB_ENABLED/
.			..					SECURITYHUB_ENABLED.py	parameters.json

Here is the command to deploy the rule with the RDKLib layer:

rdk deploy YOUR_RULE_NAME --rdklib-layer-arn YOUR_RDKLIB_LAYER_ARN

Now run the command to deploy the SECURITYHUB_ENABLED rule. It returns the following output:

Running deploy!
Found Custom Rule.
Zipping SECURITYHUB_ENABLED
Uploading SECURITYHUB_ENABLED
Upload complete.
Creating CloudFormation Stack for SECURITYHUB_ENABLED
Waiting for CloudFormation stack operation to complete...
Waiting for CloudFormation stack operation to complete...
Waiting for CloudFormation stack operation to complete...
Waiting for CloudFormation stack operation to complete...
Waiting for CloudFormation stack operation to complete...
Waiting for CloudFormation stack operation to complete...
Waiting for CloudFormation stack operation to complete...
Waiting for CloudFormation stack operation to complete...
Waiting for CloudFormation stack operation to complete...
CloudFormation stack operation complete.
Config deploy complete.

The rule is now deployed. You can use the AWS Config Console to verify that the rule is working as expected.

Conclusion

The RDKLib helps you to build and operate custom AWS Config rules at scale. It can be used to:

  • Reduce the maintenance effort by moving boilerplate code to an AWS Lambda layer.
  • Reduces the level of effort for developing and deploying Config rules by integrating with AWS Config Rule Development Kit (RDK) and using the AWS Serverless Application Repository.
  • Keep the RDK common functions in the same version, preventing the existence of multiple versions due to manual changes made by developers.

About the author

Sandeep Batchu

Sandeep Batchu

Sandeep Batchu is a Senior Security Consultant with Amazon Web Services. His background includes software engineering, solutions architecture, and security. Sandeep has a passion for helping customers connect business outcomes with technology and assisting customers throughout their cloud journey, helping them design secure, scalable, flexible, and resilient architectures