--- AWSTemplateFormatVersion: '2010-09-09' Description: 'This template deploys two Windows Server Failover Clustering (Exchange) with Exchange Server 2016 / 2019. This template is intended to be installed into an existing VPC that was built using the sample reference architecture titled: "Implementing Active Directory Domain Services in the AWS Cloud" **WARNING** This template creates Amazon EC2 Windows instance and related resources. You will be billed for the AWS resources used if you create a stack from this template. (qs-1qup6raed)' Metadata: cfn-lint: config: ignore_checks: - W9001 - W9006 QuickStartDocumentation: EntrypointName: "Launch into an existing VPC" Order: "2" AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Network Configuration Parameters: - ThirdAZ - VPCID - VPCCidrBlock - PrivateSubnet1ID - PrivateSubnet1CIDR - PrivateSubnet2ID - PrivateSubnet2CIDR - PrivateSubnet3ID - PrivateSubnet3CIDR - PublicSubnet1ID - PublicSubnet2ID - Label: default: Amazon EC2 Configuration Parameters: - KeyPairName - WS2016FULLBASE - WS2022FULLBASE - Label: default: Microsoft Active Directory Configuration Parameters: - DomainDNSName - DomainNetBIOSName - DomainAdminUser - DomainAdminPassword - ADServer1NetBIOSName - ADServer1PrivateIP - ADServer2NetBIOSName - DomainMemberSGID - Label: default: Microsoft Exchange Server Configuration Parameters: - AppInsightsApplicationName - ExchangeServerVersion - IncludeEdgeTransportRole - EdgeInstanceType - EdgeNode1NetBIOSName - EdgeNode1PrivateIP1 - EdgeNode2NetBIOSName - EdgeNode2PrivateIP1 - EnableReFSVolumes - EncryptDataVolumes - EncryptionKmsKey - SetupAppInsightsMonitoring - VolumeSize - VolumeType - VolumeIops - Exchange2016Source - Exchange2019Source - EnableBackups - Label: default: Load Balancer Configuration Parameters: - DeployLoadBalancer - CertificateArn - Label: default: Failover Cluster Configuration Parameters: - FileServerInstanceType - FileServerNetBIOSName - FileServerPrivateIP - ExchangeNodeInstanceType - ExchangeNode1NetBIOSName - ExchangeNode1PrivateIP1 - ExchangeNode1PrivateIP2 - ExchangeNode2NetBIOSName - ExchangeNode2PrivateIP1 - ExchangeNode2PrivateIP2 - ExchangeNode3NetBIOSName - ExchangeNode3PrivateIP1 - ExchangeNode3PrivateIP2 - Label: default: AWS Quick Start Configuration Parameters: - QSS3BucketName - QSS3BucketRegion - QSS3KeyPrefix ParameterLabels: ADServer1NetBIOSName: default: Domain Controller 1 NetBIOS name ADServer1PrivateIP: default: Domain Controller 1 private IP address ADServer2NetBIOSName: default: Domain Controller 2 NetBIOS name AppInsightsApplicationName: default: Application Insights Application name CertificateArn: default: Network Load Balancer Certificate DeployLoadBalancer: default: Deploy Network Load Balancer DomainAdminPassword: default: Domain Admin password DomainAdminUser: default: Domain Admin user name DomainDNSName: default: Domain DNS name DomainMemberSGID: default: Security Group ID for AD domain members DomainNetBIOSName: default: Domain NetBIOS name ExchangeServerVersion: default: Exchange Server version EdgeInstanceType: default: Instance type for Edge server EdgeNode1NetBIOSName: default: Edge Node 1 NetBIOS Name EdgeNode1PrivateIP1: default: Edge Node 1 private IP address EdgeNode2NetBIOSName: default: Edge Node 2 NetBIOS name EdgeNode2PrivateIP1: default: Edge Node 2 private IP address EnableReFSVolumes: default: Enable or disable ReFS EncryptDataVolumes: default: Encrypt Data volumes EncryptionKmsKey: default: KMS key to encrypt volumes EnableBackups: default: Enable AWS Backups Exchange2016Source: default: Path to Exchange 2016 ISO Exchange2019Source: default: Path to Exchange 2019 ISO ExchangeNodeInstanceType: default: Instance type for Exchange nodes ExchangeNode1NetBIOSName: default: Exchange Node 1 NetBIOS name ExchangeNode1PrivateIP1: default: Exchange Node 1 private IP address 1 ExchangeNode1PrivateIP2: default: Exchange Node 1 private IP address 2 ExchangeNode2NetBIOSName: default: Exchange Node 2 NetBIOS name ExchangeNode2PrivateIP1: default: Exchange Node 2 private IP address 1 ExchangeNode2PrivateIP2: default: Exchange Node 2 private IP address 2 ExchangeNode3NetBIOSName: default: Exchange Node 3 NetBIOS Name ExchangeNode3PrivateIP1: default: Exchange Node 3 private IP address 1 ExchangeNode3PrivateIP2: default: Exchange Node 3 private IP address 2 FileServerInstanceType: default: File Server instance type FileServerNetBIOSName: default: File Server NetBIOS name FileServerPrivateIP: default: File Server private IP address IncludeEdgeTransportRole: default: Deploy Edge servers KeyPairName: default: Key Pair Name PrivateSubnet1ID: default: Private Subnet 1 ID PrivateSubnet1CIDR: default: Private Subnet 1 CIDR PrivateSubnet2ID: default: Private Subnet 2 ID PrivateSubnet2CIDR: default: Private Subnet 2 CIDR PrivateSubnet3ID: default: Private Subnet 3 ID PrivateSubnet3CIDR: default: Private Subnet 3 CIDR PublicSubnet1ID: default: Public Subnet 1 ID PublicSubnet2ID: default: Public Subnet 2 ID QSS3BucketName: default: Quick Start S3 Bucket Name QSS3BucketRegion: default: Quick Start S3 bucket region QSS3KeyPrefix: default: Quick Start S3 Key Prefix SetupAppInsightsMonitoring: default: Setup Application Insights Monitoring ThirdAZ: default: Third Availability Zone VPCID: default: VPC for Exchange deployment VPCCidrBlock: default: CIDR block of VPC VolumeIops: default: Data Volume IOPS VolumeSize: default: Data Volume size (GiB) VolumeType: default: Data Volume type WS2016FULLBASE: default: Windows Server 2016 AMI name WS2022FULLBASE: default: Windows Server 2022 AMI name Parameters: ADServer1NetBIOSName: AllowedPattern: '^[a-zA-Z0-9]+$' Default: DC1 Description: The NetBIOS name of the first Active Directory server (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String ADServer1PrivateIP: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.0.10 Description: The private IP for the first Active Directory server located in Availability Zone 1. Type: String ADServer2NetBIOSName: AllowedPattern: '^[a-zA-Z0-9]+$' Default: DC2 Description: The NetBIOS name of the second Active Directory server (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String AppInsightsApplicationName: Description: Application name to be used with AppInsights monitoring. Type: String Default: '' MaxLength: '300' AllowedPattern: '^[a-zA-Z0-9\-]*$' CertificateArn: AllowedPattern: '^(arn:[\w+=\/,.@-]+:[\w+=\/,.@-]+:[\w+=\/,.@-]*:[0-9]+:[\w+=,.@-]+(\/[\w+=,.@-]+)*)?$' Default: '' Description: (Conditional) If 'true' was chosen in Deploy Network Load Balancer option, specify the Certificate arn to be used by load balancer in arn:aws:acm:[REGION]:[ACCOUNTNUMBER]:certificate/[GUID] format. MaxLength: '90' Type: String DeployLoadBalancer: AllowedValues: - 'false' - 'true' Default: 'false' Description: Choose true to deploy an Network Load Balancer (NLB). Type: String DomainAdminPassword: AllowedPattern: '(?=^.{8,32}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*' Description: The password for the domain admin user. Must be at least 8 characters containing letters, numbers and symbols. MaxLength: '32' MinLength: '8' NoEcho: 'true' Type: String DomainAdminUser: AllowedPattern: '^[a-zA-Z0-9]+$' Default: StackAdmin Description: The user name for the account that will be used as Domain Administrator. This is separate from the default "Administrator" account. MaxLength: '25' MinLength: '5' Type: String DomainDNSName: AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9\-]*\.[a-zA-Z0-9]+$' Default: example.com Description: The fully qualified domain name (FQDN) of the forest root domain (e.g. example.com). MaxLength: '25' MinLength: '3' Type: String DomainMemberSGID: Description: The ID of the Domain Member Security Group (e.g., sg-7f16e910). Type: AWS::EC2::SecurityGroup::Id DomainNetBIOSName: AllowedPattern: '^[a-zA-Z0-9]+$' Default: EXAMPLE Description: The NetBIOS name of the domain (up to 15 characters) for users of earlier versions of Windows (e.g. EXAMPLE). MaxLength: '15' MinLength: '1' Type: String ExchangeServerVersion: AllowedValues: - '2016' - '2019' Default: '2019' Description: Version of Exchange Server to install. Options include either "2016" or "2019" Type: String EdgeInstanceType: Description: The Amazon EC2 instance type for the Exchange Edge Transport servers. Type: String Default: t3.large AllowedValues: - t3.large - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge ConstraintDescription: Select a general purpose instance type EdgeNode1NetBIOSName: AllowedPattern: '^[a-zA-Z0-9]+$' Default: EdgeNode1 Description: The NetBIOS name of the first Edge Server (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String EdgeNode1PrivateIP1: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.128.12 Description: The primary private IP for the first Edge Server located in Availability Zone 1. Type: String EdgeNode2NetBIOSName: AllowedPattern: '^[a-zA-Z0-9]+$' Default: EdgeNode2 Description: The NetBIOS name of the second Edge Server (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String EdgeNode2PrivateIP1: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.144.12 Description: The primary private IP for the second Edge Server located in Availability Zone 2. Type: String EnableBackups: AllowedValues: - 'yes' - 'no' Default: 'yes' Description: Creates a default daily/weekly backup schedule using AWS Backup Type: String EnableReFSVolumes: AllowedValues: - 'false' - 'true' Default: 'true' Description: Choose false to format the data and log volumes on Exchange nodes using NTFS instead of ReFS. Type: String EncryptDataVolumes: AllowedValues: - 'false' - 'true' Default: 'false' Description: Choose true to encrypt the data and log volumes on Exchange nodes. Type: String EncryptionKmsKey: AllowedPattern: '^(arn:[\w+=\/,.@-]+:[\w+=\/,.@-]+:[\w+=\/,.@-]*:[0-9]+:[\w+=,.@-]+(\/[\w+=,.@-]+)*)?$' Default: '' Description: (Optional) Specify the KMS encryption arn in format arn:aws:kms:[REGION]:[ACCOUNTNUMBER]:key/[GUID]. Leave blank to use default EBS encryption key. MaxLength: '90' Type: String ExchangeNodeInstanceType: AllowedValues: - m5.xlarge - r4.xlarge - r4.2xlarge - r4.4xlarge - r4.8xlarge - r5.xlarge - r5.2xlarge - r5.4xlarge - r5.8xlarge ConstraintDescription: Only EBS Optimized instance types r4.*, r5.* allowed Default: r5.xlarge Description: The Amazon EC2 instance type for the Exchange nodes. Type: String ExchangeNode1NetBIOSName: AllowedPattern: '^[a-zA-Z0-9]+$' Default: ExchangeNode1 Description: The NetBIOS name of the first Exchange Node (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String ExchangeNode1PrivateIP1: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.0.100 Description: The primary private IP for Exchange node 1. Type: String ExchangeNode1PrivateIP2: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.0.101 Description: The secondary private IP for Exchange node 1. Type: String ExchangeNode2NetBIOSName: AllowedPattern: '^[a-zA-Z0-9]+$' Default: ExchangeNode2 Description: The NetBIOS name of the second Exchange Node (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String ExchangeNode2PrivateIP1: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.32.100 Description: The primary private IP for Exchange node 2. Type: String ExchangeNode2PrivateIP2: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.32.101 Description: The secondary private IP for Exchange node 2. Type: String ExchangeNode3NetBIOSName: AllowedPattern: '^[a-zA-Z0-9]+$' Default: ExchangeNode3 Description: (Optional) The NetBIOS name of the third Exchange node (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String ExchangeNode3PrivateIP1: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.64.100 Description: (Optional) The primary private IP for the Exchange node 3. Type: String ExchangeNode3PrivateIP2: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.64.101 Description: (Optional) The secondary private IP for the Exchange node 3. Type: String Exchange2016Source: AllowedPattern: '^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)$' Default: 'https://download.microsoft.com/download/8/d/2/8d2d01b4-5bbb-4726-87da-0e331bc2b76f/ExchangeServer2016-x64-CU23.ISO' Description: Full URL (including https://) for Exchange 2016 ISO. MaxLength: '2000' MinLength: '1' Type: String Exchange2019Source: AllowedPattern: '^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)$' Default: 'https://download.microsoft.com/download/7/5/f/75f4d77e-002c-419c-a03a-948e8eb019f2/ExchangeServer2019-x64-CU13.ISO' Description: Full URL (including https://) for Exchange 2019 ISO. MaxLength: '2000' MinLength: '1' Type: String FileServerInstanceType: Default: t3.small AllowedValues: - t3.small - t3.large - m5.xlarge Description: The Amazon EC2 instance type for the file-share witness server. Type: String FileServerNetBIOSName: AllowedPattern: '^[a-zA-Z0-9]+$' Default: FileServer Description: The NetBIOS name of the file-share witness server (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String FileServerPrivateIP: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$' Default: 10.0.0.200 Description: The primary private IP for the file-share witness server. Type: String IncludeEdgeTransportRole: AllowedValues: - 'yes' - 'no' Default: 'no' Description: Choose yes to deploy Exchange Edge Transport servers in the public subnets. Type: String KeyPairName: Description: The public/private key pair, which allows you to connect securely to your instance after it launches. When you created an AWS account, this is the key pair you created in your preferred region. Type: AWS::EC2::KeyPair::KeyName PrivateSubnet1ID: Description: The ID of the private subnet 1 in Availability Zone 1 (e.g., subnet-a0246dcd). Type: AWS::EC2::Subnet::Id PrivateSubnet1CIDR: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$' Default: 10.0.0.0/19 Description: The CIDR block for the private subnet 1 located in Availability Zone 1. Type: String PrivateSubnet2ID: Description: The ID of the private subnet 2 in Availability Zone 2 (e.g., subnet-a0246dcd). Type: AWS::EC2::Subnet::Id PrivateSubnet2CIDR: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$' Default: 10.0.32.0/19 Description: The CIDR block for the private subnet 2 located in Availability Zone 2. Type: String PrivateSubnet3ID: Default: '' Description: (Optional) The ID of the private subnet 3 in Availability Zone 3 (e.g., subnet-a0246dcd) Type: String PrivateSubnet3CIDR: AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ Default: 10.0.64.0/19 Description: (Optional) The CIDR block for private subnet 3 located in Availability Zone 3. Type: String PublicSubnet1ID: Description: (Optional) The ID of the public subnet 1 in Availability Zone 1 (e.g., subnet-a0246dcd). Type: AWS::EC2::Subnet::Id PublicSubnet2ID: Description: (Optional) The ID of the public subnet 2 in Availability Zone 2 (e.g., subnet-a0246dcd). Type: AWS::EC2::Subnet::Id QSS3BucketName: AllowedPattern: '^[a-z0-9]+[a-z0-9\.\-]*[a-z0-9]+$' ConstraintDescription: Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Default: aws-quickstart Description: S3 bucket name for the Quick Start assets. Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Type: String QSS3BucketRegion: AllowedPattern: '^[a-z]+\-[a-z\-]+\-[0-9]{1}$' Default: us-east-1 Description: The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value. Type: String QSS3KeyPrefix: AllowedPattern: '^[a-zA-Z0-9\-\/]+$' ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). Default: quickstart-microsoft-exchange/ Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). Type: String SetupAppInsightsMonitoring: AllowedValues: - 'true' - 'false' Default: 'false' Description: Setup Application Insights monitoring for Exchange resources. Type: String ThirdAZ: AllowedValues: - 'no' - witness - full Default: 'no' Description: Enables you to deploy three Availability Zones. The third Availability Zone can either be used just for the witness, or can be a full Exchange node. If you use the Availability Zone for the witness, you must set the File Server Private IP Address parameter to an IP in the third subnet range. Type: String VPCID: Description: The ID of the VPC (e.g., vpc-0343606e). Type: AWS::EC2::VPC::Id VPCCidrBlock: AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/(1[6-9]|2[0-8]))$' ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 Default: 10.0.0.0/16 Description: The CIDR block for the VPC. Type: String VolumeIops: Default: '3000' Description: The Iops for the Exchange Data drive (Only used when volume type is gp3). MaxValue: '16000' MinValue: '3000' Type: Number VolumeSize: Default: '500' Description: The volume size for the Exchange data drive. MaxValue: '16000' MinValue: '125' Type: Number VolumeType: AllowedValues: - gp3 - st1 Default: gp3 Description: The volume type for the Exchange data drive. Type: String WS2016FULLBASE: Type: 'AWS::SSM::Parameter::Value' Default: '/aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base' Description: The image name for the AWS Systems Manager Windows Server 2016 AMI ID lookup WS2022FULLBASE: Type: 'AWS::SSM::Parameter::Value' Default: '/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-Base' Description: The image name for the AWS Systems Manager Windows Server 2022 AMI ID lookup Conditions: UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] DeployEdge: !Equals [!Ref IncludeEdgeTransportRole, 'yes'] DeployLoadBalancer: !Equals [!Ref DeployLoadBalancer, 'true'] Exchange2016Selected: !Equals [!Ref ExchangeServerVersion, '2016'] UsingDefaultAppName: !Equals [!Ref AppInsightsApplicationName, ''] AppInsightsEnabled: !Equals [!Ref SetupAppInsightsMonitoring, 'true'] EncryptionKmsKeySelected: !Not - !Equals - !Ref EncryptionKmsKey - '' IsTwoNode: !Not - !Equals - !Ref ThirdAZ - full ThirdAzIsFullNode: !Equals [!Ref ThirdAZ, 'full'] ThirdAzIsWitness: !Equals [!Ref ThirdAZ, 'witness'] UseEncryptedDataVolumes: !Equals [!Ref EncryptDataVolumes, 'true'] UseReFSDataVolumes: !Equals [!Ref EnableReFSVolumes, 'true'] VolIsgp3: !Equals [!Ref VolumeType, 'gp3'] EnableBackups: !Equals [!Ref EnableBackups, 'yes'] Rules: SubnetsInVPC: Assertions: - Assert: !EachMemberIn - !ValueOfAll - AWS::EC2::Subnet::Id - VpcId - !RefAll AWS::EC2::VPC::Id AssertDescription: All subnets must in the VPC Mappings: MediaLinksMapper: UCMA: ALL: https://download.microsoft.com/download/2/C/4/2C47A5C1-A1F3-4843-B9FE-84C0032C61EC/UcmaRuntimeSetup.exe NetFramework: v48: https://download.visualstudio.microsoft.com/download/pr/7afca223-55d2-470a-8edc-6a1739ae3252/abd170b4b0ec15ad0222a809b761a036/ndp48-x86-x64-allos-enu.exe VisualCRuntime: 2012x64: https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe 2013x64: https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe UrlRewrite: v21: https://download.microsoft.com/download/1/2/8/128E2E22-C1B9-44A4-BE2A-5859ED1D4592/rewrite_amd64_en-US.msi SecurityUpdates: e2016: https://download.microsoft.com/download/e/9/a/e9a07b3b-b440-44bb-8484-7ece339ffaf1/Exchange2016-KB5019758-x64-en.exe # KB5019758 for Exchange 2017 CU23 e2019: https://download.microsoft.com/download/d/b/9/db9ee80e-9c18-40d8-91f9-f2353dcf4f86/Exchange2019-KB5019758-x64-en.exe # KB5019758 for Exchange 2019 CU12 Resources: ExchangeAdminSecrets: Type: AWS::SecretsManager::Secret Properties: Name: !Sub 'ExAltUserSecrets-${AWS::StackName}' Description: Exchange Admin User from AD Quick Start SecretString: !Sub '{"UserName":"${DomainAdminUser}","Password":"${DomainAdminPassword}"}' EDGE1: DependsOn: ExchangeNode1WaitCondition Condition: DeployEdge Metadata: AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref ExchangeRole AWS::CloudFormation::Init: Cleanup: commands: a-disable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Disable-CredSSP.ps1" waitAfterCompletion: '0' b-enable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Enable" waitAfterCompletion: '0' c-remove-wsmantrustedhost: command: powershell.exe -Command "Set-Item WSMan:\localhost\Client\TrustedHosts -value '' -Force" waitAfterCompletion: '0' Finalize: commands: a-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever b-signal-success: command: powershell -Command "Write-AWSQuickStartStatus" Install: commands: a-install-exchange-edge: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-ExchangeEdgeServer.ps1 -EdgeNodeNetBIOSName ' - !Ref EdgeNode1NetBIOSName - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - '''"' waitAfterCompletion: '0' b-create-edge-dnsrecord: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Configure-EdgeDnsRecord.ps1 -EdgeNodeNetBIOSName ' - !Ref EdgeNode1NetBIOSName - ''' -EdgeNodePrivateIP ''' - !Ref EdgeNode1PrivateIP1 - ''' -DnsServer ''' - !Ref ADServer1PrivateIP - ''' -DomainNetBIOSName ''' - !Ref DomainDNSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - '''"' waitAfterCompletion: '0' Prep: commands: a-rename-computer: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Rename-Computer.ps1 -Restart -NewName ' - !Ref EdgeNode1NetBIOSName - '''"' waitAfterCompletion: forever b-set-DnsSuffix: command: !Join - '' - - powershell.exe -command "c:\cfn\scripts\Set-PrimaryDNSSuffix.ps1 -Suffix ' - !Ref DomainDNSName - '''"' waitAfterCompletion: forever c-install-edge-prerequisites: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-EdgePrerequisites.ps1 -ExchangeServerVersion ' - !Ref ExchangeServerVersion - '''"' waitAfterCompletion: '0' d-reset-local-admin: command: !Join - '' - - powershell.exe -command C:\cfn\scripts\Reset-LocalAdminPassword.ps1 -ADAdminSecParam ' - !Ref ExchangeAdminSecrets - '''' waitAfterCompletion: '0' e-enable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Enable-CredSSP.ps1" waitAfterCompletion: '0' f-disable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Disable" waitAfterCompletion: '0' g-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever h-download-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-PreRequisites.ps1 -source ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' i-expand-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Expand-Exchange.ps1 -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - ''' -ExchangeDownloadLink ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' j-configure-wsmantrustedhost: command: !Sub | powershell.exe -command "Set-Item WSMan:\localhost\Client\TrustedHosts -value '${ADServer1PrivateIP}' -Force" waitAfterCompletion: '0' k-download-visualcruntime: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' waitAfterCompletion: '0' l-download-netframework: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' m-install-visualcruntime: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-VisualCRuntime.ps1 -DomainNetBIOSName ' - !Ref EdgeNode1NetBIOSName - ''' -DomainAdminUser ''Administrator' - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -VisualCRuntimeLink ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' waitAfterCompletion: '0' n-install-netframework: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-NetFramework.ps1 -DomainNetBIOSName ' - !Ref EdgeNode1NetBIOSName - ''' -DomainAdminUser ''Administrator' - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -NetFrameworkDownloadLink ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' waitAfterCompletion: '0' o-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever setup: commands: a-set-execution-policy: command: powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Force" waitAfterCompletion: '0' b-unpack-quickstart-module: command: powershell.exe -Command C:\cfn\scripts\Unzip-Archive.ps1 -Source C:\cfn\modules\AWSQuickStart.zip -Destination C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ waitAfterCompletion: '0' c-init-quickstart-module: command: !Join - '' - - powershell.exe -Command " - New-AWSQuickStartWaitHandle -Handle ' - !Ref EdgeNode1WaitHandle - '''"' waitAfterCompletion: '0' files: C:\cfn\modules\AWSQuickStart.zip: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/modules/AWSQuickStart.zip - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Unzip-Archive.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Unzip-Archive.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Rename-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Rename-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Restart-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Restart-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Join-Domain.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Join-Domain.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Enable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Enable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Disable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Disable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Expand-Exchange.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Expand-Exchange.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-EdgePrerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-EdgePrerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchangeEdgeServer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchangeEdgeServer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Set-PrimaryDNSSuffix.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Set-PrimaryDNSSuffix.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Configure-EdgeDnsRecord.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Configure-EdgeDnsRecord.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Reset-LocalAdminPassword.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Reset-LocalAdminPassword.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Configure-UAC.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Configure-UAC.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Download-Prerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Download-Prerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-VisualCRuntime.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-VisualCRuntime.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-NetFramework.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-NetFramework.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-SecurityUpdates.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-SecurityUpdates.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds configSets: config: - setup - Prep - Install - Cleanup - Finalize Properties: BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp3 - DeviceName: /dev/xvdca VirtualName: ephemeral0 ImageId: !If - Exchange2016Selected - !Ref WS2016FULLBASE - !Ref WS2022FULLBASE IamInstanceProfile: !Ref ExchangeProfile InstanceType: !Ref EdgeInstanceType KeyName: !Ref KeyPairName NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' GroupSet: - !Ref DomainMemberSGID - !Ref EXCHEdgeSecurityGroup PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref EdgeNode1PrivateIP1 SubnetId: !Ref PublicSubnet1ID Tags: - Key: Name Value: !Ref EdgeNode1NetBIOSName Tenancy: default UserData: !Base64 Fn::Join: - '' - - ' Type: AWS::EC2::Instance EdgeNode1EIP: Condition: DeployEdge Type: AWS::EC2::EIP Properties: Domain: vpc InstanceId: !Ref EDGE1 EDGE2: DependsOn: ExchangeNode1WaitCondition Condition: DeployEdge Metadata: AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref ExchangeRole AWS::CloudFormation::Init: Cleanup: commands: a-disable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Disable-CredSSP.ps1" waitAfterCompletion: '0' b-enable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Enable" waitAfterCompletion: '0' c-remove-wsmantrustedhost: command: powershell.exe -Command "Set-Item WSMan:\localhost\Client\TrustedHosts -value '' -Force" waitAfterCompletion: '0' Finalize: commands: a-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever b-signal-success: command: powershell -Command "Write-AWSQuickStartStatus" Install: commands: a-install-exchange-edge: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-ExchangeEdgeServer.ps1 -EdgeNodeNetBIOSName ' - !Ref EdgeNode2NetBIOSName - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - '''"' waitAfterCompletion: '0' b-create-edge-dnsrecord: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Configure-EdgeDnsRecord.ps1 -EdgeNodeNetBIOSName ' - !Ref EdgeNode2NetBIOSName - ''' -EdgeNodePrivateIP ''' - !Ref EdgeNode2PrivateIP1 - ''' -DnsServer ''' - !Ref ADServer1PrivateIP - ''' -DomainNetBIOSName ''' - !Ref DomainDNSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - '''"' waitAfterCompletion: '0' Prep: commands: a-rename-computer: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Rename-Computer.ps1 -Restart -NewName ' - !Ref EdgeNode2NetBIOSName - '''"' waitAfterCompletion: forever b-set-DnsSuffix: command: !Join - '' - - powershell.exe -command "c:\cfn\scripts\Set-PrimaryDNSSuffix.ps1 -Suffix ' - !Ref DomainDNSName - '''"' waitAfterCompletion: forever c-install-edge-prerequisites: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-EdgePrerequisites.ps1 -ExchangeServerVersion ' - !Ref ExchangeServerVersion - '''"' waitAfterCompletion: '0' d-reset-local-admin: command: !Join - '' - - powershell.exe -command C:\cfn\scripts\Reset-LocalAdminPassword.ps1 -ADAdminSecParam ' - !Ref ExchangeAdminSecrets - '''' waitAfterCompletion: '0' e-enable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Enable-CredSSP.ps1" waitAfterCompletion: '0' f-disable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Disable" waitAfterCompletion: '0' g-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever h-download-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-PreRequisites.ps1 -source ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' i-expand-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Expand-Exchange.ps1 -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - ''' -ExchangeDownloadLink ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' j-configure-wsmantrustedhost: command: !Sub | powershell.exe -command "Set-Item WSMan:\localhost\Client\TrustedHosts -value '${ADServer1PrivateIP}' -Force" waitAfterCompletion: '0' k-download-visualcruntime: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' waitAfterCompletion: '0' l-download-netframework: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' m-install-visualcruntime: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-VisualCRuntime.ps1 -DomainNetBIOSName ' - !Ref EdgeNode2NetBIOSName - ''' -DomainAdminUser ''Administrator' - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -VisualCRuntimeLink ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' waitAfterCompletion: '0' n-install-netframework: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-NetFramework.ps1 -DomainNetBIOSName ' - !Ref EdgeNode2NetBIOSName - ''' -DomainAdminUser ''Administrator' - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -NetFrameworkDownloadLink ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' waitAfterCompletion: '0' o-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever setup: commands: a-set-execution-policy: command: powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Force" waitAfterCompletion: '0' b-unpack-quickstart-module: command: powershell.exe -Command C:\cfn\scripts\Unzip-Archive.ps1 -Source C:\cfn\modules\AWSQuickStart.zip -Destination C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ waitAfterCompletion: '0' c-init-quickstart-module: command: !Join - '' - - powershell.exe -Command " - New-AWSQuickStartWaitHandle -Handle ' - !Ref EdgeNode2WaitHandle - '''"' waitAfterCompletion: '0' files: C:\cfn\modules\AWSQuickStart.zip: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/modules/AWSQuickStart.zip - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Unzip-Archive.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Unzip-Archive.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Rename-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Rename-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Restart-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Restart-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Join-Domain.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Join-Domain.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Enable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Enable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Disable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Disable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Expand-Exchange.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Expand-Exchange.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-EdgePrerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-EdgePrerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchangeEdgeServer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchangeEdgeServer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Set-PrimaryDNSSuffix.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Set-PrimaryDNSSuffix.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Configure-EdgeDnsRecord.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Configure-EdgeDnsRecord.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Reset-LocalAdminPassword.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Reset-LocalAdminPassword.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Configure-UAC.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Configure-UAC.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Download-Prerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Download-Prerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-VisualCRuntime.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-VisualCRuntime.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-NetFramework.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-NetFramework.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-SecurityUpdates.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-SecurityUpdates.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds configSets: config: - setup - Prep - Install - Cleanup - Finalize Properties: BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp3 - DeviceName: /dev/xvdca VirtualName: ephemeral0 IamInstanceProfile: !Ref ExchangeProfile ImageId: !If - Exchange2016Selected - !Ref WS2016FULLBASE - !Ref WS2022FULLBASE InstanceType: !Ref EdgeInstanceType KeyName: !Ref KeyPairName NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' GroupSet: - !Ref DomainMemberSGID - !Ref EXCHEdgeSecurityGroup PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref EdgeNode2PrivateIP1 SubnetId: !Ref PublicSubnet2ID Tags: - Key: Name Value: !Ref EdgeNode2NetBIOSName Tenancy: default UserData: !Base64 Fn::Join: - '' - - ' Type: AWS::EC2::Instance EdgeNode2EIP: Condition: DeployEdge Type: AWS::EC2::EIP Properties: Domain: vpc InstanceId: !Ref EDGE2 EdgeNode1WaitCondition: Condition: DeployEdge DependsOn: EDGE1 Properties: Handle: !Ref EdgeNode1WaitHandle Timeout: '9000' Type: AWS::CloudFormation::WaitCondition EdgeNode1WaitHandle: Condition: DeployEdge Type: AWS::CloudFormation::WaitConditionHandle EdgeNode2WaitCondition: Condition: DeployEdge DependsOn: EDGE2 Properties: Handle: !Ref EdgeNode2WaitHandle Timeout: '9000' Type: AWS::CloudFormation::WaitCondition EdgeNode2WaitHandle: Condition: DeployEdge Type: AWS::CloudFormation::WaitConditionHandle EXCHClientSecurityGroup: Properties: GroupDescription: Exchange Client access ports SecurityGroupIngress: - Description: Encrypted web connections from clients FromPort: 443 IpProtocol: tcp CidrIp: !Ref VPCCidrBlock ToPort: 443 - Description: Unencrypted web connections from clients FromPort: 80 IpProtocol: tcp CidrIp: !Ref VPCCidrBlock ToPort: 80 - Description: IMAP4 clients FromPort: 143 IpProtocol: tcp CidrIp: !Ref VPCCidrBlock ToPort: 143 - Description: Secure IMAP4 clients FromPort: 993 IpProtocol: tcp CidrIp: !Ref VPCCidrBlock ToPort: 993 - Description: POP3 clients FromPort: 110 IpProtocol: tcp CidrIp: !Ref VPCCidrBlock ToPort: 110 - Description: Secure POP3 clients FromPort: 995 IpProtocol: tcp CidrIp: !Ref VPCCidrBlock ToPort: 995 - Description: Authenticated SMTP clients FromPort: 587 IpProtocol: tcp CidrIp: !Ref VPCCidrBlock ToPort: 587 - Description: SMTP clients FromPort: 25 IpProtocol: tcp CidrIp: !Ref VPCCidrBlock ToPort: 25 VpcId: !Ref VPCID Type: AWS::EC2::SecurityGroup ExchangeRole: Type: AWS::IAM::Role Properties: Policies: - PolicyName: aws-quick-start-s3-policy PolicyDocument: Version: '2012-10-17' Statement: - Action: - s3:GetObject Resource: !Sub - arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}* - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Effect: Allow - PolicyName: AD-SSM-Secrets PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - secretsmanager:GetSecretValue - secretsmanager:DescribeSecret Resource: !Ref ExchangeAdminSecrets Path: / ManagedPolicyArns: - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' AssumeRolePolicyDocument: Statement: - Action: - sts:AssumeRole Principal: Service: - ec2.amazonaws.com Effect: Allow Version: '2012-10-17' ExchangeProfile: Type: AWS::IAM::InstanceProfile Properties: Roles: - !Ref ExchangeRole Path: / EXCHEdgeSecurityGroup: Condition: DeployEdge Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable communications for Exchange Edge Transport Servers VpcId: !Ref VPCID SecurityGroupIngress: - Description: Edge Server directory synchronization IpProtocol: tcp FromPort: 50636 ToPort: 50636 CidrIp: !Ref PrivateSubnet1CIDR - Description: Edge Server directory synchronization IpProtocol: tcp FromPort: 50636 ToPort: 50636 CidrIp: !Ref PrivateSubnet2CIDR - Description: Edge Server directory synchronization IpProtocol: tcp FromPort: 50636 ToPort: 50636 CidrIp: !Ref PrivateSubnet3CIDR - Description: Inbound mail over SMTP IpProtocol: tcp FromPort: 25 ToPort: 25 CidrIp: 0.0.0.0/0 FileServerWaitCondition: Condition: IsTwoNode DependsOn: FileServer Properties: Handle: !Ref FileServerWaitHandle Timeout: '3600' Type: AWS::CloudFormation::WaitCondition FileServerWaitHandle: Type: AWS::CloudFormation::WaitConditionHandle ExchangeNode1WaitCondition: DependsOn: ExchangeNode1 Properties: Handle: !Ref ExchangeNode1WaitHandle Timeout: '9000' Type: AWS::CloudFormation::WaitCondition ExchangeNode1WaitHandle: Type: AWS::CloudFormation::WaitConditionHandle ExchangeNode2WaitCondition: DependsOn: ExchangeNode2 Properties: Handle: !Ref ExchangeNode2WaitHandle Timeout: '9000' Type: AWS::CloudFormation::WaitCondition ExchangeNode2WaitHandle: Type: AWS::CloudFormation::WaitConditionHandle ExchangeNode3WaitCondition: Condition: ThirdAzIsFullNode DependsOn: ExchangeNode3 Properties: Handle: !Ref ExchangeNode3WaitHandle Timeout: '9000' Type: AWS::CloudFormation::WaitCondition ExchangeNode3WaitHandle: Condition: ThirdAzIsFullNode Type: AWS::CloudFormation::WaitConditionHandle FileServer: Condition: IsTwoNode Metadata: AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref ExchangeRole AWS::CloudFormation::Init: Cleanup: {} Configure: {} Finalize: commands: a-signal-success: command: powershell -Command "Write-AWSQuickStartStatus" Install: {} Prep: commands: a-rename-computer: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Rename-Computer.ps1 -Restart -NewName ' - !Ref FileServerNetBIOSName - '''"' waitAfterCompletion: forever b-join-domain: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Join-Domain.ps1 -DomainName ' - !Ref DomainDNSName - ''' -ADAdminSecParam ''' - !Ref ExchangeAdminSecrets - '''"' waitAfterCompletion: forever c-Invoke-ADReplication-DC1: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Invoke-ADReplication.ps1 - ' -ADAdminSecParam ''' - !Ref ExchangeAdminSecrets - ''' -DomainController ''' - !Ref ADServer1NetBIOSName - '''"' waitAfterCompletion: '0' d-Invoke-ADReplication-DC2: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Invoke-ADReplication.ps1 - ' -ADAdminSecParam ''' - !Ref ExchangeAdminSecrets - ''' -DomainController ''' - !Ref ADServer2NetBIOSName - '''"' waitAfterCompletion: '15' setup: commands: a-set-execution-policy: command: powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Force" waitAfterCompletion: '0' b-unpack-quickstart-module: command: powershell.exe -Command C:\cfn\scripts\Unzip-Archive.ps1 -Source C:\cfn\modules\AWSQuickStart.zip -Destination C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ waitAfterCompletion: '0' c-init-quickstart-module: command: !Join - '' - - powershell.exe -Command " - New-AWSQuickStartWaitHandle -Handle ' - !Ref FileServerWaitHandle - '''"' waitAfterCompletion: '0' files: C:\cfn\scripts\Unzip-Archive.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Unzip-Archive.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\modules\AWSQuickStart.zip: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/modules/AWSQuickStart.zip - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Join-Domain.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Join-Domain.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Invoke-ADReplication.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Invoke-ADReplication.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Rename-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Rename-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds configSets: config: - setup - Prep - Install - Configure - Cleanup - Finalize Properties: BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp3 ImageId: !Ref WS2022FULLBASE IamInstanceProfile: !Ref ExchangeProfile InstanceType: !Ref FileServerInstanceType KeyName: !Ref KeyPairName NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' GroupSet: - !Ref DomainMemberSGID - !Ref ExchangeSecurityGroup - !Ref EXCHClientSecurityGroup PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref FileServerPrivateIP SubnetId: !If - ThirdAzIsWitness - !Ref PrivateSubnet3ID - !Ref PrivateSubnet1ID Tags: - Key: Name Value: !Ref FileServerNetBIOSName UserData: !Base64 Fn::Join: - '' - - ' Type: AWS::EC2::Instance ExchangeNode1: Metadata: AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref ExchangeRole AWS::CloudFormation::Init: Cleanup: commands: a-disable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Disable-CredSSP.ps1" waitAfterCompletion: '0' b-enable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Enable" waitAfterCompletion: '0' Finalize: commands: a-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever b-signal-success: command: powershell -Command "Write-AWSQuickStartStatus" Install: commands: a-install-ucma-runtime: command: powershell.exe -Command "C:\cfn\scripts\Install-UcmaRuntime.ps1" waitAfterCompletion: '0' b-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever c-install-exchange-organization: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-ExchangeOrg.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - '''"' waitAfterCompletion: '0' d-install-exchange: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-ExchangeServer.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - ''' -ServerIndex ''1' - '''"' waitAfterCompletion: '0' Prep: commands: a-rename-computer: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Rename-Computer.ps1 -Restart -NewName ' - !Ref ExchangeNode1NetBIOSName - '''"' waitAfterCompletion: forever b-join-domain: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Join-Domain.ps1 -DomainName ' - !Ref DomainDNSName - ''' -ADAdminSecParam ''' - !Ref ExchangeAdminSecrets - '''"' waitAfterCompletion: forever c-install-windows-failover-clustering: command: powershell.exe -Command "C:\cfn\scripts\Install-WindowsFailoverClustering.ps1" waitAfterCompletion: '0' d-install-exchange-prerequisites: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-ExchPrerequisites.ps1 -ExchangeServerVersion ' - !Ref ExchangeServerVersion - '''"' waitAfterCompletion: forever e-enable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Enable-CredSSP.ps1" waitAfterCompletion: '0' f-disable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Disable" waitAfterCompletion: '0' g-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever h-initializedisks: command: !If - UseReFSDataVolumes - powershell.exe -command "C:\cfn\scripts\Initialize-Disks.ps1" -EnableReFSVolumes $true - powershell.exe -command "C:\cfn\scripts\Initialize-Disks.ps1" -EnableReFSVolumes $false waitAfterCompletion: '0' i-download-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-PreRequisites.ps1 -source ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' j-expand-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Expand-Exchange.ps1 -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - ''' -ExchangeDownloadLink ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' k-download-ucmaruntime: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-PreRequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - UCMA - ALL - '''"' waitAfterCompletion: '0' l-download-visualcruntime: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2013x64 - '''"' waitAfterCompletion: '0' m-download-netframework: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' waitAfterCompletion: '0' n-install-visualcruntime: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-VisualCRuntime.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -VisualCRuntimeLink ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2013x64 - '''"' o-install-netframework: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-NetFramework.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -NetFrameworkDownloadLink ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' p-download-visualcruntime2012: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' q-install-visualcruntime2012: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-VisualCRuntime.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -VisualCRuntimeLink ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' r-download-urlrewrite: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - UrlRewrite - v21 - '''"' s-install-urlrewrite: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-UrlRewrite.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -UrlRewriteLink ''' - !FindInMap - MediaLinksMapper - UrlRewrite - v21 - '''"' z-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever setup: commands: a-set-execution-policy: command: powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Force" waitAfterCompletion: '0' b-unpack-quickstart-module: command: powershell.exe -Command C:\cfn\scripts\Unzip-Archive.ps1 -Source C:\cfn\modules\AWSQuickStart.zip -Destination C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ waitAfterCompletion: '0' c-init-quickstart-module: command: !Join - '' - - powershell.exe -Command " - New-AWSQuickStartWaitHandle -Handle ' - !Ref ExchangeNode1WaitHandle - '''"' waitAfterCompletion: '0' files: C:\cfn\scripts\Unzip-Archive.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Unzip-Archive.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\modules\AWSQuickStart.zip: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/modules/AWSQuickStart.zip - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Rename-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Rename-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Restart-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Restart-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Join-Domain.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Join-Domain.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Enable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Enable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Disable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Disable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchPrerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchPrerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Expand-Exchange.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Expand-Exchange.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-WindowsFailoverClustering.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-WindowsFailoverClustering.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-UcmaRuntime.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-UcmaRuntime.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchangeOrg.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchangeOrg.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchangeServer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchangeServer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Configure-UAC.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Configure-UAC.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Download-Prerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Download-Prerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-VisualCRuntime.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-VisualCRuntime.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-NetFramework.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-NetFramework.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Initialize-Disks.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Initialize-Disks.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-UrlRewrite.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-UrlRewrite.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-SecurityUpdates.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-SecurityUpdates.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds configSets: config: - setup - Prep - Install - Cleanup - Finalize Properties: BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp3 - DeviceName: /dev/xvdca VirtualName: ephemeral0 EbsOptimized: true ImageId: !If - Exchange2016Selected - !Ref WS2016FULLBASE - !Ref WS2022FULLBASE IamInstanceProfile: !Ref ExchangeProfile InstanceType: !Ref ExchangeNodeInstanceType KeyName: !Ref KeyPairName NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' GroupSet: - !Ref DomainMemberSGID - !Ref ExchangeSecurityGroup - !Ref EXCHClientSecurityGroup PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref ExchangeNode1PrivateIP1 - Primary: false PrivateIpAddress: !Ref ExchangeNode1PrivateIP2 SubnetId: !Ref PrivateSubnet1ID Tags: - Key: Name Value: !Ref ExchangeNode1NetBIOSName - Key: Backup Value: !If [EnableBackups, 'yes', 'no'] Tenancy: default UserData: !Base64 Fn::Join: - '' - - ' Type: AWS::EC2::Instance ExchangeNode2: Type: AWS::EC2::Instance Metadata: PseudoDependsOn: !If - IsTwoNode - - !Ref FileServerWaitCondition - !Ref ExchangeNode1WaitCondition - - !Ref ExchangeNode1WaitCondition - !Ref ExchangeNode3WaitCondition AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref ExchangeRole AWS::CloudFormation::Init: Cleanup: commands: a-disable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Disable-CredSSP.ps1" waitAfterCompletion: '0' b-enable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Enable" waitAfterCompletion: '0' ConfigureDAG: commands: a-configure-fileserver: command: !If - IsTwoNode - !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Add-ExchangeGroup.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -ServerName ''' - !Ref FileServerNetBIOSName - '''"' - !Join - '' - - powershell.exe -Command exit waitAfterCompletion: '10' b-configure-dag: command: !If - IsTwoNode - !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Configure-ExchangeDAG.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -ExchangeNode1NetBIOSName ''' - !Ref ExchangeNode1NetBIOSName - ''' -ExchangeNode2NetBIOSName ''' - !Ref ExchangeNode2NetBIOSName - ''' -ExchangeNode1PrivateIP2 ''' - !Ref ExchangeNode1PrivateIP2 - ''' -ExchangeNode2PrivateIP2 ''' - !Ref ExchangeNode2PrivateIP2 - ''' -FileServerNetBIOSName ''' - !Ref FileServerNetBIOSName - '''"' - !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Configure-ExchangeDAG.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -ExchangeNode1NetBIOSName ''' - !Ref ExchangeNode1NetBIOSName - ''' -ExchangeNode2NetBIOSName ''' - !Ref ExchangeNode2NetBIOSName - ''' -ExchangeNode3NetBIOSName ''' - !Ref ExchangeNode3NetBIOSName - ''' -ExchangeNode1PrivateIP2 ''' - !Ref ExchangeNode1PrivateIP2 - ''' -ExchangeNode2PrivateIP2 ''' - !Ref ExchangeNode2PrivateIP2 - ''' -ExchangeNode3PrivateIP2 ''' - !Ref ExchangeNode3PrivateIP2 - '''"' waitAfterCompletion: '0' Finalize: commands: a-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever b-signal-success: command: powershell -Command "Write-AWSQuickStartStatus" Install: commands: a-install-ucma-runtime: command: powershell.exe -Command "C:\cfn\scripts\Install-UcmaRuntime.ps1 waitAfterCompletion: '0' b-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever c-install-exchange: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-ExchangeServer.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - ''' -ServerIndex ''2' - '''"' waitAfterCompletion: '0' Prep: commands: a-rename-computer: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Rename-Computer.ps1 -Restart -NewName ' - !Ref ExchangeNode2NetBIOSName - '''"' waitAfterCompletion: forever b-join-domain: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Join-Domain.ps1 -DomainName ' - !Ref DomainDNSName - ''' -ADAdminSecParam ''' - !Ref ExchangeAdminSecrets - '''"' waitAfterCompletion: forever c-install-windows-failover-clustering: command: powershell.exe -Command "C:\cfn\scripts\Install-WindowsFailoverClustering.ps1" waitAfterCompletion: '0' d-install-exchange-prerequisites: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-ExchPrerequisites.ps1 -ExchangeServerVersion ' - !Ref ExchangeServerVersion - '''"' waitAfterCompletion: forever e-enable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Enable-CredSSP.ps1" waitAfterCompletion: '0' f-disable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Disable" waitAfterCompletion: '0' g-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever h-initializedisks: command: !If - UseReFSDataVolumes - powershell.exe -command "C:\cfn\scripts\Initialize-Disks.ps1" -EnableReFSVolumes $true - powershell.exe -command "C:\cfn\scripts\Initialize-Disks.ps1" -EnableReFSVolumes $false waitAfterCompletion: '0' i-download-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-PreRequisites.ps1 -source ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' j-expand-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Expand-Exchange.ps1 -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - ''' -ExchangeDownloadLink ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' k-download-ucmaruntime: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-PreRequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - UCMA - ALL - '''"' waitAfterCompletion: '0' l-download-visualcruntime: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2013x64 - '''"' waitAfterCompletion: '0' m-download-netframework: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' waitAfterCompletion: '0' n-install-visualcruntime: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-VisualCRuntime.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -VisualCRuntimeLink ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2013x64 - '''"' o-install-netframework: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-NetFramework.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -NetFrameworkDownloadLink ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' p-download-visualcruntime2012: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' q-install-visualcruntime2012: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-VisualCRuntime.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -VisualCRuntimeLink ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' r-download-urlrewrite: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - UrlRewrite - v21 - '''"' s-install-urlrewrite: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-UrlRewrite.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -UrlRewriteLink ''' - !FindInMap - MediaLinksMapper - UrlRewrite - v21 - '''"' z-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever setup: commands: a-set-execution-policy: command: powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Force" waitAfterCompletion: '0' b-unpack-quickstart-module: command: powershell.exe -Command C:\cfn\scripts\Unzip-Archive.ps1 -Source C:\cfn\modules\AWSQuickStart.zip -Destination C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ waitAfterCompletion: '0' c-init-quickstart-module: command: !Join - '' - - powershell.exe -Command " - New-AWSQuickStartWaitHandle -Handle ' - !Ref ExchangeNode2WaitHandle - '''"' waitAfterCompletion: '0' files: C:\cfn\scripts\Unzip-Archive.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Unzip-Archive.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\modules\AWSQuickStart.zip: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/modules/AWSQuickStart.zip - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Rename-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Rename-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Restart-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Restart-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Join-Domain.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Join-Domain.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Enable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Enable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Disable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Disable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchPrerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchPrerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Expand-Exchange.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Expand-Exchange.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-WindowsFailoverClustering.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-WindowsFailoverClustering.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-UcmaRuntime.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-UcmaRuntime.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchangeOrg.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchangeOrg.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchangeServer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchangeServer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Configure-UAC.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Configure-UAC.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Download-Prerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Download-Prerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-VisualCRuntime.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-VisualCRuntime.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-NetFramework.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-NetFramework.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Add-ExchangeGroup.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Add-ExchangeGroup.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Configure-ExchangeDAG.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Configure-ExchangeDAG.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Initialize-Disks.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Initialize-Disks.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-UrlRewrite.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-UrlRewrite.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-SecurityUpdates.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-SecurityUpdates.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds configSets: config: - setup - Prep - Install # - ConfigureDAG - Cleanup - Finalize Properties: BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp3 - DeviceName: /dev/xvdca VirtualName: ephemeral0 EbsOptimized: true ImageId: !If - Exchange2016Selected - !Ref WS2016FULLBASE - !Ref WS2022FULLBASE IamInstanceProfile: !Ref ExchangeProfile InstanceType: !Ref ExchangeNodeInstanceType KeyName: !Ref KeyPairName NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' GroupSet: - !Ref DomainMemberSGID - !Ref ExchangeSecurityGroup - !Ref EXCHClientSecurityGroup PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref ExchangeNode2PrivateIP1 - Primary: false PrivateIpAddress: !Ref ExchangeNode2PrivateIP2 SubnetId: !Ref PrivateSubnet2ID Tags: - Key: Name Value: !Ref ExchangeNode2NetBIOSName - Key: Backup Value: !If [EnableBackups, 'yes', 'no'] Tenancy: default UserData: !Base64 Fn::Join: - '' - - ' ExchangeNode3: Condition: ThirdAzIsFullNode DependsOn: ExchangeNode1WaitCondition Metadata: AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref ExchangeRole AWS::CloudFormation::Init: Cleanup: commands: a-disable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Disable-CredSSP.ps1" waitAfterCompletion: '0' b-enable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Enable" waitAfterCompletion: '0' Finalize: commands: a-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever b-signal-success: command: powershell -Command "Write-AWSQuickStartStatus" Install: commands: a-install-ucma-runtime: command: powershell.exe -Command "C:\cfn\scripts\Install-UcmaRuntime.ps1 waitAfterCompletion: '0' b-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever c-install-exchange: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-ExchangeServer.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - ''' -ServerIndex 3''' - '''"' waitAfterCompletion: '0' Prep: commands: a-rename-computer: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Rename-Computer.ps1 -Restart -NewName ' - !Ref ExchangeNode3NetBIOSName - '''"' waitAfterCompletion: forever b-join-domain: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Join-Domain.ps1 -DomainName ' - !Ref DomainDNSName - ''' -ADAdminSecParam ''' - !Ref ExchangeAdminSecrets - '''"' waitAfterCompletion: forever c-install-windows-failover-clustering: command: powershell.exe -Command "C:\cfn\scripts\Install-WindowsFailoverClustering.ps1" waitAfterCompletion: '0' d-install-exchange-prerequisites: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-ExchPrerequisites.ps1 -ExchangeServerVersion ' - !Ref ExchangeServerVersion - '''"' waitAfterCompletion: forever e-enable-credssp: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Enable-CredSSP.ps1" waitAfterCompletion: '0' f-disable-uac: command: powershell.exe -ExecutionPolicy RemoteSigned -Command "C:\cfn\scripts\Configure-UAC.ps1 -status Disable" waitAfterCompletion: '0' g-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever h-initializedisks: command: !If - UseReFSDataVolumes - powershell.exe -command "C:\cfn\scripts\Initialize-Disks.ps1" -EnableReFSVolumes $true - powershell.exe -command "C:\cfn\scripts\Initialize-Disks.ps1" -EnableReFSVolumes $false waitAfterCompletion: '0' i-download-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-PreRequisites.ps1 -source ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' j-expand-exchange-kit: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Expand-Exchange.ps1 -ExchangeServerVersion ''' - !Ref ExchangeServerVersion - ''' -ExchangeDownloadLink ''' - !If - Exchange2016Selected - !Ref Exchange2016Source - !Ref Exchange2019Source - '''"' waitAfterCompletion: '0' k-download-ucmaruntime: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-PreRequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - UCMA - ALL - '''"' waitAfterCompletion: '0' l-download-visualcruntime: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2013x64 - '''"' waitAfterCompletion: '0' m-download-netframework: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' waitAfterCompletion: '0' n-install-visualcruntime: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-VisualCRuntime.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -VisualCRuntimeLink ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2013x64 - '''"' o-install-netframework: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-NetFramework.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -NetFrameworkDownloadLink ''' - !FindInMap - MediaLinksMapper - NetFramework - v48 - '''"' p-download-visualcruntime2012: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' q-install-visualcruntime2012: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-VisualCRuntime.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -VisualCRuntimeLink ''' - !FindInMap - MediaLinksMapper - VisualCRuntime - 2012x64 - '''"' r-download-urlrewrite: command: !Join - '' - - 'powershell.exe ' - '-ExecutionPolicy RemoteSigned ' - -Command " - ' C:\cfn\scripts\Download-Prerequisites.ps1 -source ''' - !FindInMap - MediaLinksMapper - UrlRewrite - v21 - '''"' s-install-urlrewrite: command: !Join - '' - - powershell.exe -Command "C:\cfn\scripts\Install-UrlRewrite.ps1 -DomainNetBIOSName ' - !Ref DomainNetBIOSName - ''' -DomainAdminUser ''' - !Ref DomainAdminUser - ''' -ExUserSecParam ''' - !Ref ExchangeAdminSecrets - ''' -UrlRewriteLink ''' - !FindInMap - MediaLinksMapper - UrlRewrite - v21 - '''"' z-reboot: command: powershell.exe -Command "C:\cfn\scripts\Restart-Computer.ps1" waitAfterCompletion: forever setup: commands: a-set-execution-policy: command: powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Force" waitAfterCompletion: '0' b-unpack-quickstart-module: command: powershell.exe -Command C:\cfn\scripts\Unzip-Archive.ps1 -Source C:\cfn\modules\AWSQuickStart.zip -Destination C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ waitAfterCompletion: '0' c-init-quickstart-module: command: !Join - '' - - powershell.exe -Command " - New-AWSQuickStartWaitHandle -Handle ' - !Ref ExchangeNode3WaitHandle - '''"' waitAfterCompletion: '0' files: C:\cfn\scripts\Unzip-Archive.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Unzip-Archive.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\modules\AWSQuickStart.zip: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/modules/AWSQuickStart.zip - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Rename-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Rename-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Restart-Computer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Restart-Computer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Join-Domain.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Join-Domain.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Enable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Enable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Disable-CredSSP.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-utilities/scripts/Disable-CredSSP.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchPrerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchPrerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Expand-Exchange.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Expand-Exchange.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-WindowsFailoverClustering.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-WindowsFailoverClustering.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-UcmaRuntime.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-UcmaRuntime.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchangeOrg.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchangeOrg.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Install-ExchangeServer.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-ExchangeServer.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds c:\cfn\scripts\Configure-UAC.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Configure-UAC.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Download-Prerequisites.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Download-Prerequisites.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-VisualCRuntime.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-VisualCRuntime.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-NetFramework.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-NetFramework.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Initialize-Disks.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Initialize-Disks.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-UrlRewrite.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-UrlRewrite.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds C:\cfn\scripts\Install-SecurityUpdates.ps1: source: !Sub - https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}scripts/Install-SecurityUpdates.ps1 - S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName authentication: S3AccessCreds configSets: config: - setup - Prep - Install - Cleanup - Finalize Properties: BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp3 - DeviceName: /dev/xvdca VirtualName: ephemeral0 EbsOptimized: true ImageId: !If - Exchange2016Selected - !Ref WS2016FULLBASE - !Ref WS2022FULLBASE IamInstanceProfile: !Ref ExchangeProfile InstanceType: !Ref ExchangeNodeInstanceType KeyName: !Ref KeyPairName NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' GroupSet: - !Ref DomainMemberSGID - !Ref ExchangeSecurityGroup - !Ref EXCHClientSecurityGroup PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref ExchangeNode3PrivateIP1 - Primary: false PrivateIpAddress: !Ref ExchangeNode3PrivateIP2 SubnetId: !Ref PrivateSubnet3ID Tags: - Key: Name Value: !Ref ExchangeNode3NetBIOSName - Key: Backup Value: !If [EnableBackups, 'yes', 'no'] Tenancy: default UserData: !Base64 Fn::Join: - '' - - ' Type: AWS::EC2::Instance loadBalancer: Condition: DeployLoadBalancer Type: AWS::ElasticLoadBalancingV2::LoadBalancer DependsOn: - ExchangeNode1WaitCondition - ExchangeNode2WaitCondition Properties: Scheme: internal Subnets: !If - ThirdAzIsFullNode - - !Ref PrivateSubnet1ID - !Ref PrivateSubnet2ID - !Ref PrivateSubnet3ID - - !Ref PrivateSubnet1ID - !Ref PrivateSubnet2ID Type: network TargetGroup: Condition: DeployLoadBalancer DependsOn: - loadBalancer Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 30 HealthCheckTimeoutSeconds: 10 HealthyThresholdCount: 3 HealthCheckProtocol: TCP HealthCheckPort: '443' Name: ExchangeNodes Port: 443 Protocol: TLS TargetGroupAttributes: - Key: deregistration_delay.timeout_seconds Value: '20' Targets: !If - ThirdAzIsFullNode - - Id: !Ref ExchangeNode1 Port: '443' - Id: !Ref ExchangeNode2 Port: '443' - Id: !Ref ExchangeNode3 Port: '443' - - Id: !Ref ExchangeNode1 Port: '443' - Id: !Ref ExchangeNode2 Port: '443' UnhealthyThresholdCount: 3 VpcId: !Ref VPCID Listener: Condition: DeployLoadBalancer Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref TargetGroup LoadBalancerArn: !Ref loadBalancer Port: 443 Protocol: TLS Certificates: - CertificateArn: !Ref CertificateArn SslPolicy: ELBSecurityPolicy-2016-08 ExchangeNode1Volume1: Properties: AvailabilityZone: !GetAtt ExchangeNode1.AvailabilityZone Iops: !If - VolIsgp3 - !Ref VolumeIops - !Ref AWS::NoValue Encrypted: !If - UseEncryptedDataVolumes - !Ref EncryptDataVolumes - !Ref AWS::NoValue KmsKeyId: !If - UseEncryptedDataVolumes - !If - EncryptionKmsKeySelected - !Ref EncryptionKmsKey - !Ref AWS::NoValue - !Ref AWS::NoValue Size: !Ref VolumeSize VolumeType: !Ref VolumeType Type: AWS::EC2::Volume Metadata: cfn-lint: config: ignore_checks: - EBSVolumeEncryption ExchangeNode1Volume2: Properties: AvailabilityZone: !GetAtt ExchangeNode1.AvailabilityZone Encrypted: !If - UseEncryptedDataVolumes - !Ref EncryptDataVolumes - !Ref AWS::NoValue KmsKeyId: !If - UseEncryptedDataVolumes - !If - EncryptionKmsKeySelected - !Ref EncryptionKmsKey - !Ref AWS::NoValue - !Ref AWS::NoValue Iops: !If - VolIsgp3 - !Ref VolumeIops - !Ref AWS::NoValue Size: !Ref VolumeSize VolumeType: !Ref VolumeType Type: AWS::EC2::Volume Metadata: cfn-lint: config: ignore_checks: - EBSVolumeEncryption ExchangeNode2Volume1: Properties: AvailabilityZone: !GetAtt ExchangeNode2.AvailabilityZone Encrypted: !If - UseEncryptedDataVolumes - !Ref EncryptDataVolumes - !Ref AWS::NoValue KmsKeyId: !If - UseEncryptedDataVolumes - !If - EncryptionKmsKeySelected - !Ref EncryptionKmsKey - !Ref AWS::NoValue - !Ref AWS::NoValue Iops: !If - VolIsgp3 - !Ref VolumeIops - !Ref AWS::NoValue Size: !Ref VolumeSize VolumeType: !Ref VolumeType Type: AWS::EC2::Volume Metadata: cfn-lint: config: ignore_checks: - EBSVolumeEncryption ExchangeNode2Volume2: Properties: AvailabilityZone: !GetAtt ExchangeNode2.AvailabilityZone Encrypted: !If - UseEncryptedDataVolumes - !Ref EncryptDataVolumes - !Ref AWS::NoValue KmsKeyId: !If - UseEncryptedDataVolumes - !If - EncryptionKmsKeySelected - !Ref EncryptionKmsKey - !Ref AWS::NoValue - !Ref AWS::NoValue Iops: !If - VolIsgp3 - !Ref VolumeIops - !Ref AWS::NoValue Size: !Ref VolumeSize VolumeType: !Ref VolumeType Type: AWS::EC2::Volume Metadata: cfn-lint: config: ignore_checks: - EBSVolumeEncryption ExchangeNode3Volume1: Condition: ThirdAzIsFullNode Properties: AvailabilityZone: !GetAtt ExchangeNode3.AvailabilityZone Encrypted: !If - UseEncryptedDataVolumes - !Ref EncryptDataVolumes - !Ref AWS::NoValue KmsKeyId: !If - UseEncryptedDataVolumes - !If - EncryptionKmsKeySelected - !Ref EncryptionKmsKey - !Ref AWS::NoValue - !Ref AWS::NoValue Iops: !If - VolIsgp3 - !Ref VolumeIops - !Ref AWS::NoValue Size: !Ref VolumeSize VolumeType: !Ref VolumeType Type: AWS::EC2::Volume Metadata: cfn-lint: config: ignore_checks: - EBSVolumeEncryption ExchangeNode3Volume2: Condition: ThirdAzIsFullNode Properties: AvailabilityZone: !GetAtt ExchangeNode3.AvailabilityZone Encrypted: !If - UseEncryptedDataVolumes - !Ref EncryptDataVolumes - !Ref AWS::NoValue KmsKeyId: !If - UseEncryptedDataVolumes - !If - EncryptionKmsKeySelected - !Ref EncryptionKmsKey - !Ref AWS::NoValue - !Ref AWS::NoValue Iops: !If - VolIsgp3 - !Ref VolumeIops - !Ref AWS::NoValue Size: !Ref VolumeSize VolumeType: !Ref VolumeType Type: AWS::EC2::Volume Metadata: cfn-lint: config: ignore_checks: - EBSVolumeEncryption ExchangeNode1Volume1Attachment: Properties: Device: /dev/xvdf InstanceId: !Ref ExchangeNode1 VolumeId: !Ref ExchangeNode1Volume1 Type: AWS::EC2::VolumeAttachment ExchangeNode1Volume2Attachment: Properties: Device: /dev/xvdg InstanceId: !Ref ExchangeNode1 VolumeId: !Ref ExchangeNode1Volume2 Type: AWS::EC2::VolumeAttachment ExchangeNode2Volume1Attachment: Properties: Device: /dev/xvdf InstanceId: !Ref ExchangeNode2 VolumeId: !Ref ExchangeNode2Volume1 Type: AWS::EC2::VolumeAttachment ExchangeNode2Volume2Attachment: Properties: Device: /dev/xvdg InstanceId: !Ref ExchangeNode2 VolumeId: !Ref ExchangeNode2Volume2 Type: AWS::EC2::VolumeAttachment ExchangeNode3Volume1Attachment: Condition: ThirdAzIsFullNode Properties: Device: /dev/xvdf InstanceId: !Ref ExchangeNode3 VolumeId: !Ref ExchangeNode3Volume1 Type: AWS::EC2::VolumeAttachment ExchangeNode3Volume2Attachment: Condition: ThirdAzIsFullNode Properties: Device: /dev/xvdg InstanceId: !Ref ExchangeNode3 VolumeId: !Ref ExchangeNode3Volume2 Type: AWS::EC2::VolumeAttachment ExchangeSecurityGroup: Properties: GroupDescription: Enable all traffic between Exchange nodes VpcId: !Ref VPCID Type: AWS::EC2::SecurityGroup ExchangeSecurityGroupIngressAllTraffic: Properties: Description: All traffic allowed between Exchange nodes GroupId: !Ref ExchangeSecurityGroup IpProtocol: '-1' SourceSecurityGroupId: !Ref ExchangeSecurityGroup Type: AWS::EC2::SecurityGroupIngress BackupEncryptionKmsKey: Type: AWS::KMS::Key Metadata: cfn-lint: config: ignore_checks: - EIAMPolicyActionWildcard # The 'Principal' statement effectively narrows the scope of the key policy Condition: EnableBackups Properties: Description: "Encryption key Exchange backups" EnableKeyRotation: True Enabled: True KeyPolicy: Version: "2012-10-17" Statement: - Effect: Allow Principal: "AWS": !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:root" Action: - kms:* Resource: "*" ExchangeBackupVault: Type: "AWS::Backup::BackupVault" Condition: EnableBackups Properties: BackupVaultName: "exchange-backup-vault" EncryptionKeyArn: !GetAtt BackupEncryptionKmsKey.Arn ExchangeBackupPlan: Type: "AWS::Backup::BackupPlan" Condition: EnableBackups Properties: BackupPlan: BackupPlanName: "BackupPlanWithThinBackups" AdvancedBackupSettings: - ResourceType: 'EC2' BackupOptions: WindowsVSS: 'enabled' BackupPlanRule: - RuleName: "DailyBackups" TargetBackupVault: !Ref ExchangeBackupVault ScheduleExpression: "cron(0 5 ? * * *)" Lifecycle: DeleteAfterDays: 7 - RuleName: "WeeklyBackups" TargetBackupVault: !Ref ExchangeBackupVault ScheduleExpression: "cron(0 5 ? * 1 *)" Lifecycle: DeleteAfterDays: 28 - RuleName: "MonthlyBackups" TargetBackupVault: !Ref ExchangeBackupVault ScheduleExpression: "cron(0 5 1 * ? *)" Lifecycle: DeleteAfterDays: 90 ExchangeBackupSelection: Type: "AWS::Backup::BackupSelection" Condition: EnableBackups Properties: BackupSelection: SelectionName: "TagBasedBackupSelection" IamRoleArn: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/service-role/AWSBackupDefaultServiceRole" ListOfTags: - ConditionType: "STRINGEQUALS" ConditionKey: "Backup" ConditionValue: "yes" BackupPlanId: !Ref ExchangeBackupPlan ExchangeResourceGroup: Condition: AppInsightsEnabled Type: AWS::ResourceGroups::Group Properties: Name: !If [UsingDefaultAppName, !Sub "ApplicationInsights-${AWS::StackName}", !Ref AppInsightsApplicationName] ResourceQuery: Query: TagFilters: - Key: 'aws:cloudformation:stack-name' Values: - !Sub "${AWS::StackName}" Type: 'TAG_FILTERS_1_0' ApplicationInsightsExchange: Condition: AppInsightsEnabled Type: AWS::ApplicationInsights::Application Properties: ResourceGroupName: !Ref 'ExchangeResourceGroup' AutoConfigurationEnabled: true DependsOn: ExchangeResourceGroup Outputs: DomainAdmin: Description: Domain administrator account Value: !Join - '' - - !Ref DomainNetBIOSName - \ - !Ref DomainAdminUser LocalAdmin: Description: Please retrieve Administrator password of the instance Value: Administrator ExchangeNode1NetBIOSName: Description: NetBIOS name of the 1st Exchange Node Value: !Ref ExchangeNode1NetBIOSName ExchangeNode2NetBIOSName: Description: NetBIOS name of the 2nd Exchange Node Value: !Ref ExchangeNode2NetBIOSName ExchangeNode3NetBIOSName: Condition: ThirdAzIsFullNode Description: NetBIOS name of the 3rd Exchange Node Value: !Ref ExchangeNode3NetBIOSName