Skip to content

Commit

Permalink
Merge pull request #281 from awslabs/master
Browse files Browse the repository at this point in the history
RELEASE 0.7.12
  • Loading branch information
rickychau2780 authored Oct 26, 2020
2 parents 1bc6c07 + 207c7ae commit 3ac5cb2
Show file tree
Hide file tree
Showing 13 changed files with 78 additions and 41 deletions.
5 changes: 4 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
include README.rst
include rdk/template/*
include rdk/template/terraform/*
include rdk/template/terraform/0.11/*
include rdk/template/terraform/0.12/*
include rdk/template/example_ci/*
incldue rdk/template/runtime/*
include rdk/template/runtime/*
include rdk/template/runtime/java8/*
include rdk/template/runtime/java8/jars/*
include rdk/template/runtime/java8/src/main/java/com/rdk/*
Expand Down
2 changes: 2 additions & 0 deletions docs/reference/deploy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,7 @@ Deploy
The ``--lambda-security-groups`` flag can be used for attaching a comma-separated list of Security Groups to deploy with your Lambda function(s).
The ``--custom-code-bucket`` flag can be used for providing the custom code S3 bucket name, which is not created with rdk init, for generated cloudformation template storage.
The ``--boundary-policy-arn`` flag can be used for attaching boundary Policy ARN that will be added to rdkLambdaRole.
The ``--lambda-timeout`` flag can be used for specifying the timeout associated to the lambda function


Note: Behind the scenes the ``--functions-only`` flag generates a CloudFormation template and runs a "create" or "update" on the targeted AWS Account and Region. If subsequent calls to ``deploy`` with the ``--functions-only`` flag are made with the same stack name (either the default or otherwise) but with *different Config rules targeted*, any Rules deployed in previous ``deploy``s but not included in the latest ``deploy`` will be removed. After a functions-only ``deploy`` _only_ the Rules specifically targeted by that command (either through Rulesets or an explicit list supplied on the command line) will be deployed in the environment, all others will be removed.s
1 change: 1 addition & 0 deletions docs/reference/export.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ Export
The ``--lambda-layers`` flag can be used for attaching a comma-separated list of Lambda Layer ARNs to deploy with your Lambda function(s).
The ``--lambda-subnets`` flag can be used for attaching a comma-separated list of Subnets to deploy your Lambda function(s).
The ``--lambda-security-groups`` flag can be used for attaching a comma-separated list of Security Groups to deploy with your Lambda function(s).
The ``--lambda-timeout`` flag can be used for specifying the timeout associated to the lambda function


1 change: 1 addition & 0 deletions docs/reference/init.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ Init

- ``--config-bucket-exists-in-another-account``: [optional] If the bucket being used by a Config Delivery Channel exists in another account, it is possible to skip the check that the bucket exists. This is useful when using ``init`` to initialize AWS Config in an account which already has a delivery channel setup with a central bucket. Currently, the rdk lists out all the buckets within the account your are running ``init`` from, to check if the provided bucket name exists, if it doesn't then it will create it. This presents an issue when a Config Delivery Channel has been configured to push configuration recordings to a central bucket. The bucket will never be found as it doesn't exist in the same account, but cannot be created as bucket names have to be globally unique.
- ``--skip-code-bucket-creation``: [optional] If you want to use custom code bucket for rdk, enable this and use flag ``--custom-code-bucket`` to ``rdk deploy``
- ``control-tower``: [optional] If your account is part of an AWS Control Tower setup --control-tower will skip the setup of configuration_recorder and delivery_channel
3 changes: 2 additions & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Sphinx==1.7.8
sphinx-argparse==0.2.2
sphinx-argparse==0.2.5
sphinx-rtd-theme==0.4.3
sphinxcontrib-websupport==1.1.0
2 changes: 1 addition & 1 deletion rdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
#
# or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

MY_VERSION = "0.7.11"
MY_VERSION = "0.7.12"

82 changes: 50 additions & 32 deletions rdk/rdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ def get_init_parser():

parser.add_argument('--config-bucket-exists-in-another-account', required=False, action='store_true', help='[optional] If the Config bucket exists in another account, remove the check of the bucket')
parser.add_argument('--skip-code-bucket-creation', required=False, action='store_true', help='[optional] If you want to use custom code bucket for rdk, enable this and use flag --custom-code-bucket to "rdk deploy"')
parser.add_argument('--control-tower', required=False, action='store_true', help='[optional] If your account is part of an AWS Control Tower setup --control-tower will skip the setup of configuration_recorder and delivery_channel')

return parser

Expand Down Expand Up @@ -243,6 +244,7 @@ def get_deployment_parser(ForceArgument=False, Command="deploy"):
parser.add_argument('--lambda-layers', required=False, help="[optional] Comma-separated list of Lambda Layer ARNs to deploy with your Lambda function(s).")
parser.add_argument('--lambda-subnets', required=False, help="[optional] Comma-separated list of Subnets to deploy your Lambda function(s).")
parser.add_argument('--lambda-security-groups', required=False, help="[optional] Comma-separated list of Security Groups to deploy with your Lambda function(s).")
parser.add_argument('--lambda-timeout', required=False, default=60, help="[optional] Timeout (in seconds) for the lambda function", type=str)
parser.add_argument('--boundary-policy-arn', required=False, help="[optional] Boundary Policy ARN that will be added to \"rdkLambdaRole\".")

if ForceArgument:
Expand All @@ -261,6 +263,7 @@ def get_export_parser(ForceArgument=False, Command="export"):
parser.add_argument('--lambda-layers', required=False, help="[optional] Comma-separated list of Lambda Layer ARNs to deploy with your Lambda function(s).")
parser.add_argument('--lambda-subnets', required=False, help="[optional] Comma-separated list of Subnets to deploy your Lambda function(s).")
parser.add_argument('--lambda-security-groups', required=False, help="[optional] Comma-separated list of Security Groups to deploy with your Lambda function(s).")
parser.add_argument('--lambda-timeout', required=False, default=60, help="[optional] Timeout (in seconds) for the lambda function", type=str)
parser.add_argument('--lambda-role-arn', required=False,
help="[optional] Assign existing iam role to lambda functions. If omitted, new lambda role will be created.")
parser.add_argument('--rdklib-layer-arn', required=False,
Expand Down Expand Up @@ -373,6 +376,11 @@ def init(self):
config_bucket_exists = True

config_bucket_name = config_bucket_prefix + "-" + account_id

control_tower = False
if self.args.control_tower:
print("This account is part of an AWS Control Tower managed organization. Playing nicely with it")
control_tower = True

#Check to see if the ConfigRecorder has been created.
recorders = my_config.describe_configuration_recorders()
Expand Down Expand Up @@ -449,17 +457,20 @@ def init(self):
#create or update config recorder
if not config_role_arn:
config_role_arn = "arn:" + partition + ":iam::" + account_id + ":role/rdk/config-role"

if (not control_tower):
my_config.put_configuration_recorder(ConfigurationRecorder={'name':config_recorder_name, 'roleARN':config_role_arn, 'recordingGroup':{'allSupported':True, 'includeGlobalResourceTypes': True}})

my_config.put_configuration_recorder(ConfigurationRecorder={'name':config_recorder_name, 'roleARN':config_role_arn, 'recordingGroup':{'allSupported':True, 'includeGlobalResourceTypes': True}})

if not delivery_channel_exists:
#create delivery channel
print("Creating delivery channel to bucket " + config_bucket_name)
my_config.put_delivery_channel(DeliveryChannel={'name':'default', 's3BucketName':config_bucket_name, 'configSnapshotDeliveryProperties':{'deliveryFrequency':'Six_Hours'}})

#start config recorder
my_config.start_configuration_recorder(ConfigurationRecorderName=config_recorder_name)
print('Config Service is ON')
if not delivery_channel_exists:
#create delivery channel
print("Creating delivery channel to bucket " + config_bucket_name)
my_config.put_delivery_channel(DeliveryChannel={'name':'default', 's3BucketName':config_bucket_name, 'configSnapshotDeliveryProperties':{'deliveryFrequency':'Six_Hours'}})

#start config recorder
my_config.start_configuration_recorder(ConfigurationRecorderName=config_recorder_name)
print('Config Service is ON')
else:
print('Skipped put_configuration_recorder, put_delivery_channel & start_configuration_recorder as this is part of a Control Tower managed Organization')

print('Config setup complete.')

Expand Down Expand Up @@ -1229,6 +1240,10 @@ def deploy(self):
'ParameterKey': 'SourceHandler',
'ParameterValue': self.__get_handler(rule_name, rule_params)

},
{
'ParameterKey': 'Timeout',
'ParameterValue': str(self.args.lambda_timeout)
}]
layers = []
if 'SourceRuntime' in rule_params:
Expand Down Expand Up @@ -1279,18 +1294,18 @@ def deploy(self):

if "SSMAutomation" in rule_params:
print('Building SSM Automation Section')

ssm_automation = self.__create_automation_cloudformation_block(rule_params['SSMAutomation'], rule_name)
json_body["Resources"][self.__get_alphanumeric_rule_name(rule_name+"RemediationAction")] = ssm_automation
if "IAM" in rule_params['SSMAutomation']:
print('Lets Build IAM Role and Policy')
#TODO Check For IAM Settings
json_body["Resources"]['Remediation']['Properties']['Parameters']['AutomationAssumeRole']['StaticValue']['Values'] = [{"Fn::GetAtt":[self.__get_alphanumeric_rule_name(rule_name+"Role"), "Arn"]}]

ssm_iam_role, ssm_iam_policy = self.__create_automation_iam_cloudformation_block(rule_params['SSMAutomation'], rule_name)
json_body["Resources"][self.__get_alphanumeric_rule_name(rule_name+'Role')] = ssm_iam_role
json_body["Resources"][self.__get_alphanumeric_rule_name(rule_name+'Policy')] = ssm_iam_policy

#debugging
#print(json.dumps(json_body, indent=2))

Expand All @@ -1316,7 +1331,7 @@ def deploy(self):
response = my_cfn.update_stack(**cfn_args)
except ClientError as e:
if e.response['Error']['Code'] == 'ValidationError':

if 'No updates are to be performed.' in str(e):
#No changes made to Config rule definition, so CloudFormation won't do anything.
print("No changes to Config Rule.")
Expand Down Expand Up @@ -1451,7 +1466,8 @@ def export(self):
"subnet_ids": subnet_ids,
"security_group_ids": security_group_ids,
"lambda_layers": layers,
"lambda_role_arn": lambda_role_arn
"lambda_role_arn": lambda_role_arn,
"lambda_timeout": str(self.args.lambda_timeout)
}

params_file_path = os.path.join(os.getcwd(), rules_dir, rule_name, rule_name.lower() + ".tfvars.json")
Expand Down Expand Up @@ -1760,10 +1776,10 @@ def create_rule_template(self):
for input_param in input_params:
cfn_param = {}
cfn_param["Description"] = "Pass-through to required Input Parameter " + input_param + " for Config Rule " + rule_name
if len(input_params[input_param].strip()) == 0:
if len(str(input_params[input_param]).strip()) == 0:
default = "<REQUIRED>"
else:
default = input_params[input_param]
default = str(input_params[input_param])
cfn_param["Default"] = default
cfn_param["Type"] = "String"
cfn_param["MinLength"] = 1
Expand Down Expand Up @@ -1883,14 +1899,14 @@ def create_rule_template(self):
remediation["DependsOn"] = [config_rule_resource_name]
if not self.args.rules_only:
remediation["DependsOn"].append("ConfigRole")

if "SSMAutomation" in params:
ssm_automation = self.__create_automation_cloudformation_block(params['SSMAutomation'], rule_name)
#AWS needs to build the SSM before the Config Rule
remediation["DependsOn"].append(self.__get_alphanumeric_rule_name(rule_name+'RemediationAction'))
#Add JSON Reference to SSM Document { "Ref" : "MyEC2Instance" }
remediation['Properties']['TargetId'] = {"Ref" : self.__get_alphanumeric_rule_name(rule_name) + 'RemediationAction' }

if "IAM" in params['SSMAutomation']:
print('Lets Build IAM Role and Policy For the SSM Document')
ssm_iam_role, ssm_iam_policy = self.__create_automation_iam_cloudformation_block(params['SSMAutomation'], rule_name)
Expand All @@ -1900,7 +1916,7 @@ def create_rule_template(self):
#Override the placeholder to associate the SSM Document Role with newly crafted role
resources[self.__get_alphanumeric_rule_name(rule_name+"RemediationAction")] = ssm_automation
resources[self.__get_alphanumeric_rule_name(rule_name)+"Remediation"] = remediation

if tags:
tags_str=""
for tag in tags:
Expand Down Expand Up @@ -2574,6 +2590,8 @@ def __wait_for_cfn_stack(self, cfn_client, stackname):
time.sleep(5)

def __get_handler(self, rule_name, params):
if 'SourceHandler' in params:
return params['SourceHandler']
if params['SourceRuntime'] in ['python2.7', 'python3.6', 'python3.6-lib', 'python3.7', 'python3.8', 'nodejs4.3', 'nodejs6.10', 'nodejs8.10']:
return (rule_name+'.lambda_handler')
elif params['SourceRuntime'] in ['java8']:
Expand Down Expand Up @@ -2725,16 +2743,16 @@ def __create_automation_cloudformation_block(self, ssm_automation, rule_name):
"DocumentType": "Automation",
"Content" : ssm_automation_json
}

}


return(ssm_automation_config)

def __create_automation_iam_cloudformation_block(self, ssm_automation, rule_name):

print('Generate IAM Role for SSM Document with these actions', str(ssm_automation['IAM']))

assume_role_template = {
"Version": "2012-10-17",
"Statement": [
Expand All @@ -2748,7 +2766,7 @@ def __create_automation_iam_cloudformation_block(self, ssm_automation, rule_name
]
}


#params_file_path = os.path.join(os.getcwd(), rules_dir, rulename, parameter_file_name)
ssm_automation_iam_role = {"Type": "AWS::IAM::Role",
"Properties": {
Expand All @@ -2757,7 +2775,7 @@ def __create_automation_iam_cloudformation_block(self, ssm_automation, rule_name
#"RoleName": {"Fn::Sub": "" + rule_name + "-Remedation-Role-${AWS::Region}"},
"AssumeRolePolicyDocument" : assume_role_template
}

}

ssm_automation_iam_policy = {
Expand All @@ -2781,10 +2799,10 @@ def __create_automation_iam_cloudformation_block(self, ssm_automation, rule_name
]
}
}
return(ssm_automation_iam_role, ssm_automation_iam_policy)



return(ssm_automation_iam_role, ssm_automation_iam_policy)



Expand Down Expand Up @@ -2917,7 +2935,7 @@ def __create_function_cloudformation_template(self):
lambda_function["DependsOn"] = "rdkLambdaRole"
properties["Role"] = {"Fn::GetAtt": [ "rdkLambdaRole", "Arn" ]}
properties["Runtime"] = self.__get_runtime_string(params)
properties["Timeout"] = 300
properties["Timeout"] = str(self.args.lambda_timeout)
properties["Tags"] = tags
if self.args.lambda_subnets and self.args.lambda_security_groups:
properties["VpcConfig"] = {
Expand Down
7 changes: 6 additions & 1 deletion rdk/template/configRule.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@
"Description": "Comma-separated list of Subnet Ids for Lambda Function deployment",
"Type": "String",
"Default": ""
},
"Timeout":{
"Description": "Lambda Function timeout",
"Type": "String",
"Default": 60
}
},
"Conditions": {
Expand Down Expand Up @@ -112,7 +117,7 @@
]
},
"Runtime": { "Ref": "SourceRuntime"},
"Timeout": 60,
"Timeout": { "Ref": "Timeout"},
"Layers":
{"Fn::If":
[ "UseAdditionalLayers",
Expand Down
2 changes: 1 addition & 1 deletion rdk/template/terraform/0.11/config_rule.tf
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ resource "aws_lambda_function" "rdk_rule" {
handler = "${var.source_handler}"
role = "${ local.create_new_lambda_role ? "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${lower(var.rule_name)}-awsconfig-role" : var.lambda_role_arn}"

timeout = "60"
timeout = "${var.lambda_timeout}"
s3_bucket = "${var.source_bucket}"
s3_key = "${var.rule_name}.zip"
memory_size = "256"
Expand Down
4 changes: 4 additions & 0 deletions rdk/template/terraform/0.11/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ variable "lambda_role_arn" {
type = "string"
}

variable "lambda_timeout" {
description = "Lambda function timeout"
type = "string"
}

locals {
event_triggered = "${ length(var.source_events)>0 ? true : false}"
Expand Down
2 changes: 1 addition & 1 deletion rdk/template/terraform/0.12/config_rule.tf
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ resource "aws_lambda_function" "rdk_rule" {
runtime = var.source_runtime
handler = var.source_handler
role = local.create_new_lambda_role ? format ("arn:aws:iam::%s:role/%s", data.aws_caller_identity.current.account_id,format("%s-awsconfig-role", lower(var.rule_name))) : var.lambda_role_arn
timeout = "60"
timeout = var.lambda_timeout
s3_bucket = var.source_bucket
s3_key = local.rule_name_source
memory_size = "256"
Expand Down
5 changes: 5 additions & 0 deletions rdk/template/terraform/0.12/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ variable "lambda_role_arn" {
type = string
}

variable "lambda_timeout" {
description = "Lambda function timeout"
type = string
}

locals {
event_triggered = (length(var.source_events)>0 ? true : false)
periodic_triggered = var.source_periodic != "NONE" ? true : false
Expand Down
3 changes: 0 additions & 3 deletions requirements-dev.txt

This file was deleted.

0 comments on commit 3ac5cb2

Please sign in to comment.