--- AWSTemplateFormatVersion: '2010-09-09' Description: This template deploys a two- or three-node Windows Server Failover Cluster (WSFC) with SQL Server and SIOS DataKeeper replication software. This template is intended to be installed into an existing VPC that was built using the Active Directory Domain Services on AWS Quick Start. **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-1qup6ralg) Metadata: cfn-lint: config: ignore_checks: - E9101 - E1019 - W9006 QuickStartDocumentation: EntrypointName: Parameters for deploying into an existing VPC Order: "2" AWSAMIRegionMap: Filters: SDKCEWIN2019: name: SIOS DataKeeper v8* on 2019* owner-alias: aws-marketplace product-code.type: marketplace product-code: 4751lqgr72zqz6fwj12p82x8s SDKCEWIN2019BYOL: name: SIOS DataKeeper v8* on 2019 BYOL* owner-alias: aws-marketplace product-code.type: marketplace product-code: 4em0o0s00hf8yye81sq8d619d SDKCEWIN2016: name: SIOS DataKeeper v8* on 2016* owner-alias: aws-marketplace product-code.type: marketplace product-code: 39ui2evyq6bmfxwhpwyci6l06 SDKCEWIN2016BYOL: name: SIOS DataKeeper v8* on 2016 BYOL* owner-alias: aws-marketplace product-code.type: marketplace product-code: 959g9sxo7jo9axg7au8fjxvmi SDKCEWIN2012R2: name: SIOS DataKeeper v8* on 2012R2* owner-alias: aws-marketplace product-code.type: marketplace product-code: dvw0k1cslwup93kxyf85trjxm SDKCEWIN2012R2BYOL: name: SIOS DataKeeper v8* on 2012R2 BYOL* owner-alias: aws-marketplace product-code.type: marketplace product-code: 14oj75sfcidvzwqizi8lzs7c2 AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Network configuration Parameters: - ThirdAZ - VPCID - VPCCIDR - PrivateSubnet1ID - PrivateSubnet1CIDR - PrivateSubnet2ID - PrivateSubnet2CIDR - PrivateSubnet3ID - PrivateSubnet3CIDR - Label: default: Amazon EC2 configuration Parameters: - KeyPairName - Label: default: Active Directory configuration Parameters: - ActiveDirectoryId - DomainDNSName - DomainNetBIOSName - DomainAdminPassword - ADServer1PrivateIP - ADServer2PrivateIP - DomainMemberSGID - Label: default: (Optional) Self-managed Active Directory configuration Parameters: - DomainAdminUser - ADServer1NetBIOSName - ADServer2NetBIOSName - Label: default: Replication configuration Parameters: - AMIType - SIOSLicenseKeyFtpURL - SQLServerVersion - SQLServiceAccount - SQLServiceAccountPassword - Volume1Size - Volume1Type - Volume1Iops - Label: default: Failover-cluster configuration Parameters: - OSVersion - ClusterName - WSFCNode1InstanceType - WSFCNode1NetBIOSName - WSFCNode1PrivateIP1 - WSFCNode1PrivateIP2 - WSFCNode1PrivateIP3 - WSFCNode2InstanceType - WSFCNode2NetBIOSName - WSFCNode2PrivateIP1 - WSFCNode2PrivateIP2 - WSFCNode2PrivateIP3 - WSFCNode3InstanceType - WSFCNode3NetBIOSName - WSFCNode3PrivateIP1 - WSFCNode3PrivateIP2 - WSFCNode3PrivateIP3 - WSFCWitnessNetBIOSName - WSFCWitnessInstanceType - WSFCWitnessAmiId - Label: default: AWS Quick Start configuration Parameters: - QSS3BucketName - QSS3BucketRegion - QSS3KeyPrefix ParameterLabels: ActiveDirectoryId: default: AWS Managed Microsoft AD ID ADServer1NetBIOSName: default: Domain controller 1 NetBIOS name ADServer1PrivateIP: default: Private IP address of DNS Server in private subnet 1 ADServer2NetBIOSName: default: Domain controller 2 NetBIOS name ADServer2PrivateIP: default: Private IP address of DNS Server in private subnet 2 AMIType: default: AMI type ClusterName: default: Cluster name DomainAdminPassword: default: Domain administrator password DomainAdminUser: default: Domain administrator user name DomainDNSName: default: Domain DNS name DomainMemberSGID: default: Security group ID for AD domain members DomainNetBIOSName: default: Domain NetBIOS name KeyPairName: default: Key-pair name OSVersion: default: OS version for cluster nodes 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 QSS3BucketName: default: Quick Start S3 bucket name QSS3BucketRegion: default: Quick Start S3 bucket Region QSS3KeyPrefix: default: Quick Start S3 key prefix SIOSLicenseKeyFtpURL: default: SIOS DataKeeper license key FTP URL SQLServerVersion: default: SQL Server version SQLServiceAccount: default: Service account name SQLServiceAccountPassword: default: Service account password ThirdAZ: default: Third Availability Zone Volume1Iops: default: Data volume IOPS Volume1Size: default: Data volume size Volume1Type: default: Data volume type VPCID: default: SQL cluster VPC VPCCIDR: default: SQL cluster VPC CIDR WSFCNode1InstanceType: default: WSFC node 1 instance type WSFCNode1NetBIOSName: default: WSFC node 1 NetBIOS name WSFCNode1PrivateIP1: default: WSFC node 1 private IP address 1 WSFCNode1PrivateIP2: default: WSFC node 1 private IP address 2 WSFCNode1PrivateIP3: default: WSFC node 1 private IP address 3 WSFCNode2InstanceType: default: WSFC node 2 instance type WSFCNode2NetBIOSName: default: WSFC node 2 NetBIOS name WSFCNode2PrivateIP1: default: WSFC node 2 private IP address 1 WSFCNode2PrivateIP2: default: WSFC node 2 private IP address 2 WSFCNode2PrivateIP3: default: WSFC node 2 private IP address 3 WSFCNode3InstanceType: default: WSFC node 3 instance type WSFCNode3NetBIOSName: default: WSFC node 3 NetBIOS name WSFCNode3PrivateIP1: default: WSFC node 3 private IP address 1 WSFCNode3PrivateIP2: default: WSFC node 3 private IP address 2 WSFCNode3PrivateIP3: default: WSFC node 3 private IP address 3 WSFCWitnessNetBIOSName: default: WSFC witness NetBIOS name WSFCWitnessInstanceType: default: WSFC witness instance type WSFCWitnessAmiId: default: WSFC witness AMI ID Parameters: ActiveDirectoryId: Description: Enter the ID of the AWS Managed Microsoft AD. If you are using self-managed Active Directory, keep this blank. Default: '' Type: String ADServer1NetBIOSName: AllowedPattern: '[a-zA-Z0-9]+' Default: DC1 Description: 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: Fixed private IP address for the first Active Directory server, located in Availability Zone 1. Type: String ADServer2NetBIOSName: AllowedPattern: '[a-zA-Z0-9]+' Default: DC2 Description: NetBIOS name of the second Active Directory server (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String ADServer2PrivateIP: 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.10 Description: Fixed private IP address for the second Active Directory server, located in Availability Zone 2. Type: String AMIType: AllowedValues: - PAYG - BYOL Default: PAYG Description: AMI type for the SIOS DataKeeper license. Type: String ClusterName: AllowedPattern: '[a-zA-Z0-9]+' Default: WSFCCluster1 Description: NetBIOS name of the WSFC cluster. MaxLength: '15' MinLength: '1' Type: String DomainAdminPassword: AllowedPattern: (?=^.{6,255}$)((?=.*\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: Password for the domain administrator 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: admin Description: User name for the domain administrator account. This is separate from the default administrator account. MaxLength: '25' MinLength: '5' Type: String DomainDNSName: AllowedPattern: '[a-zA-Z0-9]+\..+' Default: datakeeper.local Description: Fully qualified domain name (FQDN) of the forest root domain (e.g., example.com). MaxLength: '25' MinLength: '3' Type: String DomainMemberSGID: Description: ID of the domain member security group (e.g., sg-7f16e910). Type: AWS::EC2::SecurityGroup::Id DomainNetBIOSName: AllowedPattern: '[a-zA-Z0-9]+' Default: DATAKEEPER Description: NetBIOS name of the domain for users of earlier versions of Windows (up to 15 characters). MaxLength: '15' MinLength: '1' Type: String KeyPairName: Description: Public-private key pairs allow you to securely connect to your instance after it launches. Type: AWS::EC2::KeyPair::KeyName OSVersion: AllowedValues: - WS2012R2 - WS2016 - WS2019 Default: WS2012R2 Description: Version of Windows Server OS for cluster nodes. Type: String 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])(\/(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/19 Description: CIDR block for private subnet 1, located in Availability Zone 1. Type: String PrivateSubnet1ID: Description: ID of private subnet 1 in Availability Zone 1 (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])(\/(1[6-9]|2[0-8]))$ ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28. Default: 10.0.32.0/19 Description: CIDR block for private subnet 2, located in Availability Zone 2. Type: String PrivateSubnet2ID: Description: ID of private subnet 2 in Availability Zone 2 (e.g., subnet-a0246dcd). Type: AWS::EC2::Subnet::Id 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])(\/(1[6-9]|2[0-8]))$ ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28. Default: 10.0.64.0/19 Description: (Optional) CIDR block for private subnet 3, located in Availability Zone 3. Type: String PrivateSubnet3ID: Description: (Optional) ID of private subnet 3 in Availability Zone 3 (e.g., subnet-a0246dcd). Default: '' Type: String QSS3BucketName: AllowedPattern: ^[0-9a-z]+([0-9a-z-\.]*[0-9a-z])*$ ConstraintDescription: >- The S3 bucket name can include numbers, lowercase letters, and hyphens (-), but it cannot start or end with a hyphen. Default: aws-quickstart Description: >- Name of the S3 bucket for your copy of the deployment assets. Keep the default name unless you are customizing the template. Changing the name updates code references to point to a new location. MinLength: 3 MaxLength: 63 Type: String QSS3BucketRegion: Default: 'us-east-1' Description: >- AWS Region where the S3 bucket (QSS3BucketName) is hosted. Keep the default Region unless you are customizing the template. Changing the Region updates code references to point to a new location. When using your own bucket, specify the Region. Type: String QSS3KeyPrefix: AllowedPattern: ^([0-9a-zA-Z!-_\.\*'\(\)/]+/)*$ ConstraintDescription: >- The S3 key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), underscores (_), periods (.), asterisks (*), single quotes ('), open parenthesis ((), close parenthesis ()), and forward slashes (/). End the prefix with a forward slash. Default: quickstart-sios-datakeeper/ Description: >- S3 key prefix that is used to simulate a folder for your copy of the deployment assets. Keep the default prefix unless you are customizing the template. Changing the prefix updates code references to point to a new location. Type: String SIOSLicenseKeyFtpURL: Default: 'override' Description: URL to obtain a license key for SIOS DataKeeper software. Type: String SQLServerVersion: AllowedValues: - None - '2016' - '2017' - '2019' Default: '2017' Description: Version of MS SQL Server to install. Choose "None" if you don't want to install SQL Server. Type: String SQLServiceAccount: AllowedPattern: '[a-zA-Z0-9]*' Default: sqlsa Description: User name for the SQL Server service account. This account is a domain user. MaxLength: '25' MinLength: '5' Type: String SQLServiceAccountPassword: AllowedPattern: (?=^(?![\s\S]))|(?=^.{6,255}$)((?=.*\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]))^.* Default: '' Description: Password for the SQL Server account. Must be at least 8 characters containing letters, numbers, and symbols. Keep blank if you don't want to install SQL Server. MaxLength: '32' MinLength: '0' NoEcho: 'true' Type: String ThirdAZ: AllowedValues: - none - witness - full Default: none Description: Choose "full" or "witness" to enable a deployment with three Availability Zones. The third Availability Zone can be used for the witness, or it can be a full WSFC cluster node. Type: String VPCID: Description: ID of the VPC (e.g., vpc-0343606e). Type: AWS::EC2::VPC::Id VPCCIDR: 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: CIDR block for the VPC. Type: String Volume1Iops: Default: 1000 Description: IOPS for the SQL data drive. (Used only when data volume type is io1.) MaxValue: 20000 MinValue: 100 Type: Number Volume1Size: Default: 100 Description: Volume size (in GiB) for the SQL data drive. MaxValue: 16000 MinValue: 100 Type: Number Volume1Type: AllowedValues: - gp2 - io1 Default: gp2 Description: Volume type for the SQL data drive. Type: String WSFCWitnessAmiId: Type: 'AWS::SSM::Parameter::Value' Default: '/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-Base' Description: AMI ID for a WSFC file-share-witness node. AllowedValues: - /aws/service/ami-windows-latest/Windows_Server-2012-R2_RTM-English-64Bit-Base - /aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base - /aws/service/ami-windows-latest/Windows_Server-2019-English-Full-Base WSFCNode1InstanceType: AllowedValues: - m3.xlarge - m3.2xlarge - c3.xlarge - c3.2xlarge - c3.4xlarge - g2.2xlarge - r3.xlarge - r3.2xlarge - r3.4xlarge - d2.xlarge - d2.2xlarge - d2.4xlarge - d2.8xlarge - i2.xlarge - i2.2xlarge - i2.4xlarge - h1.2xlarge - h1.4xlarge - h1.8xlarge - h1.16xlarge - i3.large - i3.xlarge - i3.2xlarge - i3.4xlarge - i3.8xlarge - i3.16xlarge - x1.16xlarge - x1.32xlarge - x1e.xlarge - x1e.2xlarge - x1e.4xlarge - x1e.8xlarge - x1e.16xlarge - x1e.32xlarge ConstraintDescription: Only EBS-optimized instance types are allowed. Default: i3.xlarge Description: Amazon EC2 instance type for the first WSFC node. If you're concerned about performance, SIOS recommends r3.xlarge or larger. Type: String WSFCNode1NetBIOSName: AllowedPattern: '[a-zA-Z0-9]+' Default: WSFCNode1 Description: NetBIOS name of the first WSFC Node (up to 15 characters). MaxLength: 15 MinLength: 1 Type: String WSFCNode1PrivateIP1: 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: Primary private IP address for the first WSFC node, located in Availability Zone 1. Type: String WSFCNode1PrivateIP2: 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: Secondary private IP address for WSFC cluster on the first WSFC node. Type: String WSFCNode1PrivateIP3: 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.102 Description: Third private IP address for SQL Server network name on the first WSFC node. Type: String WSFCNode2InstanceType: AllowedValues: - m3.xlarge - m3.2xlarge - c3.xlarge - c3.2xlarge - c3.4xlarge - g2.2xlarge - r3.xlarge - r3.2xlarge - r3.4xlarge - d2.xlarge - d2.2xlarge - d2.4xlarge - d2.8xlarge - i2.xlarge - i2.2xlarge - i2.4xlarge - h1.2xlarge - h1.4xlarge - h1.8xlarge - h1.16xlarge - i3.large - i3.xlarge - i3.2xlarge - i3.4xlarge - i3.8xlarge - i3.16xlarge - x1.16xlarge - x1.32xlarge - x1e.xlarge - x1e.2xlarge - x1e.4xlarge - x1e.8xlarge - x1e.16xlarge - x1e.32xlarge ConstraintDescription: Only EBS-optimized instance types are allowed. Default: i3.xlarge Description: Amazon EC2 instance type for the second WSFC node. If you're concerned about performance, SIOS recommends r3.xlarge or larger. Type: String WSFCNode2NetBIOSName: AllowedPattern: '[a-zA-Z0-9]+' Default: WSFCNode2 Description: NetBIOS name of the second WSFC node (up to 15 characters). MaxLength: 15 MinLength: 1 Type: String WSFCNode2PrivateIP1: 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: Primary private IP address for the second WSFC node, located in Availability Zone 2. Type: String WSFCNode2PrivateIP2: 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: Secondary private IP address for the WSFC cluster on the second WSFC node. Type: String WSFCNode2PrivateIP3: 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.102 Description: Third private IP address for the SQL Server network name on the second WSFC node. Type: String WSFCNode3InstanceType: AllowedValues: - m3.xlarge - m3.2xlarge - c3.xlarge - c3.2xlarge - c3.4xlarge - g2.2xlarge - r3.xlarge - r3.2xlarge - r3.4xlarge - d2.xlarge - d2.2xlarge - d2.4xlarge - d2.8xlarge - i2.xlarge - i2.2xlarge - i2.4xlarge - h1.2xlarge - h1.4xlarge - h1.8xlarge - h1.16xlarge - i3.large - i3.xlarge - i3.2xlarge - i3.4xlarge - i3.8xlarge - i3.16xlarge - x1.16xlarge - x1.32xlarge - x1e.xlarge - x1e.2xlarge - x1e.4xlarge - x1e.8xlarge - x1e.16xlarge - x1e.32xlarge Default: i3.xlarge Description: (Optional) Amazon EC2 instance type for the third WSFC node. Full cluster nodes must be EBS-optimized types, but a file-share-witness host can be any available instance type. If you're concerned about performance, SIOS recommends r3.xlarge or larger. Type: String WSFCNode3NetBIOSName: AllowedPattern: '[a-zA-Z0-9]+' Default: WSFCNode3 Description: (Optional when ThirdAZ is set to "full") NetBIOS name of the second WSFC node (up to 15 characters). MaxLength: 15 MinLength: 1 Type: String WSFCNode3PrivateIP1: 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 when ThirdAZ is set to "witness" or "full") Primary private IP address for the second WSFC node, located in Availability Zone 2. Type: String WSFCNode3PrivateIP2: 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 when ThirdAZ is set to "full") Secondary private IP address for the WSFC cluster on the third WSFC node. Type: String WSFCNode3PrivateIP3: 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.102 Description: (Optional when ThirdAZ is set to "full") Third private IP address for the SQL Server network name on the third WSFC node. Type: String WSFCWitnessNetBIOSName: AllowedPattern: '[a-zA-Z0-9]+' Default: WSFCWitness Description: (Optional when ThirdAZ is set to "witness") NetBIOS name of the second WSFC node (up to 15 characters). MaxLength: 15 MinLength: 1 Type: String WSFCWitnessInstanceType: AllowedValues: - t2.micro - t2.small - t2.medium - t2.large - t3.micro - t3.small - t3.medium - t3.large - m4.large - m5.large Default: t3.micro Description: Amazon EC2 instance type for a WSFC file-share-witness node. Type: String Conditions: Vol1IsIo1: !Equals [!Ref Volume1Type, 'io1'] UsingSelfManagedAD: !Equals [!Ref ActiveDirectoryId, ''] UsingAWSManagedAD: !Not [!Equals [!Ref ActiveDirectoryId, '']] ByolAmiCondition: !Not [!Equals [!Ref AMIType, 'PAYG']] TwoNodeDeployment: !Equals [!Ref ThirdAZ, 'none'] ThirdAzIsWitness: !Equals [!Ref ThirdAZ, 'witness'] ThirdAzIsFullNode: !Equals [!Ref ThirdAZ, 'full'] NeedsWitnessNode: !And - !Condition UsingSelfManagedAD - !Condition ThirdAzIsWitness NeedsFSxWitness: !And - !Condition UsingAWSManagedAD - !Condition ThirdAzIsWitness UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] Rules: SubnetsInVPC: Assertions: - Assert: !EachMemberIn - !ValueOfAll - AWS::EC2::Subnet::Id - VpcId - !RefAll AWS::EC2::VPC::Id AssertDescription: All subnets must be in the VPC Mappings: BYOLNameMap: WS2012R2: Code: SDKCEWIN2012R2BYOL WS2016: Code: SDKCEWIN2016BYOL WS2019: Code: SDKCEWIN2019BYOL PAYGNameMap: WS2012R2: Code: SDKCEWIN2012R2 WS2016: Code: SDKCEWIN2016 WS2019: Code: SDKCEWIN2019 AWSAMIRegionMap: ap-northeast-2: SDKCEWIN2012R2: ami-06900e8a563f173ae SDKCEWIN2012R2BYOL: ami-07ce0495ca8a3a2b9 SDKCEWIN2016: ami-09d66ac24fe9ae06d SDKCEWIN2016BYOL: ami-0cb18d1a987eacd0f SDKCEWIN2019: ami-0bdf04daeaced7d57 SDKCEWIN2019BYOL: ami-03b6d4dc60ba61f43 ap-south-1: SDKCEWIN2012R2: ami-0f6298649f96ca2b1 SDKCEWIN2012R2BYOL: ami-0aec17e30a2814fa3 SDKCEWIN2016: ami-07702bf89e2c277ee SDKCEWIN2016BYOL: ami-0c97091964cbb9912 SDKCEWIN2019: ami-002c56d9c7efbccb2 SDKCEWIN2019BYOL: ami-0c4c95030de2702ae ap-southeast-1: SDKCEWIN2012R2: ami-07f8cf83eedffa066 SDKCEWIN2012R2BYOL: ami-07761ad9642729485 SDKCEWIN2016: ami-073290dd086e19e38 SDKCEWIN2016BYOL: ami-093fd4ca392438bde SDKCEWIN2019: ami-0756d1980fbb25249 SDKCEWIN2019BYOL: ami-0f434840a8b2e86d7 ap-southeast-2: SDKCEWIN2012R2: ami-029edcdc554bc1eea SDKCEWIN2012R2BYOL: ami-0ffcf4097909911e6 SDKCEWIN2016: ami-0d43260c6e07fcd9e SDKCEWIN2016BYOL: ami-0e804016940ba694a SDKCEWIN2019: ami-0832d840e73dee727 SDKCEWIN2019BYOL: ami-007481c8709f1cd1e ca-central-1: SDKCEWIN2012R2: ami-0e762aff7b64efd27 SDKCEWIN2012R2BYOL: ami-0027aba694a03fbaa SDKCEWIN2016: ami-075aebccca2baaf7b SDKCEWIN2016BYOL: ami-0206615596a1c3589 SDKCEWIN2019: ami-07700004e4e805136 SDKCEWIN2019BYOL: ami-03f89be8e9a9e91dd eu-central-1: SDKCEWIN2012R2: ami-095989f6ef8efa312 SDKCEWIN2012R2BYOL: ami-0d37006563984e7bf SDKCEWIN2016: ami-055e8150cafb922d4 SDKCEWIN2016BYOL: ami-0ecd9eef3815ad3fe SDKCEWIN2019: ami-0f4644bb72be4b4a2 SDKCEWIN2019BYOL: ami-0d0c078fe8367bcd6 eu-north-1: SDKCEWIN2012R2: ami-0e63924f98985bfdf SDKCEWIN2012R2BYOL: ami-00dbfd4afed7c5ffb SDKCEWIN2016: ami-026815028ba218589 SDKCEWIN2016BYOL: ami-0d573706cf2c4079b SDKCEWIN2019: ami-0948238f399f133d1 SDKCEWIN2019BYOL: ami-0422792f027cebc1e eu-west-1: SDKCEWIN2012R2: ami-07a0598a32228f7d3 SDKCEWIN2012R2BYOL: ami-08b4724dab4f3ba38 SDKCEWIN2016: ami-04f08af03efba43e1 SDKCEWIN2016BYOL: ami-08f8f4fc16c161194 SDKCEWIN2019: ami-09915b4796a446b76 SDKCEWIN2019BYOL: ami-00c3c898c3d0611a4 eu-west-2: SDKCEWIN2012R2: ami-071f1c23c8195a786 SDKCEWIN2012R2BYOL: ami-00e36959ef7e0617d SDKCEWIN2016: ami-0ec21178fd7ce57e6 SDKCEWIN2016BYOL: ami-066d9c97fb36113ee SDKCEWIN2019: ami-022fcee66865ed51e SDKCEWIN2019BYOL: ami-0a960485c9815d0f8 eu-west-3: SDKCEWIN2012R2: ami-0fa9828deac779811 SDKCEWIN2012R2BYOL: ami-0e59a64d5721b2397 SDKCEWIN2016: ami-0fbf9807ba01f6ec7 SDKCEWIN2016BYOL: ami-046d11058b1619a8f SDKCEWIN2019: ami-0b4367819ceefddd0 SDKCEWIN2019BYOL: ami-0ae1e10f67257fb53 sa-east-1: SDKCEWIN2012R2: ami-05a6b3b2e94d8b9c7 SDKCEWIN2012R2BYOL: ami-0155a0cfa9a02f7da SDKCEWIN2016: ami-0f48dee3a3eb119da SDKCEWIN2016BYOL: ami-0fd87755991359e7a SDKCEWIN2019: ami-0c623e9d7f0889183 SDKCEWIN2019BYOL: ami-07e82a57374b8bd4b us-east-1: SDKCEWIN2012R2: ami-07f6aa3091bfeb928 SDKCEWIN2012R2BYOL: ami-0ebff275384135ed3 SDKCEWIN2016: ami-049e08b7f640e2735 SDKCEWIN2016BYOL: ami-0a9e50e0712dbca78 SDKCEWIN2019: ami-06081f4dcf2d87ee6 SDKCEWIN2019BYOL: ami-08026bf654cdddb63 us-east-2: SDKCEWIN2012R2: ami-00366254063505b43 SDKCEWIN2012R2BYOL: ami-044382e3b21475837 SDKCEWIN2016: ami-0f88a9b9f3cc3377a SDKCEWIN2016BYOL: ami-098c09d54b8e9c8ba SDKCEWIN2019: ami-0b9a3d410864c6ed9 SDKCEWIN2019BYOL: ami-0b6cffee167411bce us-west-1: SDKCEWIN2012R2: ami-02b9d7b282d04cc53 SDKCEWIN2012R2BYOL: ami-092ae131a6d5a33f8 SDKCEWIN2016: ami-05374d81f3ff41b49 SDKCEWIN2016BYOL: ami-04207612b15090934 SDKCEWIN2019: ami-0dfa49c85e8257650 SDKCEWIN2019BYOL: ami-0ce1c0b6b4e1d1e45 us-west-2: SDKCEWIN2012R2: ami-0c60961e199ac6d4e SDKCEWIN2012R2BYOL: ami-0ee18ff309384e3ad SDKCEWIN2016: ami-006e9dbbe8b9c9a1a SDKCEWIN2016BYOL: ami-0727dcc56f59d2d83 SDKCEWIN2019: ami-0013adaaa78c29378 SDKCEWIN2019BYOL: ami-0329158b32510f09b Resources: QuickStartLogs: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/Quick_Start/${AWS::StackName} RetentionInDays: 30 ADAdminSecrets: Type: AWS::SecretsManager::Secret Properties: Name: !Sub 'AWSQuickStart/${AWS::StackName}/ADAdminSecrets' Description: MS AD Credentials for Quick Start SecretString: !Sub '{ "username" : "${DomainAdminUser}", "password" : "${DomainAdminPassword}" }' SQLSecrets: Type: AWS::SecretsManager::Secret Properties: Name: !Sub 'AWSQuickStart/${AWS::StackName}/SQLSecrets' Description: MS SQL Credentials for Quick Start SecretString: !Sub '{ "username" : "${SQLServiceAccount}", "password" : "${SQLServiceAccountPassword}" }' SSMDocumentDKCE: Type: AWS::SSM::Document Properties: DocumentType: Automation Content: schemaVersion: '0.3' description: Deploy SIOS DKCE with SSM Automation assumeRole: '{{AutomationAssumeRole}}' parameters: AMIType: default: "PAYG" description: AMI type for SIOS license purposes. type: String ActiveDirectoryConfig: default: Managed description: Both refer to the quickstart-microsoft-activedirectory submodule. "Legacy" refers to scenario 1. "Managed" refers to scenario 3. type: String ActiveDirectoryId: default: '' description: AWS Managed Microsoft AD ID type: String AdminSecrets: description: "AWS Secrets Parameter Name that has Password and User name for a domain administrator." type: "String" ADServer1NetBIOSName: default: SIOSDC1 description: NetBIOS name of the first Active Directory server (up to 15 characters) type: String ADServer1PrivateIP: default: 10.0.0.10 description: Fixed private address for the first Active Directory server located in Availability Zone 1. type: String ADServer2NetBIOSName: default: SIOSDC2 description: NetBIOS name of the second Active Directory server (up to 15 characters) type: String ADServer2PrivateIP: default: 10.0.32.10 description: Fixed private IP address for the second Active Directory server located in Availability Zone 2. type: String ClusterName: default: WSFCCluster1 description: NetBIOS name of the WSFC cluster type: String DomainDNSName: default: datakeeper.local description: Fully qualified domain name (FQDN) e.g., example.com type: String DomainNetBIOSName: default: DATAKEEPER description: NetBIOS name of the domain (up to 15 characters) for users of earlier versions of Windows e.g. EXAMPLE. type: String FSxDNSName: default: '' description: Windows Remote PowerShell DNS name for Amazon FSx file share used with AWS Managed Microsoft AD deployment. type: String OSVersion: default: WS2012R2 description: Version of the Windows Server OS to use for cluster nodes. type: String PrivateSubnet1CIDR: default: 10.0.0.0/19 description: CIDR block for private subnet 1 located in Availability Zone 1. type: String PrivateSubnet2CIDR: default: 10.0.32.0/19 description: CIDR block for private subnet 2 located in Availability Zone 2. type: String PrivateSubnet3CIDR: default: 10.0.64.0/19 description: CIDR block for private subnet 2 located in Availability Zone 2. type: String SIOSLicenseKeyFtpURL: default: 'override' description: URL used to obtain license key for SIOS DataKeeper software. type: String SQLSecrets: description: "AWS Secrets Parameter Name that has Password and User namer for the SQL Service Account." type: "String" SQLServerVersion: default: '2017' description: Version of MS SQL Server to install. Select 'None' if SQL Server is not desired. type: String ThirdAZ: default: none description: "Purpose of third Availability Zone" type: "String" WSFCNode1NetBIOSName: default: WSFCNode1 description: NetBIOS name of the first WSFC node (up to 15 characters) type: String WSFCNode1PrivateIP1: default: 10.0.0.100 description: Primary private IP address for the first WSFC node located in Availability Zone 1. type: String WSFCNode1PrivateIP2: default: 10.0.0.101 description: Secondary private IP address for WSFC cluster on first WSFC node. type: String WSFCNode1PrivateIP3: default: 10.0.0.102 description: Third private IP address for SQL Server network name on first WSFC node. type: String WSFCNode2NetBIOSName: default: WSFCNode2 description: NetBIOS name of the second WSFC node (up to 15 characters). type: String WSFCNode2PrivateIP1: default: 10.0.32.100 description: Primary private IP address for the second WSFC Node located in Availability Zone 2 type: String WSFCNode2PrivateIP2: default: 10.0.32.101 description: Secondary private IP address for WSFC cluster on second WSFC node. type: String WSFCNode2PrivateIP3: default: 10.0.32.102 description: Third private IP address for SQL Server network name on second WSFC node. type: String WSFCNode3NetBIOSName: default: WSFCNode3 description: NetBIOS name of the third WSFC node (up to 15 characters) - WSFCNode3 or WSFCWitness. type: String WSFCNode3PrivateIP1: default: 10.0.64.100 description: Primary private IP address for the third WSFC Node located in Availability Zone 3. type: String WSFCNode3PrivateIP2: default: 10.0.64.101 description: Secondary private IP address for WSFC cluster on third WSFC node. type: String WSFCNode3PrivateIP3: default: 10.0.64.102 description: Third private IP address for SQL Server network name on third WSFC node. type: String WSFCNodeNames: default: ["WSFCNode1","WSFCNode2"] description: List of node names in use type: StringList QSS3BucketName: 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: 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: default: quickstart-microsoft-activedirectory/ 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 URLSuffix: description: AWS URL suffix type: String StackName: default: '' description: Stack Name Input for cfn resource signal type: String AutomationAssumeRole: default: '' description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf. type: String mainSteps: - name: wsfcnodesInstanceId maxAttempts: 999 action: aws:executeAwsApi onFailure: step:signalfailure inputs: Service: ec2 Api: DescribeInstances Filters: - Name: tag:Name Values: [ '{{WSFCNodeNames}}' ] - Name: tag:aws:cloudformation:stack-name Values: [ '{{StackName}}' ] - Name: instance-state-name Values: [ 'running' ] outputs: - Name: InstanceIds Selector: $.Reservations..Instances..InstanceId Type: StringList - name: wsfcnode1InstanceId action: aws:executeAwsApi onFailure: step:signalfailure inputs: Service: ec2 Api: DescribeInstances Filters: - Name: tag:Name Values: [ '{{WSFCNode1NetBIOSName}}' ] - Name: tag:aws:cloudformation:stack-name Values: [ '{{StackName}}' ] - Name: instance-state-name Values: [ 'running' ] outputs: - Name: InstanceId Selector: $.Reservations[0].Instances[0].InstanceId Type: String - name: wsfcnode2InstanceId action: aws:executeAwsApi onFailure: step:signalfailure inputs: Service: ec2 Api: DescribeInstances Filters: - Name: tag:Name Values: [ '{{WSFCNode2NetBIOSName}}' ] - Name: tag:aws:cloudformation:stack-name Values: [ '{{StackName}}' ] - Name: instance-state-name Values: [ 'running' ] outputs: - Name: InstanceId Selector: $.Reservations[0].Instances[0].InstanceId Type: String # Skip finding node 3 instance id if managed ad or no third zone - name: InstanceIdBranch action: aws:branch inputs: Choices: - NextStep: updateSSMAgent And: - Variable: '{{ActiveDirectoryConfig}}' StringEquals: Managed - Variable: '{{ThirdAZ}}' StringEquals: witness - NextStep: updateSSMAgent Variable: '{{ThirdAZ}}' StringEquals: none # START Self-Managed Third Node exists branch1 - {{WSFCNode3NetBIOSName}} holds Node3 or Witness NetBIOSName - name: wsfcnode3InstanceId action: aws:executeAwsApi onFailure: step:signalfailure inputs: Service: ec2 Api: DescribeInstances Filters: - Name: tag:Name Values: [ '{{WSFCNode3NetBIOSName}}' ] - Name: tag:aws:cloudformation:stack-name Values: [ '{{StackName}}' ] - Name: instance-state-name Values: [ 'running' ] outputs: - Name: InstanceId Selector: $.Reservations[0].Instances[0].InstanceId Type: String - name: updateSSMAgent action: aws:runCommand timeoutSeconds: 300 onFailure: Continue inputs: DocumentName: AWS-UpdateSSMAgent InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs - name: ManagedADBranch1 action: aws:branch inputs: Choices: - NextStep: CopyQSModule Variable: '{{ActiveDirectoryConfig}}' StringEquals: Managed # START Self-Managed AD branch1 - name: dc1InstanceId action: aws:executeAwsApi onFailure: step:signalfailure inputs: Service: ec2 Api: DescribeInstances Filters: - Name: tag:Name Values: [ '{{ADServer1NetBIOSName}}' ] - Name: instance-state-name Values: [ 'running' ] outputs: - Name: InstanceId Selector: $.Reservations[0].Instances[0].InstanceId Type: String - name: dc2InstanceId action: aws:executeAwsApi onFailure: step:signalfailure inputs: Service: ec2 Api: DescribeInstances Filters: - Name: tag:Name Values: [ '{{ADServer2NetBIOSName}}' ] - Name: instance-state-name Values: [ 'running' ] outputs: - Name: InstanceId Selector: $.Reservations[0].Instances[0].InstanceId Type: String # END Self-Managed AD branch1 - name: CopyQSModule action: aws:runCommand maxAttempts: 999 onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | New-Item -Type Directory C:\Windows\system32\WindowsPowerShell\v1.0\Modules\AWSQuickStart Copy-S3Object -Bucket {{QSS3BucketName}} -key {{QSS3KeyPrefix}}submodules/quickstart-microsoft-utilities/modules/AWSQuickStart/AWSQuickStart.psm1 -LocalFile C:\Windows\system32\WindowsPowerShell\v1.0\Modules\AWSQuickStart\AWSQuickStart.psm1 -Region {{QSS3BucketRegion}} - name: OSVersionBranch1 action: aws:branch inputs: Choices: - NextStep: 2012R2InstallWMF51 Variable: "{{OSVersion}}" StringEquals: WS2012R2 - name: InstallDSCModules action: aws:runCommand nextStep: LCMConfig onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/install-dsc-modules.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./install-dsc-modules.ps1 # START WS2012R2 OSVersion branch1 - name: 2012R2InstallWMF51 action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}submodules/quickstart-microsoft-utilities/scripts/Install-WMF51.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: - | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ./Install-WMF51.ps1 - name: 2012R2InstallDSC action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | Install-WindowsFeature -Name DSC-Service Set-Item -Path WSMan:\localhost\MaxEnvelopeSizeKb -Value 2048 Set-WSManQuickConfig -Force $PSVersion = $PSVersionTable.PSVersion.Major if ($PSVersion -eq '4') { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} - name: CopyNewCertificateScript action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | Copy-S3Object -Bucket {{QSS3BucketName}} -key {{QSS3KeyPrefix}}scripts/New-SelfSignedCertificateEx.ps1 -LocalFile C:\cfn\scripts\New-SelfSignedCertificateEx.ps1 -Region {{QSS3BucketRegion}} - name: InstallDSCModules2012R2 action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/install-dsc-modules.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./install-dsc-modules.ps1 -WS2012R2 # END WS2012R2 OSVersion branch1 - name: LCMConfig action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/LCM-Config.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./LCM-Config.ps1 - name: EnableCredSSP action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - Copy-S3Object -Bucket {{QSS3BucketName}} -key {{QSS3KeyPrefix}}submodules/quickstart-microsoft-utilities/scripts/EnableCredSsp.ps1 -LocalFile C:\cfn\scripts\EnableCredSsp.ps1 -Region {{QSS3BucketRegion}} - name: EnableCredSSPReboot action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | $CredSSPEnabled = Test-Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation' if ($CredSSPEnabled -eq $false) { C:\cfn\scripts\EnableCredSsp.ps1 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} - name: QSModuleStart action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - New-AWSQuickStartResourceSignal -Stack {{StackName}} -Resource SSMWaitCondition -Region {{global:REGION}} - name: SetDns action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}submodules/quickstart-microsoft-utilities/scripts/Set-Dns.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./Set-Dns.ps1 -ns1 {{ADServer1PrivateIP}} -ns2 {{ADServer2PrivateIP}} - name: OSVersionBranch2 action: aws:branch inputs: Choices: - NextStep: CopyDriveLetterMapping Variable: "{{OSVersion}}" StringEquals: WS2016 - NextStep: CopyDriveLetterMapping Variable: "{{OSVersion}}" StringEquals: WS2019 - NextStep: ManagedADBranch2 Variable: "{{OSVersion}}" StringEquals: WS2012R2 - name: CopyDriveLetterMapping action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | Copy-S3Object -Bucket {{QSS3BucketName}} -key {{QSS3KeyPrefix}}scripts/DriveLetterMappingConfig.json -LocalFile C:\ProgramData\Amazon\EC2-Windows\Launch\Config\DriveLetterMappingConfig.json -Region {{QSS3BucketRegion}} - name: InitializeDisk action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeDisks.ps1 - name: ManagedADBranch2 action: aws:branch inputs: Choices: - NextStep: DomainJoinSAD Variable: '{{ActiveDirectoryConfig}}' StringEquals: Legacy - name: DomainJoinMAD action: aws:runCommand maxAttempts: 10 nextStep: OpenWSFCPorts inputs: DocumentName: AWS-JoinDirectoryServiceDomain InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: directoryId: '{{ActiveDirectoryId}}' directoryName: '{{DomainDNSName}}' dnsIpAddresses: ['{{ADServer1PrivateIP}}','{{ADServer2PrivateIP}}'] - name: DomainJoinSAD action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/DomainJoin.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./DomainJoin.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -DomainDNSName {{DomainDNSName}} -AdminSecret {{AdminSecrets}} - name: DomainJoinApply action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | function DscStatusCheck () { $LCMState = (Get-DscLocalConfigurationManager).LCMState if ($LCMState -eq 'PendingConfiguration' -Or $LCMState -eq 'PendingReboot') { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} } Start-DscConfiguration 'C:\AWSQuickstart\DomainJoin' -Wait -Verbose -Force DscStatusCheck - name: OpenWSFCPorts action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/OpenWSFCPorts.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./OpenWSFCPorts.ps1 - name: ByolAmiBranch action: aws:branch inputs: Choices: - NextStep: CreateJob Variable: '{{AMIType}}' StringEquals: PAYG - name: DownloadDKCELicense action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/DownloadDKCELicense.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./DownloadDKCELicense.ps1 -SIOSLicenseKeyFtpURL "{{SIOSLicenseKeyFtpURL}}" - name: CreateJob action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/CreateJob.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: !If - ThirdAzIsFullNode - ./CreateJob.ps1 -JobName "vol.D" -JobDesc "DKCE Volume Protection" -SourceNames "{{WSFCNode1NetBIOSName}}.{{DomainDNSName}}","{{WSFCNode2NetBIOSName}}.{{DomainDNSName}}" -SourceVols "D","D" -SourceIPs "{{WSFCNode1PrivateIP1}}","{{WSFCNode2PrivateIP1}}" -TargetNames "{{WSFCNode2NetBIOSName}}.{{DomainDNSName}}","{{WSFCNode3NetBIOSName}}.{{DomainDNSName}}" -TargetIPs "{{WSFCNode2PrivateIP1}}","{{WSFCNode3PrivateIP1}}" -TargetVols "D","D" -SyncTypes "S","S","S" - ./CreateJob.ps1 -JobName "vol.D" -JobDesc "DKCE Volume Protection" -SourceNames "{{WSFCNode1NetBIOSName}}.{{DomainDNSName}}" -SourceVols "D" -SourceIPs "{{WSFCNode1PrivateIP1}}" -TargetNames "{{WSFCNode2NetBIOSName}}.{{DomainDNSName}}" -TargetIPs "{{WSFCNode2PrivateIP1}}" -TargetVols "D" -SyncTypes "S" - name: CreateMirror action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/CreateMirror.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: !If - ThirdAzIsFullNode - ./CreateMirror.ps1 -SourceIP "{{WSFCNode1PrivateIP1}}" -Volume "D" -TargetIPs "{{WSFCNode2PrivateIP1}}","{{WSFCNode3PrivateIP1}}" -SyncTypes "S","S" - ./CreateMirror.ps1 -SourceIP "{{WSFCNode1PrivateIP1}}" -Volume "D" -TargetIPs "{{WSFCNode2PrivateIP1}}" -SyncTypes "S" - name: ManagedADBranch3 action: aws:branch inputs: Choices: - NextStep: WSFCConfigureBranch Variable: "{{ActiveDirectoryConfig}}" StringEquals: Managed - name: ThirdAZWitnessBranch1 action: aws:branch inputs: Choices: - NextStep: WitnessInstallDSCModules3AZ Variable: '{{ThirdAZ}}' StringEquals: witness - NextStep: InvokeADReplicationDC1 Variable: '{{ThirdAZ}}' StringEquals: full - name: CreateSmbFileShare2AZ action: aws:runCommand nextStep: InvokeADReplicationDC1 onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{dc1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | $sharePath = 'C:\witness' if (-Not(Test-Path -Path $sharePath)) { New-Item -ItemType Directory -Path $sharePath -Force } New-SmbShare -Name witness -Path $sharePath -FullAccess "Everyone" - name: WitnessInstallDSCModules3AZ action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode3InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/install-fsw-modules.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./install-fsw-modules.ps1 - name: WitnessCreateFileShare3AZ action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode3InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/WSFCFileShare.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./WSFCFileShare.ps1 - name: InvokeADReplicationDC1 action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{dc1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | repadmin /syncall /A /e /P - name: InvokeADReplicationDC2 action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{dc2InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | repadmin /syncall /A /e /P # END Self-Managed AD branch2 - name: WSFCConfigureBranch action: aws:branch inputs: Choices: - NextStep: Node1configureWSFCNOSQL Variable: '{{SQLServerVersion}}' StringEquals: None # START INSTALL SQL branch2 - name: ManagedADBranch4 action: aws:branch inputs: Choices: - NextStep: Node1configureWSFCSQLManagedAD Variable: "{{ActiveDirectoryConfig}}" StringEquals: Managed # START Self-Managed AD branch3 - name: Node1configureWSFCSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/Node1Config.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./Node1Config.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -DomainDNSName {{DomainDNSName}} -WSFCNode1PrivateIP2 {{WSFCNode1PrivateIP2}} -ClusterName {{ClusterName}} -AdminSecret {{AdminSecrets}} -SQLSecret {{SQLSecrets}} - name: ApplyWSFCNode1Config action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | function DscStatusCheck () { $LCMState = (Get-DscLocalConfigurationManager).LCMState if ( -Not ($LCMState -eq 'PendingConfiguration' -Or $LCMState -eq 'PendingReboot') ) { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} } Start-DscConfiguration 'C:\AWSQuickstart\WSFCNode1Config' -Wait -Verbose -Force DscStatusCheck - name: ThirdAZWitnessBranch2 action: aws:branch inputs: Choices: - NextStep: Node1Reboot1SQL Variable: '{{ThirdAZ}}' StringEquals: full - name: SetFolderPermissions action: aws:runCommand onFailure: step:signalfailure nextStep: Node1Reboot1SQL inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode2InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/Set-Folder-Permissions.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: !Sub - ./Set-Folder-Permissions.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -AdminSecret {{AdminSecrets}} -SQLSecret {{SQLSecrets}} -ClusterName {{ClusterName}} ${ShareOption} - ShareOption: !If - ThirdAzIsWitness - '-FileServerNetBIOSName {{WSFCNode3NetBIOSName}}' - '-FileServerNetBIOSName {{ADServer1NetBIOSName}}' # END Self-Managed AD branch3 - name: Node1configureWSFCSQLManagedAD action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/Node1Config.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./Node1Config.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -DomainDNSName {{DomainDNSName}} -WSFCNode1PrivateIP2 {{WSFCNode1PrivateIP2}} -ClusterName {{ClusterName}} -AdminSecret {{AdminSecrets}} -SQLSecret {{SQLSecrets}} - name: Node1Reboot1SQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | function DscStatusCheck () { $LCMState = (Get-DscLocalConfigurationManager).LCMState if ($LCMState -eq 'PendingConfiguration' -Or $LCMState -eq 'PendingReboot') { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} } Start-DscConfiguration 'C:\AWSQuickstart\WSFCNode1Config' -Wait -Verbose -Force DscStatusCheck - name: Node2configureWSFCSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode2InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/AdditionalNodeConfig.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./AdditionalNodeConfig.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -WSFCNodePrivateIP2 {{WSFCNode2PrivateIP2}} -ClusterName {{ClusterName}} -AdminSecret {{AdminSecrets}} -SQLSecret {{SQLSecrets}} - name: Node2Reboot1SQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnode2InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | function DscStatusCheck () { $LCMState = (Get-DscLocalConfigurationManager).LCMState if ($LCMState -eq 'PendingConfiguration' -Or $LCMState -eq 'PendingReboot') { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} } Start-DscConfiguration 'C:\AWSQuickstart\AdditionalWSFCNode' -Wait -Verbose -Force DscStatusCheck - name: ThirdAZWitnessBranch3 action: aws:branch inputs: Choices: - NextStep: WSFCQuorumConfig Variable: '{{ThirdAZ}}' StringEquals: witness - NextStep: WSFCQuorumConfig Variable: '{{ThirdAZ}}' StringEquals: none - name: Node3configureWSFCSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode3InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/AdditionalNodeConfig.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./AdditionalNodeConfig.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -WSFCNodePrivateIP2 {{WSFCNode3PrivateIP2}} -ClusterName {{ClusterName}} -AdminSecret {{AdminSecrets}} -SQLSecret {{SQLSecrets}} - name: Node3Reboot1SQL action: aws:runCommand onFailure: step:signalfailure nextStep: WSFCQuorumConfig inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnode3InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | function DscStatusCheck () { $LCMState = (Get-DscLocalConfigurationManager).LCMState if ($LCMState -eq 'PendingConfiguration' -Or $LCMState -eq 'PendingReboot') { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} } Start-DscConfiguration 'C:\AWSQuickstart\AdditionalWSFCNode' -Wait -Verbose -Force DscStatusCheck # END INSTALL SQL branch2 # START NO SQL branch1 - name: Node1configureWSFCNOSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/Node1Config.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./Node1Config.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -DomainDNSName {{DomainDNSName}} -WSFCNode1PrivateIP2 {{WSFCNode1PrivateIP2}} -ClusterName {{ClusterName}} -AdminSecret {{AdminSecrets}} - name: ApplyWSFCNode1ConfigNoSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | function DscStatusCheck () { $LCMState = (Get-DscLocalConfigurationManager).LCMState if ($LCMState -eq 'PendingConfiguration' -Or $LCMState -eq 'PendingReboot') { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} } Start-DscConfiguration 'C:\AWSQuickstart\WSFCNode1Config' -Wait -Verbose -Force DscStatusCheck - name: Node1Reboot1NoSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | function DscStatusCheck () { $LCMState = (Get-DscLocalConfigurationManager).LCMState if ($LCMState -eq 'PendingConfiguration' -Or $LCMState -eq 'PendingReboot') { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} } Start-DscConfiguration 'C:\AWSQuickstart\WSFCNode1Config' -Wait -Verbose -Force DscStatusCheck - name: Node2ConfigureWSFCNOSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode2InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/AdditionalNodeConfig.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./AdditionalNodeConfig.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -WSFCNodePrivateIP2 {{WSFCNode2PrivateIP2}} -ClusterName {{ClusterName}} -AdminSecret {{AdminSecrets}} - name: Node2Reboot1NoSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnode2InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | function DscStatusCheck () { $LCMState = (Get-DscLocalConfigurationManager).LCMState if ($LCMState -eq 'PendingConfiguration' -Or $LCMState -eq 'PendingReboot') { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} } Start-DscConfiguration 'C:\AWSQuickstart\AdditionalWSFCNode' -Wait -Verbose -Force DscStatusCheck - name: ThirdAZWitnessBranch4 action: aws:branch inputs: Choices: - NextStep: WSFCQuorumConfig Variable: '{{ThirdAZ}}' StringEquals: witness - NextStep: WSFCQuorumConfig Variable: '{{ThirdAZ}}' StringEquals: none - name: Node3ConfigureWSFCNOSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode3InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/AdditionalNodeConfig.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./AdditionalNodeConfig.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -WSFCNodePrivateIP2 {{WSFCNode3PrivateIP2}} -ClusterName {{ClusterName}} -AdminSecret {{AdminSecrets}} - name: Node3Reboot1NoSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnode3InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | function DscStatusCheck () { $LCMState = (Get-DscLocalConfigurationManager).LCMState if ($LCMState -eq 'PendingConfiguration' -Or $LCMState -eq 'PendingReboot') { 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} } Start-DscConfiguration 'C:\AWSQuickstart\AdditionalWSFCNode' -Wait -Verbose -Force DscStatusCheck # END NO SQL branch1 - name: WSFCQuorumConfig action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/WSFCQuorumConfig.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: !Sub - ./WSFCQuorumConfig.ps1 ${QuorumOption} - QuorumOption: !If - UsingAWSManagedAD - !If - ThirdAzIsFullNode - '' - '-SharePath \\{{FSxDNSName}}\share' - !If - ThirdAzIsFullNode - '' - !If - ThirdAzIsWitness - '-SharePath \\{{WSFCNode3NetBIOSName}}.{{DomainDNSName}}\witness' - '-SharePath \\{{ADServer1NetBIOSName}}.{{DomainDNSName}}\witness' - name: WaitForCluster action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/WaitForCluster.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./WaitForCluster.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -AdminSecret {{AdminSecrets}} -NetBIOSName {{WSFCNode1NetBIOSName}} - name: ConfigurePermissionsOnMAD action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/Configure-MAD-Permissions.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./Configure-MAD-Permissions.ps1 -AdminSecret {{AdminSecrets}} -DomainNetBIOSName '{{DomainNetBIOSName}}' -wsfcName '{{ClusterName}}' - name: registerclustervolume action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/RegisterClusterVolume.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./RegisterClusterVolume.ps1 -Volume D - name: InstallSQLBranch action: aws:branch inputs: Choices: - NextStep: DisableCredSSP Variable: '{{SQLServerVersion}}' StringEquals: None # START INSTALL SQL branch3 - name: InstallSQL action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode1InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/InstallSQLEE.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./InstallSQLEE.ps1 -SQLServerVersion 'SQL{{SQLServerVersion}}' -DomainNetBIOSName {{DomainNetBIOSName}} -AdminSecret {{AdminSecrets}} -SQLSecret {{SQLSecrets}} -NetBIOSName {{WSFCNode1NetBIOSName}} -SQLServerClusterIP {{WSFCNode1PrivateIP3}} -ClusterSubnetCidr {{PrivateSubnet1CIDR}} - name: SQLInstallNode2MOF action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode2InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/InstallSQLEE-AddNode.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./InstallSQLEE-AddNode.ps1 -SQLServerVersion 'SQL{{SQLServerVersion}}' -DomainNetBIOSName {{DomainNetBIOSName}} -AdminSecret {{AdminSecrets}} -SQLSecret {{SQLSecrets}} -NetBIOSName {{WSFCNode2NetBIOSName}} -ClusterIPAddresses {{WSFCNode1PrivateIP3}},{{WSFCNode2PrivateIP3}} -ClusterSubnetCidrs {{PrivateSubnet1CIDR}},{{PrivateSubnet2CIDR}} - name: WaitForClusterGroup action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunRemoteScript InstanceIds: - '{{wsfcnode2InstanceId.InstanceId}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: sourceType: S3 sourceInfo: !Sub - '{"path": "https://${S3Bucket}.s3.${S3Region}.{{URLSuffix}}/{{QSS3KeyPrefix}}scripts/WaitForClusterGroup.ps1"}' - S3Bucket: !If - UsingDefaultBucket - !Sub '${QSS3BucketName}-${AWS::Region}' - !Ref QSS3BucketName S3Region: !If - UsingDefaultBucket - !Ref AWS::Region - !Ref QSS3BucketRegion commandLine: ./WaitForClusterGroup.ps1 -DomainNetBIOSName {{DomainNetBIOSName}} -AdminSecret {{AdminSecrets}} -NetBIOSName {{WSFCNode2NetBIOSName}} # END INSTALL SQL branch3 - name: DisableCredSSP action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - Copy-S3Object -Bucket {{QSS3BucketName}} -key {{QSS3KeyPrefix}}submodules/quickstart-microsoft-utilities/scripts/DisableCredSsp.ps1 -LocalFile C:\cfn\scripts\DisableCredSsp.ps1 -Region {{QSS3BucketRegion}} - name: DisableCredSSPReboot action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - | $CredSSPEnabled = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation' -Name AllowFreshCredentials -ErrorAction SilentlyContinue).AllowFreshCredentials if ($CredSSPEnabled -eq 1) { C:\cfn\scripts\DisableCredSsp.ps1 'returning 3010, should continue after reboot' exit 3010 } else {'Next Step'} - name: DSCCleanup action: aws:runCommand onFailure: step:signalfailure inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - '{{wsfcnodesInstanceId.InstanceIds}}' CloudWatchOutputConfig: CloudWatchOutputEnabled: 'true' CloudWatchLogGroupName: !Ref QuickStartLogs Parameters: commands: - Remove-Item -Path C:\AWSQuickstart\ -recurse # Determines if CFN Needs to be Signaled or if Work flow should just end - name: CFNSignalEnd action: aws:branch inputs: Choices: - NextStep: signalsuccess Not: Variable: '{{StackName}}' StringEquals: '' - NextStep: sleepend Variable: '{{StackName}}' StringEquals: '' # If all steps complete successfully signals CFN of Success - name: signalsuccess action: aws:executeAwsApi isEnd: true inputs: Service: cloudformation Api: SignalResource LogicalResourceId: SSMWaitCondition StackName: '{{StackName}}' Status: SUCCESS UniqueId: '{{wsfcnode2InstanceId.InstanceId}}' # If CFN Signl Not Needed this sleep ends work flow - name: sleepend action: aws:sleep isEnd: true inputs: Duration: PT1S # If any steps fails signals CFN of Failure - name: signalfailure action: aws:executeAwsApi inputs: Service: cloudformation Api: SignalResource LogicalResourceId: SSMWaitCondition StackName: '{{StackName}}' Status: FAILURE UniqueId: '{{wsfcnode2InstanceId.InstanceId}}' InstanceRole: Type: AWS::IAM::Role Metadata: cfn-lint: config: ignore_checks: - EIAMPolicyWildcardResource Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - !Sub 'ec2.${AWS::URLSuffix}' - !Sub 'ssm.${AWS::URLSuffix}' Action: - sts:AssumeRole Path: / ManagedPolicyArns: - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM' Policies: - PolicyName: aws-quick-start-s3-policy PolicyDocument: Version: 2012-10-17 Statement: - Action: - s3:GetObject - s3:ListBucket Resource: - !Sub ['arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}*', S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]] - !Sub ['arn:${AWS::Partition}:s3:::${S3Bucket}', S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName]] Effect: Allow - Action: - s3:GetObject Resource: - !Sub 'arn:${AWS::Partition}:s3:::aws-ssm-${AWS::Region}/*' - !Sub 'arn:${AWS::Partition}:s3:::amazon-ssm-${AWS::Region}/*' - !Sub 'arn:${AWS::Partition}:s3:::amazon-ssm-packages-${AWS::Region}/*' - !Sub 'arn:${AWS::Partition}:s3:::${AWS::Region}-birdwatcher-prod/*' - !Sub 'arn:${AWS::Partition}:s3:::patch-baseline-snapshot-${AWS::Region}/*' Effect: Allow - PolicyName: ssm-custom-s3-policy PolicyDocument: Version: '2012-10-17' Statement: - Action: - s3:GetObject Resource: - !Sub 'arn:${AWS::Partition}:s3:::aws-ssm-${AWS::Region}/*' - !Sub 'arn:${AWS::Partition}:s3:::aws-windows-downloads-${AWS::Region}/*' - !Sub 'arn:${AWS::Partition}:s3:::amazon-ssm-${AWS::Region}/*' - !Sub 'arn:${AWS::Partition}:s3:::amazon-ssm-packages-${AWS::Region}/*' - !Sub 'arn:${AWS::Partition}:s3:::${AWS::Region}-birdwatcher-prod/*' - !Sub 'arn:${AWS::Partition}:s3:::patch-baseline-snapshot-${AWS::Region}/*' Effect: Allow - PolicyName: QS-MSSQL-SSM PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - secretsmanager:GetSecretValue - secretsmanager:DescribeSecret Resource: - !Ref 'SQLSecrets' - !Ref 'ADAdminSecrets' - Effect: Allow Action: - ssm:StartAutomationExecution Resource: '*' - PolicyName: cloudformation-policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - cloudformation:SignalResource Resource: !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${AWS::StackName}/*' - Effect: Allow Action: - cloudformation:DescribeStacks Resource: !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/*' - PolicyName: ssm-policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: ssm:StartAutomationExecution Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${SSMDocumentDKCE}:$DEFAULT - Effect: Allow Action: ssm:SendCommand Resource: - !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:*:document/AWS-JoinDirectoryServiceDomain - Effect: Allow Action: ssm:SendCommand Resource: - !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:*:document/AWS-RunRemoteScript - Effect: Allow Action: ssm:SendCommand Resource: - !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:*:document/AWS-RunPowerShellScript - Effect: Allow Action: ssm:SendCommand Resource: - !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:*:document/AWS-UpdateSSMAgent - Effect: Allow Action: ssm:SendCommand Resource: !Sub arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/* - Effect: Allow Action: - ssm:DescribeInstanceInformation - ssm:ListCommandInvocations - ssm:ListCommands Resource: '*' - PolicyName: ec2-policy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - ec2:DescribeInstances - ec2:DescribeInstanceStatus - ec2:DescribeTags - fsx:DescribeFileSystems - tag:GetResources Resource: '*' SIOSSSMPassRolePolicy: Type: AWS::IAM::Policy Properties: PolicyName: SIOS-SSM-PassRole PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - iam:PassRole Resource: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${InstanceRole} Roles: - !Ref InstanceRole InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Path: / Roles: - !Ref InstanceRole FSxSecurityGroup: Condition: NeedsFSxWitness Type: 'AWS::EC2::SecurityGroup' Properties: VpcId: !Ref VPCID GroupDescription: Security group for Amazon FSx file-storage access SecurityGroupIngress: - IpProtocol: tcp FromPort: 53 ToPort: 53 CidrIp: !Ref VPCCIDR - IpProtocol: udp FromPort: 53 ToPort: 53 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 88 ToPort: 88 CidrIp: !Ref VPCCIDR - IpProtocol: udp FromPort: 88 ToPort: 88 CidrIp: !Ref VPCCIDR - IpProtocol: udp FromPort: 123 ToPort: 123 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 135 ToPort: 135 CidrIp: !Ref VPCCIDR - IpProtocol: udp FromPort: 389 ToPort: 389 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 389 ToPort: 389 CidrIp: !Ref VPCCIDR - IpProtocol: udp FromPort: 445 ToPort: 445 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 445 ToPort: 445 CidrIp: !Ref VPCCIDR - IpProtocol: udp FromPort: 464 ToPort: 464 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 464 ToPort: 464 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 636 ToPort: 636 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 3268 ToPort: 3268 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 3269 ToPort: 3269 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 5985 ToPort: 5985 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 9389 ToPort: 9389 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 49152 ToPort: 65535 CidrIp: !Ref VPCCIDR WindowsFSx: Condition: NeedsFSxWitness Type: AWS::FSx::FileSystem Properties: FileSystemType: WINDOWS StorageCapacity: 32 SubnetIds: !If - ThirdAzIsWitness - [ !Ref 'PrivateSubnet3ID' ] - [ !Ref 'PrivateSubnet1ID' ] SecurityGroupIds: - !Ref 'DomainMemberSGID' - !Ref 'FSxSecurityGroup' Tags: - Key: Name Value: !Sub "FSxWitness-${AWS::StackName}" WindowsConfiguration: ActiveDirectoryId: !Ref 'ActiveDirectoryId' DeploymentType: SINGLE_AZ_2 ThroughputCapacity: 32 WSFCWitness: Condition: NeedsWitnessNode Type: AWS::EC2::Instance Metadata: AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref InstanceRole buckets: !Ref QSS3BucketName Properties: ImageId: !Ref WSFCWitnessAmiId IamInstanceProfile: !Ref InstanceProfile InstanceType: !Ref WSFCWitnessInstanceType NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' SubnetId: !Ref PrivateSubnet3ID PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref WSFCNode3PrivateIP1 GroupSet: - !Ref DomainMemberSGID - !Ref WSFCSecurityGroup Tags: - Key: Name Value: !Ref WSFCWitnessNetBIOSName BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp2 KeyName: !Ref KeyPairName UserData: !Base64 Fn::Join: - '' - - "\n" - "New-Item -Path C:\\ -Name log -ItemType Directory \n" - !Sub 'Set-Content -Value "${WSFCWitnessNetBIOSName}" -Path C:\log\hostname.txt' - "\n" - !Sub 'Rename-Computer -NewName "${WSFCWitnessNetBIOSName}"' - "\n" - "\n" WSFCNode1: Type: AWS::EC2::Instance Metadata: AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref InstanceRole buckets: !Ref QSS3BucketName Properties: ImageId: !If - ByolAmiCondition - !FindInMap - AWSAMIRegionMap - !Ref AWS::Region - !FindInMap - BYOLNameMap - !Ref OSVersion - Code - !FindInMap - AWSAMIRegionMap - !Ref AWS::Region - !FindInMap - PAYGNameMap - !Ref OSVersion - Code IamInstanceProfile: !Ref InstanceProfile InstanceType: !Ref WSFCNode1InstanceType EbsOptimized: true NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' SubnetId: !Ref PrivateSubnet1ID PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref WSFCNode1PrivateIP1 - Primary: false PrivateIpAddress: !Ref WSFCNode1PrivateIP2 - Primary: false PrivateIpAddress: !Ref WSFCNode1PrivateIP3 GroupSet: - !Ref DomainMemberSGID - !Ref WSFCSecurityGroup - !Ref SIOSDataKeeperSG Tags: - Key: Name Value: !Ref WSFCNode1NetBIOSName BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 127 VolumeType: gp2 - DeviceName: /dev/xvdca VirtualName: ephemeral0 KeyName: !Ref KeyPairName UserData: !Base64 Fn::Join: - '' - - "\n" - "New-Item -Path C:\\ -Name log -ItemType Directory \n" - !Sub 'Set-Content -Value "${WSFCNode1NetBIOSName}" -Path C:\log\hostname.txt' - "\n" - !Sub 'Rename-Computer -NewName "${WSFCNode1NetBIOSName}"' - "\n" - "\n" WSFCNode3: Condition: ThirdAzIsFullNode Type: AWS::EC2::Instance Metadata: AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref InstanceRole buckets: !Ref QSS3BucketName Properties: ImageId: !If - ByolAmiCondition - !FindInMap - AWSAMIRegionMap - !Ref AWS::Region - !FindInMap - BYOLNameMap - !Ref OSVersion - Code - !FindInMap - AWSAMIRegionMap - !Ref AWS::Region - !FindInMap - PAYGNameMap - !Ref OSVersion - Code IamInstanceProfile: !Ref InstanceProfile InstanceType: !Ref WSFCNode3InstanceType EbsOptimized: true NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' SubnetId: !Ref PrivateSubnet3ID PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref WSFCNode3PrivateIP1 - Primary: false PrivateIpAddress: !Ref WSFCNode3PrivateIP2 - Primary: false PrivateIpAddress: !Ref WSFCNode3PrivateIP3 GroupSet: - !Ref DomainMemberSGID - !Ref WSFCSecurityGroup - !Ref SIOSDataKeeperSG Tags: - Key: Name Value: !Ref WSFCNode3NetBIOSName BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 127 VolumeType: gp2 - DeviceName: /dev/xvdca VirtualName: ephemeral0 KeyName: !Ref KeyPairName UserData: !Base64 Fn::Join: - '' - - "\n" - "New-Item -Path C:\\ -Name log -ItemType Directory \n" - !Sub 'Set-Content -Value "${WSFCNode3NetBIOSName}" -Path C:\log\hostname.txt' - "\n" - !Sub 'Rename-Computer -NewName "${WSFCNode3NetBIOSName}"' - "\n" - "\n" WSFCNode2: Type: AWS::EC2::Instance Metadata: AWS::CloudFormation::Authentication: S3AccessCreds: type: S3 roleName: !Ref InstanceRole buckets: !Ref QSS3BucketName Properties: ImageId: !If - ByolAmiCondition - !FindInMap - AWSAMIRegionMap - !Ref AWS::Region - !FindInMap - BYOLNameMap - !Ref OSVersion - Code - !FindInMap - AWSAMIRegionMap - !Ref AWS::Region - !FindInMap - PAYGNameMap - !Ref OSVersion - Code IamInstanceProfile: !Ref InstanceProfile InstanceType: !Ref WSFCNode2InstanceType EbsOptimized: true NetworkInterfaces: - DeleteOnTermination: true DeviceIndex: '0' SubnetId: !Ref PrivateSubnet2ID PrivateIpAddresses: - Primary: true PrivateIpAddress: !Ref WSFCNode2PrivateIP1 - Primary: false PrivateIpAddress: !Ref WSFCNode2PrivateIP2 - Primary: false PrivateIpAddress: !Ref WSFCNode2PrivateIP3 GroupSet: - !Ref DomainMemberSGID - !Ref WSFCSecurityGroup - !Ref SIOSDataKeeperSG Tags: - Key: Name Value: !Ref WSFCNode2NetBIOSName BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 127 VolumeType: gp2 - DeviceName: /dev/xvdca VirtualName: ephemeral0 KeyName: !Ref KeyPairName UserData: !Base64 Fn::Join: - '' - - "\n" - "New-Item -Path C:\\ -Name log -ItemType Directory \n" - !Sub 'Set-Content -Value "${WSFCNode2NetBIOSName}" -Path C:\log\hostname.txt' - "\n" - !Sub 'Rename-Computer -NewName "${WSFCNode2NetBIOSName}"' - "\n" - 'Start-Transcript -Path C:\\cfn\\log\\Start-DSCConfiguration.txt;' - 'Start-SSMAutomationExecution -DocumentName ' - !Sub '"${SSMDocumentDKCE}"' - ' -Parameter @{"AMIType"=' - !Sub '"${AMIType}"' - ';"ActiveDirectoryConfig"=' - !Sub - '"${ADConfig}"' - ADConfig: !If - UsingAWSManagedAD - Managed - Legacy - ';"ActiveDirectoryId"=' - !Sub '"${ActiveDirectoryId}"' - ';"AdminSecrets"=' - !Sub '"${ADAdminSecrets}"' - ';"ADServer1NetBIOSName"=' - !Sub '"${ADServer1NetBIOSName}"' - ';"ADServer1PrivateIP"=' - !Sub '"${ADServer1PrivateIP}"' - ';"ADServer2NetBIOSName"=' - !Sub '"${ADServer2NetBIOSName}"' - ';"ADServer2PrivateIP"=' - !Sub '"${ADServer2PrivateIP}"' - ';"ClusterName"=' - !Sub '"${ClusterName}"' - ';"DomainDNSName"=' - !Sub '"${DomainDNSName}"' - ';"DomainNetBIOSName"=' - !Sub '"${DomainNetBIOSName}"' - ';"FSxDNSName"=' - !Sub - '"${FSxDNSName}"' - FSxDNSName: !If - NeedsFSxWitness - !Sub ${WindowsFSx.DNSName} - '' - ';"OSVersion"=' - !Sub '"${OSVersion}"' - ';"PrivateSubnet1CIDR"=' - !Sub '"${PrivateSubnet1CIDR}"' - ';"PrivateSubnet2CIDR"=' - !Sub '"${PrivateSubnet2CIDR}"' - ';"PrivateSubnet3CIDR"=' - !Sub '"${PrivateSubnet3CIDR}"' - ';"SIOSLicenseKeyFtpURL"=' - !Sub '"${SIOSLicenseKeyFtpURL}"' - ';"SQLSecrets"=' - !Sub '"${SQLSecrets}"' - ';"SQLServerVersion"=' - !Sub '"${SQLServerVersion}"' - ';"ThirdAZ"=' - !Sub '"${ThirdAZ}"' - ';"WSFCNode1NetBIOSName"=' - !Sub '"${WSFCNode1NetBIOSName}"' - ';"WSFCNode1PrivateIP1"=' - !Sub '"${WSFCNode1PrivateIP1}"' - ';"WSFCNode1PrivateIP2"=' - !Sub '"${WSFCNode1PrivateIP2}"' - ';"WSFCNode1PrivateIP3"=' - !Sub '"${WSFCNode1PrivateIP3}"' - ';"WSFCNode2NetBIOSName"=' - !Sub '"${WSFCNode2NetBIOSName}"' - ';"WSFCNode2PrivateIP1"=' - !Sub '"${WSFCNode2PrivateIP1}"' - ';"WSFCNode2PrivateIP2"=' - !Sub '"${WSFCNode2PrivateIP2}"' - ';"WSFCNode2PrivateIP3"=' - !Sub '"${WSFCNode2PrivateIP3}"' - ';"WSFCNode3NetBIOSName"=' - !Sub - '"${WSFCNode3Name}"' - WSFCNode3Name: !If - NeedsWitnessNode - !Sub ${WSFCWitnessNetBIOSName} - !Sub ${WSFCNode3NetBIOSName} - ';"WSFCNode3PrivateIP1"=' - !Sub '"${WSFCNode3PrivateIP1}"' - ';"WSFCNode3PrivateIP2"=' - !Sub '"${WSFCNode3PrivateIP2}"' - ';"WSFCNode3PrivateIP3"=' - !Sub '"${WSFCNode3PrivateIP3}"' - ';"WSFCNodeNames"=' - !If - TwoNodeDeployment - !Sub '"${WSFCNode1NetBIOSName}","${WSFCNode2NetBIOSName}"' - !Sub - '"${WSFCNode1NetBIOSName}","${WSFCNode2NetBIOSName}","${WSFCNode3Name}"' - WSFCNode3Name: !If - NeedsWitnessNode - !Sub ${WSFCWitnessNetBIOSName} - !Sub ${WSFCNode3NetBIOSName} - ';"QSS3BucketName"=' - !Sub '"${QSS3BucketName}"' - ';"QSS3BucketRegion"=' - !Sub '"${QSS3BucketRegion}"' - ';"QSS3KeyPrefix"=' - !Sub '"${QSS3KeyPrefix}"' - ';"StackName"=' - !Sub '"${AWS::StackName}"' - ';"URLSuffix"=' - !Sub '"${AWS::URLSuffix}"' - ';"AutomationAssumeRole"=' - !Sub '"arn:aws:iam::${AWS::AccountId}:role/${InstanceRole}"' - '}' - ';Stop-Transcript;' - "\n" WSFCNode1Volume1: Type: AWS::EC2::Volume Properties: Encrypted: true Size: !Ref Volume1Size VolumeType: !Ref Volume1Type AvailabilityZone: !GetAtt WSFCNode1.AvailabilityZone Iops: !If [Vol1IsIo1, !Ref 'Volume1Iops', !Ref 'AWS::NoValue'] WSFCNode2Volume1: Type: AWS::EC2::Volume Properties: Encrypted: true Size: !Ref Volume1Size VolumeType: !Ref Volume1Type AvailabilityZone: !GetAtt WSFCNode2.AvailabilityZone Iops: !If [Vol1IsIo1, !Ref 'Volume1Iops', !Ref 'AWS::NoValue'] WSFCNode3Volume1: Condition: ThirdAzIsFullNode Type: AWS::EC2::Volume Properties: Encrypted: true Size: !Ref Volume1Size VolumeType: !Ref Volume1Type AvailabilityZone: !GetAtt WSFCNode3.AvailabilityZone Iops: !If [Vol1IsIo1, !Ref 'Volume1Iops', !Ref 'AWS::NoValue'] WSFCNode1Volume1Attachment: Type: AWS::EC2::VolumeAttachment Properties: Device: /dev/xvdb InstanceId: !Ref WSFCNode1 VolumeId: !Ref WSFCNode1Volume1 WSFCNode2Volume1Attachment: Type: AWS::EC2::VolumeAttachment Properties: Device: /dev/xvdb InstanceId: !Ref WSFCNode2 VolumeId: !Ref WSFCNode2Volume1 WSFCNode3Volume1Attachment: Condition: ThirdAzIsFullNode Type: AWS::EC2::VolumeAttachment Properties: Device: /dev/xvdb InstanceId: !Ref WSFCNode3 VolumeId: !Ref WSFCNode3Volume1 SSMWaitHandle: Type: AWS::CloudFormation::WaitConditionHandle SSMWaitCondition: Type: AWS::CloudFormation::WaitCondition CreationPolicy: ResourceSignal: Timeout: PT300M Count: 1 DependsOn: WSFCNode2 Properties: Handle: Ref: SSMWaitHandle Timeout: '18000' Count: 1 SIOSDataKeeperSG: Type: AWS::EC2::SecurityGroup Properties: VpcId: !Ref VPCID GroupDescription: Security group for replication communication SecurityGroupIngress: - IpProtocol: tcp FromPort: 9999 ToPort: 9999 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 10000 ToPort: 10025 CidrIp: !Ref VPCCIDR WSFCSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: VpcId: !Ref VPCID GroupDescription: Security group to enable WSFC communications SecurityGroupIngress: - IpProtocol: '-1' FromPort: -1 ToPort: -1 CidrIp: !Ref VPCCIDR Outputs: QuickStartLogs: Value: !Ref QuickStartLogs Description: CloudWatch log group WSFCNode1NetBIOSName: Value: !Ref WSFCNode1NetBIOSName Description: NetBIOS name of the 1st WSFC Node WSFCNode2NetBIOSName: Value: !Ref WSFCNode2NetBIOSName Description: NetBIOS name of the 2nd WSFC Node WSFCNode3NetBIOSName: Condition: ThirdAzIsFullNode Value: !Ref WSFCNode3NetBIOSName Description: NetBIOS name of the 3rd WSFC Node WSFCWitnessNetBIOSName: Condition: ThirdAzIsWitness Value: !Ref WSFCNode3NetBIOSName Description: NetBIOS name of the WSFC Witness Node Postdeployment: Description: See the deployment guide for post-deployment steps. Value: https://aws.amazon.com/quickstart/?quickstart-all.sort-by=item.additionalFields.sortDate&quickstart-all.sort-order=desc&awsm.page-quickstart-all=5