AWSTemplateFormatVersion: '2010-09-09' Description: >- (0004) - This template creates and installs a Windows Server 2012 based application server for testing purposes into a subnet inside a VPC. **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-1tsaami1r) Metadata: cfn-lint: config: ignore_checks: - W2001 - W4002 - W9002 - W9003 - W9006 - E9007 - E9010 Parameters: KeyPairName: Description: Public/private key pairs allow you to securely connect to your instance after it launches Type: AWS::EC2::KeyPair::KeyName AppServerInstanceType: Description: Amazon EC2 instance type for the 1st WSFC Node Type: String Default: m3.xlarge AllowedValues: - m1.large - m3.xlarge - m2.4xlarge ConstraintDescription: Only EBS Optimized instance types m1.large, m3.xlarge, m2.4xlarge allowed DomainDNSName: Description: Fully qualified domain name (FQDN) of the forest root domain e.g. example.com Type: String Default: example.com MinLength: '3' MaxLength: '25' AllowedPattern: '[a-zA-Z0-9\-]+\..+' DomainNetBIOSName: Description: NetBIOS name of the domain (upto 15 characters) for users of earlier versions of Windows e.g. CORP Type: String Default: example MinLength: '1' MaxLength: '15' AllowedPattern: '[a-zA-Z0-9\-]+' AppServerNetBIOSName: Description: NetBIOS name of the 1st WSFC Node (up to 15 characters) Type: String Default: SQLClient MinLength: '1' MaxLength: '15' AllowedPattern: '[a-zA-Z0-9\-]+' DomainAdminUser: Description: User name for an existing domain admin account in Active Directory. Type: String Default: StackAdmin MinLength: '5' MaxLength: '25' AllowedPattern: '[a-zA-Z0-9]*' DomainAdminPassword: Description: Password for the domain admin user. Type: String MinLength: '8' MaxLength: '32' NoEcho: 'true' ADServer1PrivateIp: Description: Fixed private IP for the first Active Directory server located in AZ1 Type: String Default: 10.0.0.10 ADServer2PrivateIp: Description: Fixed private IP for the second Active Directory serverr located in AZ2 Type: String Default: 10.0.64.10 DomainMemberSGID: Description: ID of the Domain Member Security Group (e.g., sg-7f16e910) Type: String VPC: Description: ID of the VPC (e.g., vpc-0343606e) Type: AWS::EC2::VPC::Id PrivateSubnet: Description: ID of the Subnet you want to provision the App Server into (e.g., subnet-a0246dcd) Type: AWS::EC2::Subnet::Id Mappings: AWSAMIRegionMap: AMI: WS2012R2: Windows_Server-2012-R2_RTM-English-64Bit-Base-2019.07.12 ap-northeast-1: WS2012R2: ami-06823103be2218b98 ap-northeast-2: WS2012R2: ami-050e65d9f2ec90145 ap-northeast-3: WS2012R2: ami-04dfed75117825fec ap-south-1: WS2012R2: ami-045e1f06f29929467 ap-southeast-1: WS2012R2: ami-0c322369af7718803 ap-southeast-2: WS2012R2: ami-0813db0de4ddab990 ca-central-1: WS2012R2: ami-0850dfaa3ee6f6233 eu-central-1: WS2012R2: ami-024652d0a3df40e74 eu-west-1: WS2012R2: ami-0d2f69fcc5f00c97a eu-west-2: WS2012R2: ami-0998a91bb1756752d eu-west-3: WS2012R2: ami-0d6e54e3504cc1615 sa-east-1: WS2012R2: ami-044d56b6baa621d7d us-east-1: WS2012R2: ami-094a644f1fb9e4ce3 us-east-2: WS2012R2: ami-0a1a54d8690206089 us-west-1: WS2012R2: ami-094dcbdb1aa24c8da us-west-2: WS2012R2: ami-0f8967b5f815400c0 Resources: AppServerWaitCondition: Type: AWS::CloudFormation::WaitCondition DependsOn: AppServer Properties: Handle: !Ref 'AppServerWaitHandle' Timeout: '3500' AppServerWaitHandle: Type: AWS::CloudFormation::WaitConditionHandle AppServer: Type: AWS::EC2::Instance Metadata: AWS::CloudFormation::Init: configSets: config: - CFNsetup - renameandjoin - finalize CFNsetup: files: c:\cfn\cfn-hup.conf: content: !Join - '' - - "[main]\n" - stack= - !Ref 'AWS::StackId' - "\n" - region= - !Ref 'AWS::Region' - "\n" c:\cfn\hooks.d\cfn-auto-reloader.conf: content: !Join - '' - - "[cfn-auto-reloader-hook]\n" - "triggers=post.update\n" - "path=Resources.AppServer.Metadata.AWS::CloudFormation::Init\n" - 'action=cfn-init.exe -v -s ' - !Ref 'AWS::StackId' - ' -r AppServer' - ' --region ' - !Ref 'AWS::Region' - "\n" services: windows: cfn-hup: enabled: 'true' ensureRunning: 'true' files: - c:\cfn\cfn-hup.conf - c:\cfn\hooks.d\cfn-auto-reloader.conf renameandjoin: files: C:\cfn\scripts\RenameComputer.ps1: content: !Join - '' - - param ($name) - "\n" - Rename-Computer $name - "\n" - Restart-Computer C:\cfn\scripts\JoinComputer.ps1: content: !Join - '' - - '$admin_pwd = convertto-securestring ' - !Ref 'DomainAdminPassword' - ' -asplaintext -force ' - "\n" - $admincreds = New-Object System.Management.Automation.PSCredential (" - !Ref 'DomainNetBIOSName' - \ - !Ref 'DomainAdminUser' - '"' - ',$admin_pwd)' - "\n" - Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses (" - !Ref 'ADServer1PrivateIp' - '","' - !Ref 'ADServer2PrivateIp' - '")' - "\n" - 'Add-Computer -Credential $admincreds -DomainName ' - !Ref 'DomainDNSName' - "\n" - Restart-Computer - "\n" commands: 1-execute-powershell-script-RenameComputer: command: !Join - '' - - 'powershell.exe ' - -ExecutionPolicy - ' RemoteSigned' - ' C:\cfn\scripts\RenameComputer.ps1 ' - !Ref 'AppServerNetBIOSName' waitAfterCompletion: forever 2-execute-powershell-script-JoinComputer: command: !Join - '' - - 'powershell.exe ' - -ExecutionPolicy - ' RemoteSigned' - ' C:\cfn\scripts\JoinComputer.ps1' waitAfterCompletion: forever finalize: files: C:\cfn\scripts\DownloadBlasterApp.ps1: content: !Join - '' - - $zipfilename = "C:\cfn\scripts\SQLBlaster_Demo.zip" - "\n" - $destination = "C:\Users\Default\Desktop" - "\n" - 'import-module BitsTransfer ' - "\n" - 'Start-BitsTransfer ' - -Source https://s3.amazonaws.com/aws-quickstart/quickstart-microsoft-sql/scripts/SQLBlaster_Demo.zip -Destination "$zipfilename" - "\n" - if(test-path($zipfilename)) - "\n" - '{' - "\n" - '[Reflection.Assembly]::LoadWithPartialName( "System.IO.Compression.FileSystem" )' - "\n" - '[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfilename, $destination)' - "\n" - '}' - "\n" C:\cfn\scripts\AddUserToGroup.ps1: content: !Join - '' - - Param( - "\n" - '[Parameter(Mandatory=$True)]' - "\n" - '[string]$ServerName,' - "\n" - '[Parameter(Mandatory=$True)]' - "\n" - '[string]$GroupName,' - "\n" - '[Parameter(Mandatory=$True)]' - "\n" - '[string]$DomainNetBIOSName,' - "\n" - '[Parameter(Mandatory=$True)]' - "\n" - '[string]$UserName' - "\n" - ) - $de = [ADSI]"WinNT://$ServerName/$GroupName,group" - "\n" - $de.psbase.Invoke("Add",([ADSI]"WinNT://$DomainNetBIOSName/$UserName").path) - "\n" commands: 1-execute-powershell-script-DownloadBlasterApp: command: !Join - '' - - 'powershell.exe ' - -ExecutionPolicy - ' RemoteSigned' - ' C:\cfn\scripts\DownloadBlasterApp.ps1' waitAfterCompletion: '0' 2-execute-powershell-script-AddUserToGroup: command: !Join - '' - - 'powershell.exe ' - -ExecutionPolicy - ' RemoteSigned' - ' C:\cfn\scripts\AddUserToGroup.ps1 -UserName ' - !Ref 'DomainAdminUser' - ' -ServerName ' - !Ref 'AppServerNetBIOSName' - ' -DomainNetBIOSName ' - !Ref 'DomainNetBIOSName' - ' -GroupName "Administrators"' - "\n" waitAfterCompletion: '0' 3-signal-success: command: !Join - '' - - cfn-signal.exe -e 0 " - !Ref 'AppServerWaitHandle' - '"' Properties: ImageId: !FindInMap - AWSAMIRegionMap - !Ref 'AWS::Region' - WS2012R2 InstanceType: !Ref 'AppServerInstanceType' SubnetId: !Ref 'PrivateSubnet' EbsOptimized: true Tags: - Key: Name Value: !Ref 'AppServerNetBIOSName' BlockDeviceMappings: - DeviceName: /dev/sda1 Ebs: VolumeSize: 100 VolumeType: gp2 SecurityGroupIds: - !Ref 'DomainMemberSGID' KeyName: !Ref 'KeyPairName' UserData: !Base64 Fn::Join: - '' - - " Outputs: DomainAdmin: Value: !Join - '' - - !Ref 'DomainNetBIOSName' - \ - !Ref 'DomainAdminUser' Description: Domain administrator account LocalAdmin: Value: Administrator Description: Please retrieve Administrator password of the instance AppServerNetBIOSName: Value: !Ref 'AppServerNetBIOSName' Description: NetBIOS name of the App Server