AWSTemplateFormatVersion: '2010-09-09' Description: This template creates 2 Windows 2016 Active Directory Domain Controllers into private subnets in separate Availability Zones inside a VPC. The default Domain Administrator password will be the one retrieved from the instance. For adding members to the domain, ensure that they are launched into the domain member security group created by this template and then configure them to use the AD instances fixed private IP addresses as the DNS server. **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(0001) Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Network Configuration Parameters: - VPCCIDR - VPCID - PrivateSubnet1ID - PrivateSubnet2ID - Label: default: Amazon EC2 Configuration Parameters: - ADServer1InstanceType - ADServer1NetBIOSName - ADServer1PrivateIP - ADServer2InstanceType - ADServer2NetBIOSName - ADServer2PrivateIP - KeyPairName - WINFULLBASE - Label: default: Microsoft Active Directory Configuration Parameters: - DomainAdminPassword - DomainAdminUser - DomainDNSName - DomainNetBIOSName - Label: default: AWS Quick Start Configuration Parameters: - QSS3BucketName - QSS3KeyPrefix ParameterLabels: ADServer1InstanceType: default: Domain Controller 1 Instance Type ADServer1NetBIOSName: default: Domain Controller 1 NetBIOS Name ADServer1PrivateIP: default: Domain Controller 1 Private IP Address ADServer2InstanceType: default: Domain Controller 2 Instance Type ADServer2NetBIOSName: default: Domain Controller 2 NetBIOS Name ADServer2PrivateIP: default: Domain Controller 2 Private IP Address DomainAdminPassword: default: Domain Admin Password DomainAdminUser: default: Domain Admin User Name DomainDNSName: default: Domain DNS Name DomainNetBIOSName: default: Domain NetBIOS Name KeyPairName: default: Key Pair Name WINFULLBASE: default: SSM Parameter Value to grab the lastest AMI ID PrivateSubnet1ID: default: Private Subnet 1 ID PrivateSubnet2ID: default: Private Subnet 2 ID QSS3BucketName: default: Quick Start S3 Bucket Name QSS3KeyPrefix: default: Quick Start S3 Key Prefix VPCCIDR: default: VPC CIDR VPCID: default: VPC ID Parameters: ADServer1InstanceType: AllowedValues: - t2.large - t3.large - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge Default: m5.xlarge Description: Amazon EC2 instance type for the first Active Directory instance 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 for the first Active Directory server located in Availability Zone 1 Type: String ADServer2InstanceType: AllowedValues: - t2.large - t3.large - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge Default: m5.xlarge Description: Amazon EC2 instance type for the second Active Directory instance 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 for the second Active Directory server located in Availability Zone 2 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 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: Admin Description: User name for the account that will be added as Domain Administrator. This is separate from the default "Administrator" account MaxLength: '25' MinLength: '5' Type: String DomainDNSName: AllowedPattern: '[a-zA-Z0-9\-]+\..+' Default: example.com Description: Fully qualified domain name (FQDN) of the forest root domain e.g. example.com MaxLength: '255' MinLength: '2' Type: String DomainNetBIOSName: AllowedPattern: '[a-zA-Z0-9\-]+' Default: example Description: 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 KeyPairName: Description: Public/private key pairs allow you to securely connect to your instance after it launches Type: AWS::EC2::KeyPair::KeyName PrivateSubnet1ID: Description: ID of the private subnet 1 in Availability Zone 1 (e.g., subnet-a0246dcd) Type: AWS::EC2::Subnet::Id PrivateSubnet2ID: Description: ID of the private subnet 2 in Availability Zone 2 (e.g., subnet-a0246dcd) Type: AWS::EC2::Subnet::Id QSS3BucketName: AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$ 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 QSS3KeyPrefix: AllowedPattern: ^[0-9a-zA-Z-/]*$ ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). 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 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 VPCID: Description: ID of the VPC (e.g., vpc-0343606e) Type: AWS::EC2::VPC::Id WINFULLBASE: Type: 'AWS::SSM::Parameter::Value' Default: '/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-Base' Rules: SubnetsInVPC: Assertions: - Assert: !EachMemberIn - !ValueOfAll - AWS::EC2::Subnet::Id - VpcId - !RefAll 'AWS::EC2::VPC::Id' AssertDescription: All subnets must in the VPC CheckSupportedInstances: RuleCondition: !Or - !Contains - - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - !Ref 'ADServer1InstanceType' - !Contains - - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - !Ref 'ADServer2InstanceType' Assertions: - Assert: !Not - !Contains - - eu-west-3 - !Ref 'AWS::Region' AssertDescription: M4 instances are not available in the Paris region Conditions: GovCloudCondition: !Equals - !Ref 'AWS::Region' - us-gov-west-1 Resources: QuickStartLogs: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/Quick_Start/${AWS::StackName}' RetentionInDays: 30 DHCPOptions: Type: AWS::EC2::DHCPOptions DependsOn: - DomainController1 - DomainController2 Properties: DomainName: !Ref 'DomainDNSName' DomainNameServers: - !Ref 'ADServer1PrivateIP' - !Ref 'ADServer2PrivateIP' Tags: - Key: Domain Value: !Ref 'DomainDNSName' VPCDHCPOptionsAssociation: Type: AWS::EC2::VPCDHCPOptionsAssociation Properties: VpcId: !Ref 'VPCID' DhcpOptionsId: !Ref 'DHCPOptions' AWSQuickstartActiveDirectoryDS: Type: AWS::SSM::Document Properties: DocumentType: Automation Content: schemaVersion: "0.3" description: "Deploy AD with SSM Automation" # Role that is utilized to perform the steps within the Automation Document. In this case to be able to Signal CFN and Describe Instances. assumeRole: "{{AutomationAssumeRole}}" # Gathering parameters needed to configure DCs in the Quick Start parameters: ADServer1NetBIOSName: default: "DC1" description: "NetBIOS name of the first Active Directory server (up to 15 characters)" type: "String" ADServer1PrivateIP: default: "10.0.0.10" description: "Fixed private IP for the first Active Directory server located in Availability Zone 1" type: "String" ADServer2NetBIOSName: default: "DC2" description: "NetBIOS name of the first Active Directory server (up to 15 characters)" type: "String" ADServer2PrivateIP: default: "10.0.32.10" description: "Fixed private IP for the first Active Directory server located in Availability Zone 1" type: "String" VPCCIDR: default: '10.0.0.0/16' description: "CIDR block for private subnet 1 located in Availability Zone 1." type: "String" ADAdminSecParamName: description: "AWS Secrets Parameter Name that has Password and User namer for the domain administrator." type: "String" ADAltUserSecParamName: description: "AWS Secrets Parameter Name for the account that will be added as Domain Administrator. This is separate from the default Administrator account" type: "String" RestoreModeSecParamName: description: "AWS Secrets Parameter Name for the Restore Mode Password" type: "String" DomainDNSName: default: "example.com" description: "Fully qualified domain name (FQDN) of the forest root domain e.g. example.com" type: "String" DomainNetBIOSName: default: "example" description: "NetBIOS name of the domain (up to 15 characters) for users of earlier versions of Windows e.g. EXAMPLE" type: "String" 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" 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" 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: # This step grabs the Instance IDs for both nodes that will be configured as DCs in the Quick Start and Instance IDs for the for next steps. - name: "dcsInstanceIds" action: aws:executeAwsApi onFailure: "step:signalfailure" nextStep: "dcsInstallDscModules" inputs: Service: ec2 Api: DescribeInstances Filters: - Name: "tag:Name" Values: [ "{{ADServer1NetBIOSName}}","{{ADServer2NetBIOSName}}" ] - Name: "tag:aws:cloudformation:stack-name" Values: ["{{StackName}}"] - Name: "instance-state-name" Values: [ "running" ] outputs: - Name: InstanceIds Selector: "$.Reservations..Instances..InstanceId" Type: "StringList" # Installs needed Powershell DSC Modules and components on both nodes. - name: "dcsInstallDscModules" action: "aws:runCommand" onFailure: "step:signalfailure" nextStep: "dcsLCMConfig" inputs: DocumentName: "AWS-RunRemoteScript" InstanceIds: - "{{dcsInstanceIds.InstanceIds}}" CloudWatchOutputConfig: CloudWatchOutputEnabled: "true" CloudWatchLogGroupName: !Ref 'QuickStartLogs' Parameters: sourceType: "S3" sourceInfo: !Sub ['{"path": "https://${QSS3Region}.amazonaws.com/{{QSS3BucketName}}/{{QSS3KeyPrefix}}scripts/install-ad-modules.ps1"}', {QSS3Region: !If [GovCloudCondition, s3-us-gov-west-1, s3]}] commandLine: "./install-ad-modules.ps1" # Configures Local Configuration Manager on each of the nodes. - name: "dcsLCMConfig" action: "aws:runCommand" onFailure: "step:signalfailure" nextStep: "dc1InstanceId" inputs: DocumentName: "AWS-RunRemoteScript" InstanceIds: - "{{dcsInstanceIds.InstanceIds}}" CloudWatchOutputConfig: CloudWatchOutputEnabled: "true" CloudWatchLogGroupName: !Ref 'QuickStartLogs' Parameters: sourceType: "S3" sourceInfo: !Sub ['{"path": "https://${QSS3Region}.amazonaws.com/{{QSS3BucketName}}/{{QSS3KeyPrefix}}scripts/LCM-Config.ps1"}', {QSS3Region: !If [GovCloudCondition, s3-us-gov-west-1, s3]}] commandLine: "./LCM-Config.ps1" # This step grabs the Instance ID for the node that will be configured as the first DC in the new domain. - name: "dc1InstanceId" action: aws:executeAwsApi onFailure: "step:signalfailure" nextStep: "createDC1Mof" inputs: Service: ec2 Api: DescribeInstances Filters: - Name: "tag:Name" Values: [ "{{ADServer1NetBIOSName}}" ] - 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" # Generates MOF file on first DC Node to be processed by LCM. - name: "createDC1Mof" action: "aws:runCommand" onFailure: "step:signalfailure" nextStep: "configDC1" inputs: DocumentName: "AWS-RunRemoteScript" InstanceIds: - "{{dc1InstanceId.InstanceId}}" CloudWatchOutputConfig: CloudWatchOutputEnabled: "true" CloudWatchLogGroupName: !Ref 'QuickStartLogs' Parameters: sourceType: "S3" sourceInfo: !Sub ['{"path": "https://${QSS3Region}.amazonaws.com/{{QSS3BucketName}}/{{QSS3KeyPrefix}}scripts/ConfigDC1.ps1"}', {QSS3Region: !If [GovCloudCondition, s3-us-gov-west-1, s3]}] commandLine: "./ConfigDC1.ps1 -ADServer1NetBIOSName {{ADServer1NetBIOSName}} -DomainNetBIOSName {{DomainNetBIOSName}} -DomainDNSName {{DomainDNSName}} -ADAdminSecParam {{ADAdminSecParamName}} -ADAltUserSecParam {{ADAltUserSecParamName}} -RestoreModeSecParam {{RestoreModeSecParamName}} -SiteName {{global:REGION}} -VPCCIDR {{VPCCIDR}}" # Kicks off DSC Configuration and loops\reboots until Node matches Configuration defined in MOF file. - name: "configDC1" action: aws:runCommand onFailure: "step:signalfailure" nextStep: "dc2InstanceId" inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - "{{dc1InstanceId.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 { 'Completed' } } Start-DscConfiguration 'C:\AWSQuickstart\ConfigDC1' -Wait -Verbose -Force DscStatusCheck # This step grabs the Instance ID for the node that will be configured as the second DC in the new domain. - name: "dc2InstanceId" action: aws:executeAwsApi onFailure: "step:signalfailure" nextStep: "createDC2Mof" inputs: Service: ec2 Api: DescribeInstances Filters: - Name: "tag:Name" Values: [ "{{ADServer2NetBIOSName}}" ] - 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" # Generates MOF file on second DC Node to be processed by LCM. - name: "createDC2Mof" action: "aws:runCommand" onFailure: "step:signalfailure" nextStep: "configDC2" inputs: DocumentName: "AWS-RunRemoteScript" InstanceIds: - "{{dc2InstanceId.InstanceId}}" CloudWatchOutputConfig: CloudWatchOutputEnabled: "true" CloudWatchLogGroupName: !Ref 'QuickStartLogs' Parameters: sourceType: "S3" sourceInfo: !Sub ['{"path": "https://${QSS3Region}.amazonaws.com/{{QSS3BucketName}}/{{QSS3KeyPrefix}}scripts/ConfigDC2.ps1"}', {QSS3Region: !If [GovCloudCondition, s3-us-gov-west-1, s3]}] commandLine: "./ConfigDC2.ps1 -ADServer2NetBIOSName {{ADServer2NetBIOSName}} -DomainNetBIOSName {{DomainNetBIOSName}} -DomainDNSName {{DomainDNSName}} -ADServer1PrivateIP {{ADServer1PrivateIP}} -ADAdminSecParam {{ADAdminSecParamName}}" # Kicks off DSC Configuration and loops\reboots until Node matches Configuration defined in MOF file. - name: "configDC2" action: aws:runCommand onFailure: "step:signalfailure" nextStep: "DnsConfig" inputs: DocumentName: AWS-RunPowerShellScript InstanceIds: - "{{dc2InstanceId.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 { 'Completed' } } Start-DscConfiguration 'C:\AWSQuickstart\ConfigDC2' -Wait -Verbose -Force DscStatusCheck # Ensure that AD servers point to themselves for DNS - name: "DnsConfig" action: "aws:runCommand" onFailure: "step:signalfailure" inputs: DocumentName: "AWS-RunRemoteScript" InstanceIds: - "{{dc2InstanceId.InstanceId}}" CloudWatchOutputConfig: CloudWatchOutputEnabled: "true" CloudWatchLogGroupName: !Ref 'QuickStartLogs' Parameters: sourceType: S3 sourceInfo: !Sub ['{"path": "https://${QSS3Region}.amazonaws.com/{{QSS3BucketName}}/{{QSS3KeyPrefix}}scripts/Dns-Config.ps1"}', {QSS3Region: !If [GovCloudCondition, s3-us-gov-west-1, s3]}] commandLine: "./Dns-Config.ps1 -ADServer1NetBIOSName {{ADServer1NetBIOSName}} -ADServer2NetBIOSName {{ADServer2NetBIOSName}} -ADServer1PrivateIP {{ADServer1PrivateIP}} -ADServer2PrivateIP {{ADServer2PrivateIP}} -DomainDNSName {{DomainDNSName}} -ADAdminSecParam {{ADAdminSecParamName}}" # 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: "DomainController2" StackName: "{{StackName}}" Status: SUCCESS UniqueId: "{{dc2InstanceId.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: "DomainController2" StackName: "{{StackName}}" Status: FAILURE UniqueId: "{{dc2InstanceId.InstanceId}}" AWSQuickstartADDSRole: Type: AWS::IAM::Role Properties: Policies: - PolicyDocument: Version: '2012-10-17' Statement: - Action: - s3:GetObject Resource: !Sub 'arn:${AWS::Partition}:s3:::${QSS3BucketName}/${QSS3KeyPrefix}*' Effect: Allow PolicyName: aws-quick-start-s3-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: - ec2:DescribeInstances - ec2:DescribeInstanceStatus - ssm:* Resource: '*' PolicyName: AD-SSM-Automation Path: / AssumeRolePolicyDocument: Statement: - Action: - sts:AssumeRole Principal: Service: - ec2.amazonaws.com - ssm.amazonaws.com Effect: Allow Version: '2012-10-17' ADSsmPassRolePolicy: Type: AWS::IAM::Policy Properties: PolicyName: AD-SSM-PassRole PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - iam:PassRole Resource: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${AWSQuickstartADDSRole}' Roles: - !Ref 'AWSQuickstartADDSRole' ADServerRole: Type: AWS::IAM::Role Properties: Policies: - PolicyDocument: Version: '2012-10-17' Statement: - Action: - s3:GetObject Resource: !Sub 'arn:${AWS::Partition}:s3:::${QSS3BucketName}/${QSS3KeyPrefix}*' Effect: Allow PolicyName: aws-quick-start-s3-policy - PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - secretsmanager:GetSecretValue - secretsmanager:DescribeSecret Resource: - !Ref 'ADAdminSecrets' - !Ref 'RestoreModeSecrets' - !Ref 'ADAltUserSecrets' - Effect: Allow Action: - ssm:StartAutomationExecution Resource: '*' PolicyName: AD-SSM-Secrets - PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - iam:PassRole Resource: !Sub 'arn:aws:iam::${AWS::AccountId}:role/${AWSQuickstartADDSRole}' PolicyName: AD-SSM-PassRole Path: / ManagedPolicyArns: - !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonEC2RoleforSSM' AssumeRolePolicyDocument: Statement: - Action: - sts:AssumeRole Principal: Service: - ec2.amazonaws.com Effect: Allow Version: '2012-10-17' ADServerProfile: Type: AWS::IAM::InstanceProfile Properties: Roles: - !Ref 'ADServerRole' Path: / ADAdminSecrets: Type: AWS::SecretsManager::Secret Properties: Name: !Sub 'ADAdministratorSecret-${AWS::StackName}' Description: Administrator Password for AD Quick Start GenerateSecretString: SecretStringTemplate: '{"username": "Administrator"}' GenerateStringKey: "password" PasswordLength: 30 ExcludeCharacters: '"@/\' RestoreModeSecrets: Type: AWS::SecretsManager::Secret Properties: Name: !Sub 'RestoreModeSecrets-${AWS::StackName}' Description: Restore Mode Password for AD Quick Start GenerateSecretString: SecretStringTemplate: '{"username": "Administrator"}' GenerateStringKey: "password" PasswordLength: 30 ExcludeCharacters: '"@/\' ADAltUserSecrets: Type: AWS::SecretsManager::Secret Properties: Name: !Sub 'ADAltUserSecrets-${AWS::StackName}' Description: Alternate AD Admin User from AD Quick Start SecretString: !Sub '{ "username" : "${DomainAdminUser}", "password" : "${DomainAdminPassword}" }' DomainController1: Type: AWS::EC2::Instance Properties: ImageId: !Ref 'WINFULLBASE' IamInstanceProfile: !Ref 'ADServerProfile' InstanceType: !Ref 'ADServer1InstanceType' SubnetId: !Ref 'PrivateSubnet1ID' Tags: - Key: Name Value: !Ref 'ADServer1NetBIOSName' BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp2 SecurityGroupIds: - !Ref 'DomainControllersSG' PrivateIpAddress: !Ref 'ADServer1PrivateIP' KeyName: !Ref 'KeyPairName' DomainController2: Type: AWS::EC2::Instance DependsOn: DomainController1 CreationPolicy: ResourceSignal: Timeout: PT60M Count: 1 Properties: ImageId: !Ref 'WINFULLBASE' IamInstanceProfile: !Ref 'ADServerProfile' InstanceType: !Ref 'ADServer2InstanceType' SubnetId: !Ref 'PrivateSubnet2ID' Tags: - Key: Name Value: !Ref 'ADServer2NetBIOSName' BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp2 SecurityGroupIds: - !Ref 'DomainControllersSG' PrivateIpAddress: !Ref 'ADServer2PrivateIP' KeyName: !Ref 'KeyPairName' UserData: !Base64 Fn::Join: - '' - - "\n" - 'Start-SSMAutomationExecution -DocumentName ' - !Sub '"${AWSQuickstartActiveDirectoryDS}"' - ' -Parameter @{' - '"ADServer1NetBIOSName"=' - !Sub '"${ADServer1NetBIOSName}"' - ';"ADServer2NetBIOSName"=' - !Sub '"${ADServer2NetBIOSName}"' - ';"ADServer1PrivateIP"=' - !Sub '"${ADServer1PrivateIP}"' - ';"ADServer2PrivateIP"=' - !Sub '"${ADServer2PrivateIP}"' - ';"DomainDNSName"=' - !Sub '"${DomainDNSName}"' - ';"DomainNetBIOSName"=' - !Sub '"${DomainNetBIOSName}"' - ';"VPCCIDR"=' - !Sub '"${VPCCIDR}"' - ';"QSS3BucketName"=' - !Sub '"${QSS3BucketName}"' - ';"QSS3KeyPrefix"=' - !Sub '"${QSS3KeyPrefix}"' - ';"ADAdminSecParamName"=' - !Sub '"${ADAdminSecrets}"' - ';"ADAltUserSecParamName"=' - !Sub '"${ADAltUserSecrets}"' - ';"RestoreModeSecParamName"=' - !Sub '"${RestoreModeSecrets}"' - ';"StackName"=' - !Sub '"${AWS::StackName}"' - ';"AutomationAssumeRole"=' - !Sub '"arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${AWSQuickstartADDSRole}"' - '}' - "\n" - "\n" DomainControllersSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Domain Controllers Security Group VpcId: Ref: VPCID SecurityGroupIngress: - IpProtocol: tcp FromPort: 5985 ToPort: 5985 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 53 ToPort: 53 CidrIp: !Ref VPCCIDR - IpProtocol: udp FromPort: 53 ToPort: 53 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 3389 ToPort: 3389 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 445 ToPort: 445 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 139 ToPort: 139 CidrIp: !Ref VPCCIDR - IpProtocol: icmp FromPort: -1 ToPort: -1 CidrIp: !Ref VPCCIDR - IpProtocol: udp FromPort: 123 ToPort: 123 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 135 ToPort: 135 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 9389 ToPort: 9389 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: udp FromPort: 138 ToPort: 138 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 445 ToPort: 445 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: udp FromPort: 445 ToPort: 445 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: udp FromPort: 464 ToPort: 464 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 464 ToPort: 464 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 49152 ToPort: 65535 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: udp FromPort: 49152 ToPort: 65535 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 389 ToPort: 389 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: udp FromPort: 389 ToPort: 389 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 636 ToPort: 636 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 3268 ToPort: 3268 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 3269 ToPort: 3269 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 9389 ToPort: 9389 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 88 ToPort: 88 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: udp FromPort: 88 ToPort: 88 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: udp FromPort: 5355 ToPort: 5355 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: udp FromPort: 137 ToPort: 137 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 139 ToPort: 139 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: tcp FromPort: 5722 ToPort: 5722 SourceSecurityGroupId: !Ref DomainMembersSG - IpProtocol: icmp FromPort: -1 ToPort: -1 SourceSecurityGroupId: !Ref DomainMembersSG DomainMembersSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Domain Members VpcId: !Ref VPCID SecurityGroupIngress: - IpProtocol: tcp FromPort: 5985 ToPort: 5985 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 3389 ToPort: 3389 CidrIp: !Ref VPCCIDR - IpProtocol: tcp FromPort: 53 ToPort: 53 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: udp FromPort: 53 ToPort: 53 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: tcp FromPort: 53 ToPort: 53 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: udp FromPort: 53 ToPort: 53 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: tcp FromPort: 49152 ToPort: 65535 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: udp FromPort: 49152 ToPort: 65535 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: tcp FromPort: 49152 ToPort: 65535 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: udp FromPort: 49152 ToPort: 65535 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: tcp FromPort: 88 ToPort: 88 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: udp FromPort: 88 ToPort: 88 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: tcp FromPort: 88 ToPort: 88 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: udp FromPort: 88 ToPort: 88 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: tcp FromPort: 445 ToPort: 445 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: udp FromPort: 445 ToPort: 445 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: tcp FromPort: 445 ToPort: 445 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: udp FromPort: 445 ToPort: 445 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: tcp FromPort: 389 ToPort: 389 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: udp FromPort: 389 ToPort: 389 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: tcp FromPort: 389 ToPort: 389 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: udp FromPort: 389 ToPort: 389 CidrIp: !Sub ${ADServer2PrivateIP}/32 - IpProtocol: tcp FromPort: 636 ToPort: 636 CidrIp: !Sub ${ADServer1PrivateIP}/32 - IpProtocol: tcp FromPort: 636 ToPort: 636 CidrIp: !Sub ${ADServer2PrivateIP}/32 DCSecurityGroupIngress: Type: AWS::EC2::SecurityGroupIngress Properties: Description: Security Group Rule between Domain Controllers GroupId: !Ref DomainControllersSG IpProtocol: '-1' FromPort: -1 ToPort: -1 SourceSecurityGroupId: !Ref DomainControllersSG Outputs: DomainAdmin: Value: !Join - '' - - !Ref 'DomainNetBIOSName' - \ - !Ref 'DomainAdminUser' Description: Domain administrator account DomainMemberSGID: Value: !Ref 'DomainMembersSG' Description: Domain Member Security Group ID ADSecretsArn: Value: !Ref 'ADAltUserSecrets' Description: Alternate AD User Secrets ARN DC1InstanceId: Value: !Ref 'DomainController1' Description: DomainController 1 instance ID DC2InstanceId: Value: !Ref 'DomainController2' Description: DomainController 2 instance ID