# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 --- AWSTemplateFormatVersion: "2010-09-09" Transform: "AWS::Serverless-2016-10-31" Description: Automated AWS Organizations configuration for security operations Parameters: Regions: Type: CommaDelimitedList Description: Regions to enable for Security Hub and GuardDuty (leave blank for all regions) Default: "us-east-1" ExecutionRoleName: Type: String Description: Execution IAM role name Default: AWSControlTowerExecution AdministratorAccountName: Type: String Description: "Security operations AWS account name (Audit Manager, SecurityHub, GuardDuty, Macie, S3 Storage Lens and Firewall Manager)" Default: Audit ExecutionCount: Type: Number Description: Increment this value to re-execute the OrganizationSetup custom resource Default: 1 SigningProfileVersionArn: Type: String Description: Code Signing Profile Version ARN EnableAIOptOutPolicy: Type: String Description: Opt-out of AI-services improvement Default: "false" AllowedValues: - "true" - "false" Resources: OrganizationSetupFunctionLogGroup: Type: "AWS::Logs::LogGroup" UpdateReplacePolicy: Delete DeletionPolicy: Delete Metadata: cfn_nag: rules_to_suppress: - id: W84 reason: "Ignore KMS key" Properties: LogGroupName: !Sub "/aws/lambda/${OrganizationSetupFunction}" RetentionInDays: 3 OrganizationSetupFunctionRole: Type: "AWS::IAM::Role" Metadata: cfn_nag: rules_to_suppress: - id: W11 reason: "Ignore * in resource policy" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: Effect: Allow Principal: Service: !Sub "lambda.${AWS::URLSuffix}" Action: "sts:AssumeRole" Description: !Sub "DO NOT DELETE - Used by Lambda. Created by CloudFormation ${AWS::StackId}" Policies: - PolicyName: OrganizationSetupFunctionPolicy PolicyDocument: Version: "2012-10-17" Statement: - Sid: OrganizationsAccess Effect: Allow Action: - "organizations:AttachPolicy" - "organizations:CreatePolicy" - "organizations:DescribeAccount" - "organizations:DescribeEffectivePolicy" - "organizations:DescribeOrganization" - "organizations:DescribeOrganizationalUnit" - "organizations:EnableAWSServiceAccess" - "organizations:EnableAllFeatures" - "organizations:EnablePolicyType" - "organizations:ListAccounts" - "organizations:ListAWSServiceAccessForOrganization" - "organizations:ListDelegatedAdministrators" - "organizations:ListPolicies" - "organizations:ListRoots" - "organizations:RegisterDelegatedAdministrator" Resource: "*" - Effect: Allow Action: "access-analyzer:CreateAnalyzer" Resource: !Sub "arn:${AWS::Partition}:access-analyzer:*:${AWS::AccountId}:analyzer/*" - Effect: Allow Action: "iam:GetRole" Resource: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/*" - Effect: Allow Action: - "cloudformation:ActivateOrganizationsAccess" - "detective:EnableOrganizationAdminAccount" - "ec2:DescribeRegions" - "fms:AssociateAdminAccount" - "guardduty:EnableOrganizationAdminAccount" - "inspector2:Enable" - "inspector2:EnableDelegatedAdminAccount" - "macie2:EnableMacie" - "macie2:EnableOrganizationAdminAccount" - "ram:EnableSharingWithAwsOrganization" - "securityhub:EnableOrganizationAdminAccount" - "servicecatalog:EnableAWSOrganizationsAccess" - "securitylake:RegisterDataLakeDelegatedAdministrator" Resource: "*" - Effect: Allow Action: "iam:CreateServiceLinkedRole" Resource: "*" Condition: StringLike: "iam:AWSServiceName": - !Sub "access-analyzer.${AWS::URLSuffix}" - !Sub "detective.${AWS::URLSuffix}" - !Sub "fms.${AWS::URLSuffix}" - !Sub "inspector2.${AWS::URLSuffix}" - !Sub "macie.${AWS::URLSuffix}" - !Sub "orgsdatasync.servicecatalog.${AWS::URLSuffix}" - !Sub "ram.${AWS::URLSuffix}" - !Sub "securitylake.${AWS::URLSuffix}" - !Sub "stacksets.cloudformation.${AWS::URLSuffix}" - !Sub "sync.servicecatalog.${AWS::URLSuffix}" - Effect: Allow Action: "sts:AssumeRole" Resource: !Sub "arn:${AWS::Partition}:iam::*:role/AWSControlTowerExecution" Tags: - Key: "aws-cloudformation:stack-name" Value: !Ref "AWS::StackName" - Key: "aws-cloudformation:stack-id" Value: !Ref "AWS::StackId" - Key: "aws-cloudformation:logical-id" Value: OrganizationSetupFunctionRole - Key: GITHUB_ORG Value: "aws-samples" - Key: GITHUB_REPO Value: aws-control-tower-org-setup-sample CloudWatchLogsPolicy: Type: "AWS::IAM::Policy" Properties: PolicyName: CloudWatchLogs PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - "logs:CreateLogStream" - "logs:PutLogEvents" Resource: !GetAtt OrganizationSetupFunctionLogGroup.Arn Roles: - !Ref OrganizationSetupFunctionRole CodeSigningConfig: Type: "AWS::Lambda::CodeSigningConfig" Properties: Description: OrganizationSetup Code Signing AllowedPublishers: SigningProfileVersionArns: - !Ref SigningProfileVersionArn CodeSigningPolicies: UntrustedArtifactOnDeployment: Enforce OrganizationSetupFunction: Type: "AWS::Serverless::Function" Metadata: cfn_nag: rules_to_suppress: - id: W58 reason: "Ignore CloudWatch Logs write" - id: W89 reason: "Ignore VPC" Properties: CodeSigningConfigArn: !Ref CodeSigningConfig CodeUri: src/ Description: DO NOT DELETE - Organization Setup Function Environment: Variables: ADMINISTRATOR_ACCOUNT_NAME: !Ref AdministratorAccountName ENABLE_AI_OPTOUT_POLICY: !Ref EnableAIOptOutPolicy EXECUTION_ROLE_NAME: !Ref ExecutionRoleName LOG_LEVEL: INFO REGIONS: !Join [",", !Ref Regions] PRIMARY_REGION: !Ref "AWS::Region" Events: EventBridgeEvent: Type: EventBridgeRule Properties: InputPath: "$.detail" Pattern: source: - "aws.controltower" "detail-type": - "AWS Service Event via CloudTrail" detail: eventName: - SetupLandingZone serviceEventDetails: setupLandingZoneStatus: state: - SUCCEEDED Handler: org_setup.lambda_handler.handler MemorySize: 256 # megabytes ReservedConcurrentExecutions: 1 Role: !GetAtt OrganizationSetupFunctionRole.Arn Runtime: python3.10 Tags: GITHUB_ORG: aws-samples GITHUB_REPO: aws-control-tower-org-setup-sample Timeout: 600 # 10 minutes OrganizationSetup: Type: "Custom::OrganizationSetup" DependsOn: CloudWatchLogsPolicy Properties: ServiceToken: !GetAtt OrganizationSetupFunction.Arn ExecutionCount: !Ref ExecutionCount