######################################################################################################################## # Any code, applications, scripts, templates, proofs of concept, documentation and other items provided by AWS under # # this SOW are "AWS Content," as defined in the Agreement, and are provided for illustration purposes only. All such # # AWS Content is provided solely at the option of AWS, and is subject to the terms of the Addendum and the Agreement. # # Customer is solely responsible for using, deploying, testing, and supporting any code and applications provided by # # AWS under this SOW. # ######################################################################################################################## AWSTemplateFormatVersion: '2010-09-09' Description: Prepares the Management Account for adding custom solutions Parameters: OrganizationId: Type: 'String' Description: AWS Organization Id of Control Tower ManagementAccountId: Type: 'String' Description: AWS Account ID of the Organization Management Account NetworkHubAccountId: Type: 'String' Description: AWS Account ID of the Network Hub Account DevelopmentOrganizationUnitId: Type: 'String' Description: AWS Organization unit Id for Development Accounts NameforSSMParameterforOrganizationId: Type: String Description: Name of the SSM Parameter under which the AWS Organization ID of the LZ will be stored Default: /org/core/OrganizationID NameforSSMParameterforDevelopmentOrganizationUnitId: Type: String Description: Name of the SSM Parameter under which the name of Development OU will be stored Default: /org/core/DevelopmentOU NameforSSMParameterforManagementAccountId: Type: String Description: Name of the SSM Parameter under which the name of Management AWS account ID will be stored Default: /org/core/ManagementAccountId NameforSSMParameterforNetworkHubAccountId: Type: String Description: Name of the SSM Parameter under which the name of NetworkHub account will be stored Default: /org/sharedservice/networking/NetworkHubAccount Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "Key Account IDs" Parameters: - ManagementAccountId - NetworkHubAccountId - Label: default: "Organization and Organization Units" Parameters: - OrganizationId - DevelopmentOrganizationUnitId - Label: default: "SSM Parameter Keys" Parameters: - NameforSSMParameterforOrganizationId - NameforSSMParameterforDevelopmentOrganizationUnitId - NameforSSMParameterforManagementAccountId - NameforSSMParameterforNetworkHubAccountId Resources: OrganizationIDSSMParameter: Type: AWS::SSM::Parameter Properties: Name: !Ref NameforSSMParameterforOrganizationId Type: String Value: !Ref OrganizationId DevelopmentOrganizationUnitIDSSMParameter: Type: AWS::SSM::Parameter Properties: Name: !Ref NameforSSMParameterforDevelopmentOrganizationUnitId Type: String Value: !Ref DevelopmentOrganizationUnitId ManagementAccountIdSSMParameter: Type: AWS::SSM::Parameter Properties: Name: !Ref NameforSSMParameterforManagementAccountId Type: String Value: !Ref ManagementAccountId NetworkHubAccountIDSSMParameter: Type: AWS::SSM::Parameter Properties: Name: !Ref NameforSSMParameterforNetworkHubAccountId Type: String Value: !Ref NetworkHubAccountId EnableRAMLambdaFunctionRole: Type: AWS::IAM::Role Properties: ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: "/" Policies: - PolicyName: EnableRAMSharing PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - organizations:EnableAWSServiceAccess - iam:CreateServiceLinkedRole - organizations:DescribeOrganization - ram:EnableSharingWithAwsOrganization - organizations:RegisterDelegatedAdministrator Resource: "*" EnableRAMLambdaFunction: # needs no monitoring because it is used as a custom resource Type: 'AWS::Lambda::Function' Properties: Code: ZipFile: !Sub | # Import statements import boto3, sys import json import cfnresponse import os from botocore.exceptions import ClientError import urllib.request # Start Lambda function def enable_ram(event, context): print("Enabling Resource Access Manager to Interact with Organization") try: client = boto3.client('ram') response = client.enable_sharing_with_aws_organization() print("SUCCESS") responseStatus = 'SUCCESS' responseData = {} sendResponse(event, context, responseStatus, responseData) except ClientError as ex: print('Something went wrong - see below') print(ex.response['Error']['Message']) print("Respond: FAILED") responseStatus = 'FAILED' responseData = {} sendResponse(event, context, responseStatus, responseData) def sendResponse(event, context, responseStatus, responseData): data = json.dumps({ 'Status': responseStatus, 'PhysicalResourceId': context.log_stream_name, 'StackId': event['StackId'], 'RequestId': event['RequestId'], 'LogicalResourceId': event['LogicalResourceId'], 'Data': responseData }) print(data) opener = urllib.request.build_opener(urllib.request.HTTPHandler) request = urllib.request.Request(url=event['ResponseURL'], data=data.encode('utf-8')) request.add_header('Content-Type', '') request.get_method = lambda: 'PUT' url = opener.open(request) print('HTTP Request Sent') return def lambda_handler(event, context): client = event['ResourceProperties'] print('event=', event) print('client=', client) if event['RequestType'] in ["Create","Update"]: print(f"{event['RequestType']}") enable_ram(event, context) # Handle a CloudFormation resource delete event if event['RequestType'] == "Delete": print("Received Delete request: Nothing to Delete") responseStatus = 'SUCCESS' responseData = {} sendResponse(event, context, responseStatus, responseData) Handler: "index.lambda_handler" MemorySize: 128 Role: !GetAtt "EnableRAMLambdaFunctionRole.Arn" Runtime: "python3.6" Timeout: 60 RAMEnabler: Type: Custom::RAMEnabler DependsOn: - EnableRAMLambdaFunction Properties: ServiceToken: !GetAtt EnableRAMLambdaFunction.Arn AWSControlTowerExecutionforManagement: Type: AWS::IAM::Role Properties: RoleName: AWSControlTowerExecution ManagedPolicyArns: - arn:aws:iam::aws:policy/AdministratorAccess AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: AWS: - !Join [ "", ["arn:aws:iam::", !Ref ManagementAccountId, ":root"]] Action: - sts:AssumeRole Path: "/"