Package: rdk
AWS RDKAWS Config Rules Development KitWe greatly appreciate feedback and bug reports atrdk-maintainers@amazon.com! You may also create an issue on this repo.The RDK is designed to support a "Compliance-as-Code" workflow that is
intuitive and productive. It abstracts away much of the undifferentiated
heavy lifting associated with deploying AWS Config rules backed by
custom lambda functions, and provides a streamlined
develop-deploy-monitor iterative process.For complete documentation, including command reference, check out theReadTheDocs documentation.Getting StartedUses Python 3.7+ and is installed via pip. Requires you to have
an AWS account and sufficient permissions to manage the Config service,
and to create S3 Buckets, Roles, and Lambda Functions. An AWS IAM Policy
Document that describes the minimum necessary permissions can be found
atpolicy/rdk-minimum-permissions.json.Under the hood, rdk uses boto3 to make API calls to AWS, so you can set
your credentials any way that boto3 recognizes (options 3 through 8here)
or pass them in with the command-line parameters--profile,--region,--access-key-id, or--secret-access-keyIf you just want to use the RDK, go ahead and install it using pip.pipinstallrdkAlternately, if you want to see the code and/or contribute you can clone
the git repo, and then from the repo directory use pip to install the
package. Use the-eflag to generate symlinks so that any edits you
make will be reflected when you run the installed package.If you are going to author your Lambda functions using Java you will
need to have Java 8 and gradle installed. If you are going to author
your Lambda functions in C# you will need to have the dotnet CLI and the
.NET Core Runtime 1.08 installed.pipinstall-e.To make sure the rdk is installed correctly, running the package from
the command line without any arguments should display help information.rdk
usage:rdk[-h][-pPROFILE][-kACCESS_KEY_ID][-sSECRET_ACCESS_KEY][-rREGION][-fREGION_FILE][--region-setREGION_SET][-v]<command>...
rdk:error:thefollowingargumentsarerequired:<command>,<commandarguments>UsageConfigure your envTo use the RDK, it's recommended to create a directory that will be
your working directory. This should be committed to a source code repo,
and ideally created as a python virtualenv. In that directory, run theinitcommand to set up your AWS Config environment.rdkinit
Runninginit!
CreatingConfigbucketconfig-bucket-780784666283
CreatingIAMroleconfig-role
WaitingforIAMroletopropagate
ConfigServiceisON
Configsetupcomplete.
CreatingCodebucketconfig-rule-code-bucket-780784666283ap-southeast-1Runninginitsubsequent times will validate your AWS Config setup and
re-create any S3 buckets or IAM resources that are needed.If you have config delivery bucket already present in some other AWS account then use--config-bucket-exists-in-another-accountas argument.rdkinit--config-bucket-exists-in-another-accountIf you have AWS Organizations/ControlTower Setup in your AWS environment then additionally, use--control-toweras argument.rdkinit--control-tower--config-bucket-exists-in-another-accountIf bucket for custom lambda code is already present in current account then use--skip-code-bucket-creationargument.rdkinit--skip-code-bucket-creationIf you want rdk to create/update and upload the rdklib-layer for you, then use--generate-lambda-layerargument. In supported regions, rdk will deploy the layer using the Serverless Application Repository, otherwise it will build a local lambda layer archive and upload it for use.rdkinit--generate-lambda-layerIf you want rdk to give a custom name to the lambda layer for you, then use--custom-layer-namerargument. The Serverless Application Repository currently cannot be used for custom lambda layers.rdkinit--generate-lambda-layer--custom-layer-name<LAYER_NAME>Create RulesIn your working directory, use thecreatecommand to start creating a
new custom rule. You must specify the runtime for the lambda function
that will back the Rule, and you can also specify a resource type (or
comma-separated list of types) that the Rule will evaluate or a maximum
frequency for a periodic rule. This will add a new directory for the
rule and populate it with several files, including a skeleton of your
Lambda code.rdkcreateMyRule--runtimepython3.11--resource-typesAWS::EC2::Instance--input-parameters'{"desiredInstanceType":"t2.micro"}'Runningcreate!
LocalRulefilescreated.On Windows it is necessary to escape the double-quotes when specifying
input parameters, so the--input-parametersargument would instead
look something like this:'{\"desiredInstanceType\":\"t2.micro\"}'As of RDK v0.17.0, you can also specify--resource-types ALLto include all resource types.Note that you can create rules that use EITHER resource-types OR
maximum-frequency, but not both. We have found that rules that try to be
both event-triggered as well as periodic wind up being very complicated
and so we do not recommend it as a best practice.Edit Rules LocallyOnce you have created the rule, edit the python file in your rule
directory (in the above example it would beMyRule/MyRule.py, but may
be deeper into the rule directory tree depending on your chosen Lambda
runtime) to add whatever logic your Rule requires in theevaluate_compliancefunction. You will have access to the CI that was
sent by Config, as well as any parameters configured for the Config
Rule. Your function should return either a simple compliance status (one
ofCOMPLIANT,NON_COMPLIANT, orNOT_APPLICABLE), or if you're
using the python or node runtimes you can return a JSON object with
multiple evaluation responses that the RDK will send back to AWS Config.An example would look like:forsginresponse['SecurityGroups']:evaluations.append({'ComplianceResourceType':'AWS::EC2::SecurityGroup','ComplianceResourceId':sg['GroupId'],'ComplianceType':'COMPLIANT','Annotation':'This is an important note.','OrderingTimestamp':str(datetime.datetime.now())})returnevaluationsThis is necessary for periodic rules that are not triggered by any CI
change (which means the CI that is passed in will be null), and also for
attaching annotations to your evaluation results.If you want to see what the JSON structure of a CI looks like for
creating your logic, you can userdksample-ci<ResourceType>to output a formatted JSON document.Write and Run Unit TestsIf you are writing Config Rules using either of the Python runtimes
there will be a<rule name>_test.pyfile deployed along with your
Lambda function skeleton. This can be used to write unit tests according
to the standard Python unittest framework (documentedhere), which can be
run using thetest-localrdk command:rdktest-localMyTestRule
Runninglocaltest!
TestingMyTestRule
Lookingfortestsin/Users/mborch/Code/rdk-dev/MyTestRule

