in AccountCreationLambda.py [0:0]
def main(event, context):
""" Main function """
print(event)
client = get_client('organizations')
ec2_client = get_client('ec2')
accountname = event['ResourceProperties']['AccountName']
accountemail = event['ResourceProperties']['AccountEmail']
organization_unit_name = event['ResourceProperties']['OrganizationalUnitName']
accountrole = 'OrganizationAccountAccessRole'
stackname = event['ResourceProperties']['StackName']
stackregion = event['ResourceProperties']['StackRegion']
sourcebucket = event['ResourceProperties']['SourceBucket']
baselinetemplate = event['ResourceProperties']['BaselineTemplate']
accountbilling = event['ResourceProperties']['AccountBilling']
skip_cloud_checkr = event['ResourceProperties'].get('SkipCloudCheckr', "false")
configbucket = event['ResourceProperties']['ConfigBucket']
## These are cloud checker values.
apisecret = event['ResourceProperties']['CloudCheckrApiSecret']
ccstackname = event['ResourceProperties']['CCStackName']
cloudtrailbucket = event['ResourceProperties']['CloudTrailBucket']
curbucket = event['ResourceProperties']['CurBucket']
dbrbucket = event['ResourceProperties']['DbrBucket']
access_to_billing = "DENY"
scp = None
if event['RequestType'] == 'Create':
sts = boto3.client('sts')
top_level_account = sts.get_caller_identity().get('Account')
print("The top level account is " + top_level_account)
org_client = get_client('organizations')
try:
desc_org_response = org_client.describe_organization()
org_id = desc_org_response['Organization']['Id']
print("Organization ID" + org_id)
except:
org_id = "Error"
try:
list_roots_response = org_client.list_roots()
root_id = list_roots_response['Roots'][0]['Id']
except:
root_id = "Error"
# This means this is being run from a management account.
if (root_id is not "Error") and (org_id is not "Error"):
try:
# Create new account
print("Creating new account: " + accountname + " (" + accountemail + ")")
(create_account_response, account_id) = \
create_account(accountname, accountemail, accountrole,
access_to_billing, scp, root_id, accountbilling)
print(create_account_response)
print("Created account:{}\n".format(account_id))
time.sleep(20)
except Exception as exception:
respond_cloudformation(
event, "FAILED",
{"Message":f"Failed to create account: {exception}"}
)
print("Error creating new account.")
sys.exit(0)
# Create resources in the newly vended account
try:
# Move account to OU provided
if organization_unit_name != 'None':
try:
(organization_unit_name, organization_unit_id) = \
get_ou_name_id(event, root_id, organization_unit_name)
move_response = org_client.move_account(AccountId=account_id,
SourceParentId=root_id,
DestinationParentId=organization_unit_id)
except botocore.exceptions.ClientError as exception:
# Respond to cloud formation as failure.
respond_cloudformation(
event, "FAILED",
{"Message":f"Failed moving account to OU: {exception}"}
)
print("An error occured. Org account move response: \
{} . Error Stack: {}".format(move_response,
exception))
sys.exit(0)
credentials = assume_role(account_id, accountrole)
template = get_template(sourcebucket, baselinetemplate)
# deploy cloudformation template (AccountBaseline.yml)
stack = deploy_resources(credentials, template, stackname,
stackregion, org_id, account_id, configbucket)
print(stack)
print("Baseline setup deployment for account " + account_id + \
" (" + accountemail + ") complete!")
# delete default vpc in every region
regions = []
regions_response = ec2_client.describe_regions()
for i in range(0, len(regions_response['Regions'])):
regions.append(regions_response['Regions'][i]['RegionName'])
for r in regions:
try:
delete_vpc_response = delete_default_vpc(credentials, r)
except botocore.exceptions.ClientError as exception:
print("An error occured while deleting \
Default VPC in {}. Error: {}".format(r, exception))
i += 1
respond_cloudformation(event, "SUCCESS",
{"Message": \
"Account created successfully", \
"AccountID": account_id, \
"LoginURL": "https://" + \
account_id + ".signin.aws.amazon.com/console"})
# Only run this portion if skip cloud checker flag is set to false
if skip_cloud_checkr == 'false':
env = "https://api.cloudcheckr.com"
session = boto3.session.Session()
client = session.client(
service_name='secretsmanager'
)
try:
get_secret_value_response = client.get_secret_value(
SecretId=apisecret
)
except ClientError as e:
respond_cloudformation(
event, "FAILED",
{"Message":f"Failed to get API key from secrets manager: {e}"}
)
print("Error fetching API key.")
sys.exit(0)
else:
# Secrets Manager decrypts the secret value using the associated KMS CMK
# Depending on whether the secret was a string or binary, only one of
# these fields will be populated
if 'SecretString' in get_secret_value_response:
text_secret_data = get_secret_value_response['SecretString']
else:
text_secret_data = get_secret_value_response['SecretBinary']
secret_json = json.loads(text_secret_data)
adminapikey = secret_json['AdminApiKey']
external_id = create_account_in_cloudcheckr(env, adminapikey, accountname)
if external_id is None:
print("Was not able to successfully create an account in CloudCheckr")
return
rolearn = create_iam_role_from_cloud_formation(credentials, external_id,
template, ccstackname,
stackregion, dbrbucket,
cloudtrailbucket, curbucket)
add_role_to_cloudcheckr(env, adminapikey, accountname, rolearn)
except botocore.exceptions.ClientError as exception:
print("An error occured. Error Stack: {}".format(exception))
sys.exit(0)
if event['RequestType'] == 'Update':
print("Template in Update Status")
respond_cloudformation(event, "SUCCESS", {"Message": "Resource update successful!"})