AWSTemplateFormatVersion: '2010-09-09' Description: Control Tower Batch Account Creation (fdp-1p4ekfxow) Parameters: S3BucketName: Default: 'YOUR-BUCKET-NAME' Description: Your Amazon S3 Bucket Name. Type: String S3KeyName: Default: 'sample.csv' Description: Amazon S3 key file. Type: String Resources: NewAccountDetailsTable: Type: AWS::DynamoDB::Table Properties: KeySchema: - AttributeName: AccountName KeyType: HASH AttributeDefinitions: - AttributeName: AccountName AttributeType: S ProvisionedThroughput: ReadCapacityUnits: 10 WriteCapacityUnits: 10 StreamSpecification: StreamViewType: NEW_AND_OLD_IMAGES UpdateReplacePolicy: Delete DeletionPolicy: Delete NewAccountHandlerLambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Version: "2012-10-17" Policies: - PolicyName: S3ReadAccess PolicyDocument: Version: 2012-10-17 Statement: - Sid: '1' Action: - s3:GetObject - s3:GetObjectAcl Effect: Allow Resource: - !Sub arn:${AWS::Partition}:s3:::${S3BucketName} - !Sub arn:${AWS::Partition}:s3:::${S3BucketName}/${S3KeyName} ManagedPolicyArns: - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' NewAccountHandlerPolicy: Type: AWS::IAM::Policy Properties: PolicyDocument: Statement: - Action: - dynamodb:Query - dynamodb:GetItem - dynamodb:PutItem - dynamodb:UpdateItem - dynamodb:DeleteItem - dynamodb:scan Effect: Allow Resource: - Fn::GetAtt: - NewAccountDetailsTable - Arn - Ref: AWS::NoValue - Action: - organizations:ListAccountsForParent - organizations:ListRoots - organizations:ListAccountsForParent - organizations:ListOrganizationalUnitsForParent - organizations:ListChildren - organizations:DescribeOrganizationalUnit Effect: Allow Resource: '*' Version: "2012-10-17" PolicyName: NewAccountHandlerPolicy Roles: - Ref: NewAccountHandlerLambdaExecutionRole NewAccountHandlerLambda: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Join ['-', ['marketplace-sa-resources-ct', !Ref "AWS::Region"]] S3Key: ct_batchcreation_lambda.zip Handler: new_account_handler.account_handler Role: !GetAtt NewAccountHandlerLambdaExecutionRole.Arn Runtime: python3.7 Environment: Variables: TABLE_NAME: Ref: NewAccountDetailsTable BATCH_BUCKET_NAME: Ref: S3BucketName BATCH_KEY_NAME: Ref: S3KeyName Timeout: 900 DependsOn: - NewAccountHandlerPolicy NewAccountHandlerTriggerLambda: Type: 'Custom::AccountHandler' Properties: ServiceToken: !GetAtt "NewAccountHandlerLambda.Arn" CreateManagedAccountLambda: Type: AWS::Lambda::Function Properties: Code: S3Bucket: !Join ['-', ['marketplace-sa-resources-ct', !Ref "AWS::Region"]] S3Key: ct_account_create_lambda.zip Handler: account_create.lambda_handler MemorySize: 128 Role: !GetAtt "CreateManagedAccountLambdaRole.Arn" Runtime: python3.7 Timeout: 300 Environment: Variables: TABLE_NAME: Ref: NewAccountDetailsTable PRINCIPAL_ARN: !GetAtt "CreateManagedAccountLambdaRole.Arn" TargetLambdaTrigger: Type: 'Custom::CreateAccount' DependsOn: - EventSourceMapping Properties: ServiceToken: !GetAtt "CreateManagedAccountLambda.Arn" PermissionForEventsToInvokeLambdachk: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !GetAtt "CreateManagedAccountLambda.Arn" Principal: events.amazonaws.com SourceArn: !GetAtt "CaptureControlTowerLifeCycleEvents.Arn" CreateManagedAccountLambdaRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole Condition: {} Path: / Policies: - PolicyName: ct-admin-inline-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'sso:GetProfile' - 'sso:CreateProfile' - 'sso:UpdateProfile' - 'sso:AssociateProfile' - 'sso:CreateApplicationInstance' - 'sso:GetSSOStatus' - 'sso:GetTrust' - 'sso:CreateTrust' - 'sso:UpdateTrust' - 'sso:GetPeregrineStatus' - 'sso:GetApplicationInstance' - 'sso:ListDirectoryAssociations' - 'sso:ListPermissionSets' - 'sso:GetPermissionSet' - 'sso:ProvisionApplicationInstanceForAWSAccount' - 'sso:ProvisionApplicationProfileForAWSAccountInstance' - 'sso:ProvisionSAMLProvider' - 'sso:ListProfileAssociations' - 'sso-directory:ListMembersInGroup' - 'sso-directory:SearchGroups' - 'sso-directory:SearchGroupsWithGroupName' - 'sso-directory:SearchUsers' - 'sso-directory:CreateUser' - 'sso-directory:DescribeGroups' - 'sso-directory:DescribeDirectory' - 'sso-directory:GetUserPoolInfo' - 'controltower:CreateManagedAccount' - 'controltower:DescribeManagedAccount' - 'controltower:DeregisterManagedAccount' - 's3:GetObject' - 'organizations:describeOrganization' - 'sso:DescribeRegisteredRegions' - 'servicecatalog:DisassociatePrincipalFromPortfolio' - 'servicecatalog:AssociatePrincipalWithPortfolio' Resource: '*' ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess - arn:aws:iam::aws:policy/AWSOrganizationsFullAccess - arn:aws:iam::aws:policy/CloudWatchEventsFullAccess - arn:aws:iam::aws:policy/AWSServiceCatalogAdminReadOnlyAccess - arn:aws:iam::aws:policy/AWSServiceCatalogEndUserFullAccess CaptureControlTowerLifeCycleEvents: Type: AWS::Events::Rule Properties: Description: Capture Control Tower LifeCycle Events and Trigger an Action EventPattern: detail: eventName: - CreateManagedAccount eventSource: - controltower.amazonaws.com detail-type: - AWS Service Event via CloudTrail source: - aws.controltower State: ENABLED Targets: - Arn: !GetAtt "CreateManagedAccountLambda.Arn" Id: IDCaptureControlTowerLifeCycleEvents EventSourceMapping: Type: AWS::Lambda::EventSourceMapping DependsOn: - NewAccountHandlerTriggerLambda Properties: EventSourceArn: !GetAtt - NewAccountDetailsTable - StreamArn FunctionName: !GetAtt - CreateManagedAccountLambda - Arn StartingPosition: LATEST Outputs: DynamoDBTableWithAccountInformation: Description: The DynamoDB table name Value: !Sub 'https://console.aws.amazon.com/dynamodb/home?region=${AWS::Region}#tables:selected=${NewAccountDetailsTable}' NewAccountHandlerLambda: Description: Lambda to validate the input file and load the data in to DynamoDB table Value: !Sub 'https://console.aws.amazon.com/lambda/home?region=${AWS::Region}#/functions/${NewAccountHandlerLambda}' CreateManagedAccountLambda: Description: Lambda to create account from the DynamoDB table Value: !Sub 'https://console.aws.amazon.com/lambda/home?region=${AWS::Region}#/functions/${NewAccountHandlerLambda}'