---------------------------------------------------------------------

Ran0testsin0.000s

OK
<unittest.runner.TextTestResultrun=0errors=0failures=0>The test file includes setup for the MagicMock library that can be used
to stub boto3 API calls if your rule logic will involve making API calls
to gather additional information about your AWS environment. For some
tips on how to do this, check out this blog post:Mock Is MagicModify RuleIf you need to change the parameters of a Config rule in your working
directory you can use themodifycommand. Any parameters you specify
will overwrite existing values, any that you do not specify will not be
changed.rdkmodifyMyRule--runtimepython3.11--maximum-frequencyTwentyFour_Hours--input-parameters'{"desiredInstanceType":"t2.micro"}'Runningmodify!
ModifiedRule'MyRule'.Usethe`deploy`commandtopushyourchangestoAWS.Again, on Windows the input parameters would look like:'{\"desiredInstanceType\":\"t2.micro\"}'It is worth noting that until you actually call thedeploycommand
your rule only exists in your working directory, none of the Rule
commands discussed thus far actually makes changes to your account.Deploy RuleOnce you have completed your compliance validation code and set your
Rule's configuration, you can deploy the Rule to your account using thedeploycommand. This will zip up your code (and the other associated
code files, if any) into a deployable package (or run a gradle build if
you have selected the java8 runtime or run the Lambda packaging step
from the dotnet CLI if you have selected the dotnetcore1.0 runtime),
copy that zip file to S3, and then launch or update a CloudFormation
stack that defines your Config Rule, Lambda function, and the necessary
permissions and IAM Roles for it to function. Since CloudFormation does
not deeply inspect Lambda code objects in S3 to construct its changeset,
thedeploycommand will also directly update the Lambda function for
any subsequent deployments to make sure code changes are propagated
correctly.rdkdeployMyRule
Runningdeploy!
ZippingMyRule
UploadingMyRule
CreatingCloudFormationStackforMyRule
WaitingforCloudFormationstackoperationtocomplete...
...
WaitingforCloudFormationstackoperationtocomplete...
Configdeploycomplete.The exact output will vary depending on Lambda runtime. You can use the--allflag to deploy all of the rules in your working directory. If
you used the--generate-lambda-layerflag in rdk init, use the--generated-lambda-layerflag for rdk deploy.Deploy Organization RuleYou can also deploy the Rule to your AWS Organization using thedeploy-organizationcommand. For successful evaluation of custom rules
in child accounts, please make sure you do one of the following:Set ASSUME_ROLE_MODE in Lambda code to True, to get the Lambda to assume the Role attached on the Config Service and confirm that the role trusts the master account where the Lambda function is going to be deployed.Set ASSUME_ROLE_MODE in Lambda code to True, to get the Lambda to assume a custom role and define an optional parameter with key as ExecutionRoleName and set the value to your custom role name; confirm that the role trusts the master account of the organization where the Lambda function will be deployed.rdkdeploy-organizationMyRule
Runningdeploy!
ZippingMyRule
UploadingMyRule
CreatingCloudFormationStackforMyRule
WaitingforCloudFormationstackoperationtocomplete...
...
WaitingforCloudFormationstackoperationtocomplete...
Configdeploycomplete.The exact output will vary depending on Lambda runtime. You can use the--allflag to deploy all of the rules in your working directory. This
command usesPutOrganizationConfigRuleAPI for the rule deployment. If
a new account joins an organization, the rule is deployed to that
account. When an account leaves an organization, the rule is removed.
Deployment of existing organizational AWS Config Rules will only be
retried for 7 hours after an account is added to your organization if a
recorder is not available. You are expected to create a recorder if one
doesn't exist within 7 hours of adding an account to your organization.View Logs For Deployed RuleOnce the Rule has been deployed to AWS you can get the CloudWatch logs
associated with your Lambda function using thelogscommand.rdklogsMyRule-n52017-11-1522:59:33-STARTRequestId:96e7639a-ca15-11e7-95a2-b1521890638dVersion:$LATEST2017-11-1523:41:13-REPORTRequestId:68e0304f-ca1b-11e7-b735-81ebae95acdaDuration:0.50msBilledDuration:100msMemorySize:256MBMaxMemoryUsed:36MB2017-11-1523:41:13-ENDRequestId:68e0304f-ca1b-11e7-b735-81ebae95acda2017-11-1523:41:13-DefaultRDKutilityclassdoesnotyetsupportScheduledNotifications.2017-11-1523:41:13-STARTRequestId:68e0304f-ca1b-11e7-b735-81ebae95acdaVersion:$LATESTYou can use the-nand-fcommand line flags just like the UNIXtailcommand to view a larger number of log events and to continuously
poll for new events. The latter option can be useful in conjunction with
manually initiating Config Evaluations for your deploy Config Rule to
make sure it is behaving as expected.Running the testsThetestingdirectory contains scripts and buildspec files that I use
to run basic functionality tests across a variety of CLI environments
(currently Ubuntu Linux running Python 3.7/3.8/3.9/3.10, and Windows Server
running Python 3.10). If there is interest I can release a CloudFormation
template that could be used to build the test environment, let me know
if this is something you want!Advanced FeaturesCross-Account DeploymentsFeatures have been added to the RDK to facilitate the cross-account
deployment pattern that enterprise customers have standardized for
custom Config Rules. A cross-account architecture is one in which the
Lambda functions are deployed to a single central "Compliance" account
(which may be the same as a central "Security" account), and the
Config Rules are deployed to any number of "Satellite" accounts that
are used by other teams or departments. This gives the compliance team
confidence that their rule logic cannot be tampered with and makes it
much easier for them to modify rule logic without having to go through a
complex deployment process to potentially hundreds of AWS accounts. The
cross-account pattern uses two advanced RDK features:--functions-only(-f) deploymentcreate-rule-templatecommandFunctions-Only DeploymentBy using the-for--functions-onlyflag on thedeploycommand the
RDK will deploy only the necessary Lambda Functions, Lambda Execution
Role, and Lambda Permissions to the account specified by the execution
credentials. It accomplishes this by batching up all of the Lambda
function CloudFormation snippets for the selected Rule(s) into a single
dynamically generated template and deploy that CloudFormation template.
One consequence of this is that subsequent deployments that specify a
different set of rules for the same stack name will update that
CloudFormation stack, and any Rules that were included in the first
deployment but not in the second will be removed. You can use the--stack-nameparameter to override the default CloudFormation stack
name if you need to manage different subsets of your Lambda Functions
independently. The intended usage is to deploy the functions for all of
the Config rules in the Security/Compliance account, which can be done
simply by usingrdk deploy -f --allfrom your working directory.create-rule-template commandThis command generates a CloudFormation template that defines the AWS
Config rules themselves, along with the Config Role, Config data bucket,
Configuration Recorder, and Delivery channel necessary for the Config
rules to work in a satellite account. You must specify the file name for
the generated template using the--output-fileor-ocommand line flags. The generated template takes a
single parameter of the AccountID of the central compliance account that
contains the Lambda functions that will back your custom Config Rules.
The generated template can be deployed in the desired satellite accounts
through any of the means that you can deploy any other CloudFormation
template, including the console, the CLI, as a CodePipeline task, or
using StackSets. Thecreate-rule-templatecommand takes all of the
standard arguments for selecting Rules to include in the generated
template, including lists of individual Rule names, an--allflag, or
using the RuleSets feature described below.rdkcreate-rule-template-oremote-rule-template.json--all
GeneratingCloudFormationtemplate!
CloudFormationtemplatewrittentoremote-rule-template.jsonDisable the supported resource types checkIt is now possible to define a resource type that is not yet supported
by rdk. To disable the supported resource check use the optional flag
'--skip-supported-resource-check' during the create command.rdkcreateMyRule--runtimepython3.11--resource-typesAWS::New::ResourceType--skip-supported-resource-check'AWS::New::ResourceType'notfoundinlistofacceptedresourcetypes.
Skip-Supported-Resource-CheckFlagset(--skip-supported-resource-check),ignoringmissingresourcetypeerror.
Runningcreate!
LocalRulefilescreated.Custom Lambda Function NameAs of version 0.7.14, instead of defaulting the lambda function names toRDK-Rule-Function-<RULE_NAME>it is possible to customize the name for
the Lambda function to any 64 characters string as per Lambda's naming
standards using the optional--custom-lambda-nameflag while
performingrdk create. This opens up new features like :Longer config rule name.Custom lambda function naming as per personal or enterprise standards.rdkcreateMyLongerRuleName--runtimepython3.11--resource-typesAWS::EC2::Instance--custom-lambda-namecustom-prefix-for-MyLongerRuleName
Runningcreate!
LocalRulefilescreated.The above example would create files with config rule name asMyLongerRuleNameand lambda function with the namecustom-prefix-for-MyLongerRuleNameinstead ofRDK-Rule-Function-MyLongerRuleNameRuleSetsNew as of version 0.3.11, it is possible to add RuleSet tags to rules
that can be used to deploy and test groups of rules together. Rules can
belong to multiple RuleSets, and RuleSet membership is stored only in
the parameters.json metadata. Thedeploy,create-rule-template, andtest-localcommands are RuleSet-aware such that a RuleSet can be passed in as the
target instead of--allor a specific named Rule.A comma-delimited list of RuleSets can be added to a Rule when you
create it (using the--rulesetsflag), as part of amodifycommand,
or using newrulesetsubcommands to add or remove individual rules
from a RuleSet.Runningrdk rulesets listwill display a list of the RuleSets
currently defined across all of the Rules in the working directoryrdkrulesetslist
RuleSets:AnotherRuleSetMyNewSetNaming a specific RuleSet will list all of the Rules that are part of
that RuleSet.rdkrulesetslistAnotherRuleSet
RulesinAnotherRuleSet:RSTestRules can be added to or removed from RuleSets using theaddandremovesubcommands:rdkrulesetsaddMyNewSetRSTest
RSTestaddedtoRuleSetMyNewSet

rdkrulesetsremoveAnotherRuleSetRSTest
RSTestremovedfromRuleSetAnotherRuleSetRuleSets are a convenient way to maintain a single repository of Config
Rules that may need to have subsets of them deployed to different
environments. For example your development environment may contain some
of the Rules that you run in Production but not all of them; RuleSets
gives you a way to identify and selectively deploy the appropriate Rules
to each environment.Managed RulesThe RDK is able to deploy AWS Managed Rules.To do so, create a rule usingrdk createand provide a valid
SourceIdentifier via the--source-identifierCLI option. The list of
Managed Rules can be foundhere, and note that the Identifier can be obtained by replacing the dashes
with underscores and using all capitals (for example, the
"guardduty-enabled-centralized" rule has the SourceIdentifier
"GUARDDUTY_ENABLED_CENTRALIZED"). Just like custom Rules you will need
to specify source events and/or a maximum evaluation frequency, and also
pass in any Rule parameters. The resulting Rule directory will contain
only the parameters.json file, but usingrdk deployorrdk create-rule-templatecan be used to deploy the Managed Rule like
any other Custom Rule.Deploying Rules Across Multiple RegionsThe RDK is able to run init/deploy/undeploy across multiple regions with
ardk -f <region file> -t <region set>If no region group is specified, rdk will deploy to thedefaultregion
set.To create a sample starter region group, runrdk create-region-setto
specify the filename, add the-o <region set output file name>this
will create a region set with the following tests and regions"default":["us-east-1","us-west-1","eu-north-1","ap-east-1"],"aws-cn-region-set":["cn-north-1","cn-northwest-1"]Using RDK to Generate a Lambda Layer in a region (Python3)By defaultrdk init --generate-lambda-layerwill generate an rdklib
lambda layer while running init in whatever region it is run, to force
re-generation of the layer, runrdk init --generate-lambda-layeragain
over a regionTo use this generated lambda layer, add the flag--generated-lambda-layerwhen runningrdk deploy. For example:rdk -f regions.yaml deploy LP3_TestRule_P39_lib --generated-lambda-layerIf you created layer with a custom name (by runningrdk init --custom-lambda-layer, add a similarcustom-lambda-layerflag when running deploy.Support & FeedbackThis project is maintained by AWS Solution Architects and Consultants.
It is not part of an AWS service and support is provided best-effort by
the maintainers. To post feedback, submit feature ideas, or report bugs,
please use theIssues
sectionof this repo.Contributingemail us atrdk-maintainers@amazon.comif you have any questions. We
are happy to help and discuss.ContactsBenjamin Morris-bmorrissirromb-current maintainerJulio Delgado Jr-tekdj7-current maintainerPast ContributorsMichael Borchert-Original Python versionJonathan Rault-Original Design, testing, feedbackGreg Kim and Chris Gutierrez-Initial work and CI definitionsHenry Huang-Original CFN templates and other codeSantosh Kumar-maintainerJose Obando-maintainerJarrett Andrulis-jarrettandrulis-maintainerSandeep Batchu-batchus-maintainerMark Beacom-mbeacom-maintainerRicky Chau-rickychau2780-maintainerLicenseThis project is licensed under the Apache 2.0 LicenseAcknowledgmentsthe boto3 team makes all of this magic possible.Linkto view example of rules built with the RDK:https://github.com/awslabs/aws-config-rules/tree/master/python