AWSTemplateFormatVersion: '2010-09-09' Description: >- This template creates 2 Windows 2019 Active Directory Domain Controllers into private subnets in separate Availability Zones inside a VPC. It then creates Directory Service (AD Connector), registers it for Amazon WorkSpaces, then launches WorkSpaces for a user. Lastly, it launches a FreeRADIUS server that's used to enable MFA on the WorkSpace. Ensure the selected Availability Zones are supported by WorkSpaces. **WARNING** This template creates Amazon EC2 Windows instances, WorkSpace, RDS Cluster, and other related resources. You'll be billed for the AWS resources used if you create a stack from this template. (qs-1t9sl8qtu) Metadata: QuickStartDocumentation: EntrypointName: 'Parameters for deploying self-managed AD into a new VPC.' Order: '1' cfn-lint: config: ignore_checks: - E9101 - W9006 - E0002 - W9001 ignore_reason: - "Execution part SSM Automation" - "Referenced file does not have parameter, " AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Network configuration Parameters: - AvailabilityZones - NumberOfAZs - VPCCIDR - DHCPOptionSet - PrivateSubnet1CIDR - PrivateSubnet2CIDR - PrivateSubnet3CIDR - PublicSubnet1CIDR - PublicSubnet2CIDR - PublicSubnet3CIDR - Label: default: Amazon EC2 configuration Parameters: - ADServer1InstanceType - ADServer1NetBIOSName - ADServer1PrivateIP - ADServer2InstanceType - ADServer2NetBIOSName - ADServer2PrivateIP - DataDriveSizeGiB - KeyPairName - RADIUSServerInstanceType - Label: default: Microsoft AD Domain Services configuration Parameters: - DomainAdminUser - DomainAdminPassword - DomainDNSName - DomainNetBIOSName - CreateDefaultOUs - TombstoneLifetime - DeletedObjectLifetime - Label: default: Microsoft AD Certificate Services configuration Parameters: - PKI - CaServerInstanceType - CaDataDriveSizeGiB - OrCaServerNetBIOSName - EntCaServerNetBIOSName - CaKeyLength - CaHashAlgorithm - OrCaValidityPeriodUnits - CaValidityPeriodUnits - UseS3ForCRL - S3CRLBucketName - Label: default: Microsoft RD Gateway configuration Parameters: - NumberOfRDGWHosts - RDGWInstanceType - RDGWCIDR - Label: default: WorkSpaces and WorkSpaces directory configuration. Parameters: - DomainUser - FirstName - LastName - EnableSelfService - EnableWorkDocs - Tenancy - BundleId - ComputeTypeName - RunningMode - UserVolumeEncryptionEnabled - RootVolumeEncryptionEnabled - VolumeEncryptionKey - UserVolumeSizeGib - RootVolumeSizeGib - Label: default: RADIUS database and server configuration Parameters: - LinOTPDBName - LinOTPAdminPassword - LinOTPReamlName - RADIUSServerInstanceType - Label: default: AWS solution configuration Parameters: - QSS3BucketName - QSS3BucketRegion - QSS3KeyPrefix - Label: default: SNS/KMS configurations Parameters: - QuickStartAdminEmail 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 AvailabilityZones: default: Availability Zones CaDataDriveSizeGiB: default: CA data drive size CaHashAlgorithm: default: CA hash algorithm CaKeyLength: default: CA key length CaServerInstanceType: default: CA instance type CaValidityPeriodUnits: default: Enterprise root or subordinate CA Certificate validity period CreateDefaultOUs: default: Create default OUs DHCPOptionSet: default: Create DHCP options set DataDriveSizeGiB: default: SYSVOL, NTDS, and data drive size DeletedObjectLifetime: default: Set new deleted objects lifetime DomainAdminPassword: default: Alternate domain admin password DomainAdminUser: default: Alternate domain admin user name DomainDNSName: default: Domain DNS name DomainNetBIOSName: default: Domain NetBIOS name EntCaServerNetBIOSName: default: Enterprise root or subordinate CA NetBIOS name KeyPairName: default: Key pair name NumberOfAZs: default: Number of Availability Zones NumberOfRDGWHosts: default: Number of RDGW hosts OrCaServerNetBIOSName: default: Offline root CA NetBIOS name OrCaValidityPeriodUnits: default: Offline root CA Certificate validity period PKI: default: Deploy PKI infrastructure PrivateSubnet1CIDR: default: Private subnet 1 CIDR PrivateSubnet2CIDR: default: Private subnet 2 CIDR PrivateSubnet3CIDR: default: (Optional) Private subnet 3 CIDR PublicSubnet1CIDR: default: Public subnet 1 CIDR PublicSubnet2CIDR: default: Public subnet 2 CIDR PublicSubnet3CIDR: default: (Optional) Public subnet 3 CIDR 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-freeradius-mfa-workspaces/ 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' RDGWCIDR: default: Allowed RD Gateway external access CIDR RDGWInstanceType: default: RD Gateway instance type DomainUser: default: Normal domain user to launch WorkSpace FirstName: default: WorkSpace user first name LastName: default: WorkSpace user last name EnableSelfService: default: Enable self-service on WorkSpace directory EnableWorkDocs: default: Enable WorkDocs on WorkSpace directory Tenancy: default: WorkSpaces VPC tenancy BundleId: default: WorkSpace bundle ID ComputeTypeName: default: 'Workspaces compute type' RunningMode: default: WorkSpaces running mode UserVolumeEncryptionEnabled: default: Encrypt WorkSpace user volume RootVolumeEncryptionEnabled: default: Encrypt WorkSpace user volume VolumeEncryptionKey: default: WorkSpace KMS key to encrypt volumes UserVolumeSizeGib: default: Size of WorkSpace user volume storage RootVolumeSizeGib: default: Size of WorkSpace root volume storage LinOTPDBName: default: Database name for LinOTP configuration S3CRLBucketName: default: CA CRL S3 bucket name TombstoneLifetime: default: Set new Tombstone lifetime UseS3ForCRL: default: Use S3 for CA CRL location VPCCIDR: default: VPC CIDR QuickStartAdminEmail: default: Admin email for notification Parameters: ADServer1InstanceType: AllowedValues: - t2.medium - t3.medium - t2.large - t3.large - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge Default: m5.large Description: Amazon EC2 instance type for first AD Domain Controller instance. Type: String ADServer1NetBIOSName: AllowedPattern: '[a-zA-Z0-9\-]+' Default: DC1-ADC Description: NetBIOS name of first AD Domain Controller (maximum of 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 first AD Domain Controller located in Availability Zone 1. Type: String ADServer2InstanceType: AllowedValues: - t2.medium - t3.medium - t2.large - t3.large - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge Default: m5.large Description: Amazon EC2 instance type for second AD Domain Controller instance. Type: String RADIUSServerInstanceType: AllowedValues: - t2.medium - t3.medium - t2.large - t3.large - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge Default: t3.large Description: Amazon EC2 instance type for RADIUS Server. Type: String ADServer2NetBIOSName: AllowedPattern: '[a-zA-Z0-9\-]+' Default: DC2-ADC Description: NetBIOS name of second AD Domain Controller (maximum of 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 second AD Domain Controller located in Availability Zone 2. Type: String ADServerEnableAdvancedAudtingandMetrics: Description: Enable advanced auditing and metrics and upload to CloudWatch using Amazon Kinesis Agent for Microsoft Windows. AllowedValues: - 'true' - 'false' Type: String Default: 'false' AvailabilityZones: Description: 'List of Availability Zones to use for subnets in VPC. Logical order is preserved and only 2 Availability Zoness are used for deployment. Choose Availability Zones supported by WorkSpaces.' Type: List CaDataDriveSizeGiB: Default: '2' Description: Size of data drive (in GiB) for the CA instance(s). Type: Number CaHashAlgorithm: AllowedValues: - SHA256 - SHA384 - SHA512 Default: SHA256 Description: CA(s) hash algorithm for signing certificates. Type: String CaKeyLength: AllowedValues: - '2048' - '4096' Default: '2048' Description: CA(s) cryptographic provider key length. Type: String CaServerInstanceType: AllowedValues: - t2.small - t3.small - t2.medium - t3.medium - t2.large - t3.large Default: t3.medium Description: Amazon EC2 instance type for CA instance(s). Type: String CaValidityPeriodUnits: Default: '5' Description: Validity period (in years). Type: String CreateDefaultOUs: AllowedValues: - 'Yes' - 'No' Default: 'No' Description: Domain elevated accounts, domain users, domain computers, domain servers, domain service accounts, and domain groups OUs. Set default users and computers containers to domain users and domain computers. Type: String DHCPOptionSet: AllowedValues: - 'Yes' - 'No' Default: 'Yes' Description: Create and apply new DHCP options set. Type: String DataDriveSizeGiB: Default: '10' Description: Size of SYSVOL and NTDS data drive (in GiB). Type: Number DeletedObjectLifetime: Default: '180' Description: Number of days before deleted object is removed from AD recycling bin (minimum is 2). Type: Number 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 account named above. Must be minimum of 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 account added as domain administrator. Separate from 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 forest root domain (example-demo.com). MaxLength: '255' MinLength: '2' Type: String DomainNetBIOSName: AllowedPattern: '[a-zA-Z0-9\-]+' Default: example Description: NetBIOS name of domain (maximum 15 characters) for users of earlier versions of Windows (example-DEMO). MaxLength: '15' MinLength: '1' Type: String EntCaServerNetBIOSName: AllowedPattern: '[a-zA-Z0-9\-]+' Default: ENTCA1 Description: NetBIOS name of enterprise root or subordinate CA server (maximum 15 characters). MaxLength: '15' MinLength: '1' Type: String KeyPairName: Description: Public/private key pairs to securely connect to your instance after it launches. Type: AWS::EC2::KeyPair::KeyName NumberOfRDGWHosts: AllowedValues: - '0' - '1' - '2' - '3' - '4' Default: '1' Description: Enter number of RD Gateway instances to create. Type: String NumberOfAZs: AllowedValues: - '2' - '3' Default: '2' Description: Number of Availability Zones to use in VPC. Choose Availability Zones supported by WorkSpaces. Ensure this matches your selections in list of Availability Zones parameter. Type: String OrCaServerNetBIOSName: AllowedPattern: '[a-zA-Z0-9\-]+' Default: ORCA1 Description: NetBIOS name of the offline root CA server (only used for two tier PKI) (maximum 15 characters). MaxLength: '15' MinLength: '1' Type: String OrCaValidityPeriodUnits: Default: '10' Description: Validity period in years (only used for two tier PKI). Type: String PKI: AllowedValues: - One-Tier - Two-Tier - 'No' Default: 'No' Description: Deploy two tier (offline root with subordinate enterprise CA) or one tier (enterprise root CA) PKI infrastructure. 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 format 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 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 format 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 PrivateSubnet3CIDR: Default: '' Description: CIDR block for private subnet 3 located in Availability Zone 3. Type: String PublicSubnet1CIDR: 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 format x.x.x.x/16-28). Default: 10.0.128.0/20 Description: CIDR Block for public subnet 1 located in Availability Zone 1. Type: String PublicSubnet2CIDR: 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 format x.x.x.x/16-28). Default: 10.0.144.0/20 Description: CIDR Block for public subnet 2 located in Availability Zone 2. Type: String PublicSubnet3CIDR: Default: '' Description: CIDR Block for public subnet 3 located in Availability Zone 3. 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-freeradius-mfa-workspaces/ 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' RDGWInstanceType: Description: Amazon EC2 instance type for RD Gateway instances. Type: String Default: t3.large AllowedValues: - t2.small - t2.medium - t2.large - t3.small - t3.medium - t3.large - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge RDGWCIDR: AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ ConstraintDescription: CIDR block parameter must be in format x.x.x.x/x. Description: Allowed CIDR Block for external access to RD Gateways. Type: String S3CRLBucketName: AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$ Default: examplebucket Description: S3 bucket name for CA CRL(s) storage. Bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It can't start or end with a hyphen (-). Type: String TombstoneLifetime: Default: '180' Description: Number of days before deleted object is removed from AD (minimum is 2). Type: Number UseS3ForCRL: AllowedValues: - 'Yes' - 'No' Default: 'No' Description: Store CA CRL(s) in an S3 bucket. 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 format x.x.x.x/16-28). Default: 10.0.0.0/16 Description: CIDR Block for VPC. Type: String ## WorkSpaces configuration DomainUser: AllowedPattern: '[a-zA-Z0-9]*' Default: JaneDoe Description: User name for AD account for launching WorkSpace. MaxLength: '25' MinLength: '5' Type: String FirstName: AllowedPattern: '[a-zA-Z0-9]*' Default: Jane Description: First name of domain user account for launching WorkSpace. MaxLength: '25' MinLength: '2' Type: String LastName: AllowedPattern: '[a-zA-Z0-9]*' Default: Doe Description: Last name of domain user account for launching WorkSpace. MaxLength: '25' MinLength: '2' Type: String EnableWorkDocs: AllowedValues: - 'true' - 'false' Default: 'false' Description: WorkDocs is enabled or disabled. If enabled and WorkDocs isn't available in the region, you'll receive an OperationNotSupportedException error. Set EnableWorkDocs to disabled and try again. Type: String EnableSelfService: AllowedValues: - 'true' - 'false' Default: 'true' Description: Self-service capabilities are enabled or disabled. Type: String Tenancy: AllowedValues: - 'DEDICATED' - 'SHARED' Default: 'SHARED' Description: WorkSpace directory is dedicated or shared. To use Bring Your Own License (BYOL) images, set this value to DEDICATED and enable your AWS account for BYOL. If your account hasn't been enabled for BYOL, you'll receive an InvalidParameterValuesException error. Type: String RootVolumeEncryptionEnabled: AllowedValues: - 'true' - 'false' Default: 'true' Description: Data stored on root volume is encrypted. Type: String UserVolumeEncryptionEnabled: AllowedValues: - 'true' - 'false' Default: 'true' Description: Data stored on user volume is encrypted. Type: String VolumeEncryptionKey: Type: String Default: alias/aws/workspaces Description: Symmetric AWS KMS key used to encrypt data stored on your WorkSpace. WorkSpaces doesn't support asymmetric KMS keys. Specify KMS key ID. RootVolumeSizeGib: Default: '80' Description: Size of user storage. Refer to Modify Volume Sizes - https://docs.aws.amazon.com/workspaces/latest/adminguide/modify-workspaces.html#change_volume_sizes. Type: Number UserVolumeSizeGib: Default: '50' Description: Size of user storage. Refer to Modify Volume Sizes - https://docs.aws.amazon.com/workspaces/latest/adminguide/modify-workspaces.html#change_volume_sizes. Type: Number BundleId: Default: 'wsb-fn373c5rw' AllowedPattern: '^wsb-[0-9a-z]{8,63}$' Description: Identifier of bundle for WorkSpace. Use DescribeWorkspaceBundles to list available bundles. Provided bundle ID is for PCoIP streaming protocol. Type: String ComputeTypeName: Default: 'PERFORMANCE' AllowedValues: - VALUE - STANDARD - POWERPRO - POWER - PERFORMANCE - GRAPHICSPRO - GRAPHICS Description: Compute type. Valid values are VALUE | STANDARD | PERFORMANCE | POWER | GRAPHICS | POWERPRO | GRAPHICSPRO. Ensure bundle ID supports compute type selected. Type: String RunningMode: Default: 'AUTO_STOP' AllowedValues: - ALWAYS_ON - AUTO_STOP Description: Choose Workspaces running mode. Type: String ## RADIUS configuration LinOTPDBName: Type: String Default: LINOTP Description: RDS database name. LinOTPAdminPassword: 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 account used to manage user enrollment and LinOTP portal. Minimum 8 characters containing letters, numbers, and symbols. MaxLength: '32' MinLength: '8' NoEcho: 'true' Type: String LinOTPReamlName: AllowedPattern: '[a-zA-Z0-9]*' Default: WSRealm Description: Realm name for LinOTP/LDAP integration. Default is WSRealm. MaxLength: '12' MinLength: '5' NoEcho: 'true' Type: String ## SNS Configuration QuickStartAdminEmail: Default: workspaces@example.com Description: 'Admin email for notifications upon successful creation.' Type: String AllowedPattern: '[^@]+@[^@]+\.[^@]+' Conditions: IncludeRDGW: !Not [!Equals [!Ref NumberOfRDGWHosts, '0']] IsTwoAz: !Equals [!Ref 'NumberOfAZs', '2'] UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] WorkSpaceEncryptRootVol: !Equals [!Ref RootVolumeEncryptionEnabled, 'true'] WorkSpaceEncryptUserVol: !Equals [!Ref UserVolumeEncryptionEnabled, 'true'] KMSVolEncrptionCheck: !And [ Condition: WorkSpaceEncryptRootVol, Condition: WorkSpaceEncryptUserVol] Rules: 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 S3CRLBucketNameValidation: RuleCondition: !And - !Equals [!Ref UseS3ForCRL, 'Yes'] - !Not [!Equals [!Ref PKI, 'No']] Assertions: - AssertDescription: CRL BucketName cannot must be valid BucketName Assert: !Not [!Equals [!Ref S3CRLBucketName, 'examplebucket']] Resources: VPCStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml' - S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: AvailabilityZones: !Join [',', !Ref 'AvailabilityZones'] NumberOfAZs: !Ref 'NumberOfAZs' PrivateSubnet1ACIDR: !Ref 'PrivateSubnet1CIDR' PrivateSubnet2ACIDR: !Ref 'PrivateSubnet2CIDR' PrivateSubnet3ACIDR: !If - IsTwoAz - !Ref 'AWS::NoValue' - !Ref 'PrivateSubnet3CIDR' PublicSubnet1CIDR: !Ref 'PublicSubnet1CIDR' PublicSubnet2CIDR: !Ref 'PublicSubnet2CIDR' PublicSubnet3CIDR: !If - IsTwoAz - !Ref 'AWS::NoValue' - !Ref 'PublicSubnet3CIDR' VPCCIDR: !Ref 'VPCCIDR' ADStack: DependsOn: VPCStack Type: AWS::CloudFormation::Stack Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-activedirectory/templates/ad-1.template.yaml' - S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: ADServer1InstanceType: !Ref 'ADServer1InstanceType' ADServer1NetBIOSName: !Ref 'ADServer1NetBIOSName' ADServer1PrivateIP: !Ref 'ADServer1PrivateIP' ADServer2InstanceType: !Ref 'ADServer2InstanceType' ADServer2NetBIOSName: !Ref 'ADServer2NetBIOSName' ADServer2PrivateIP: !Ref 'ADServer2PrivateIP' EnableAdvancedAudtingandMetrics: !Ref ADServerEnableAdvancedAudtingandMetrics DomainAdminPassword: !Ref 'DomainAdminPassword' DomainAdminUser: !Ref 'DomainAdminUser' CreateDefaultOUs: !Ref 'CreateDefaultOUs' DHCPOptionSet: !Ref DHCPOptionSet CaDataDriveSizeGiB: !Ref CaDataDriveSizeGiB CaHashAlgorithm: !Ref CaHashAlgorithm CaKeyLength: !Ref CaKeyLength CaServerInstanceType: !Ref CaServerInstanceType CaValidityPeriodUnits: !Ref CaValidityPeriodUnits OrCaServerNetBIOSName: !Ref OrCaServerNetBIOSName OrCaValidityPeriodUnits: !Ref OrCaValidityPeriodUnits PKI: !Ref PKI DataDriveSizeGiB: !Ref DataDriveSizeGiB DeletedObjectLifetime: !Ref DeletedObjectLifetime DomainDNSName: !Ref 'DomainDNSName' DomainNetBIOSName: !Ref 'DomainNetBIOSName' EntCaServerNetBIOSName: !Ref EntCaServerNetBIOSName KeyPairName: !Ref 'KeyPairName' PrivateSubnet1ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet1AID' PrivateSubnet2ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet2AID' QSS3BucketName: !Ref 'QSS3BucketName' QSS3BucketRegion: !Ref 'QSS3BucketRegion' QSS3KeyPrefix: !Sub '${QSS3KeyPrefix}submodules/quickstart-microsoft-activedirectory/' S3CRLBucketName: !Ref S3CRLBucketName TombstoneLifetime: !Ref TombstoneLifetime UseS3ForCRL: !Ref UseS3ForCRL VPCCIDR: !Ref 'VPCCIDR' VPCID: !GetAtt 'VPCStack.Outputs.VPCID' RDGWStack: Condition: IncludeRDGW DependsOn: ADStack Type: AWS::CloudFormation::Stack Properties: TemplateURL: Fn::Sub: - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-rdgateway/templates/rdgw-domain.template' - S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: DomainAdminPassword: !Ref 'DomainAdminPassword' DomainAdminUser: !Ref 'DomainAdminUser' DomainDNSName: !Ref 'DomainDNSName' DomainMemberSGID: !GetAtt 'ADStack.Outputs.DomainMemberSGID' DomainNetBIOSName: !Ref 'DomainNetBIOSName' KeyPairName: !Ref 'KeyPairName' NumberOfRDGWHosts: !Ref 'NumberOfRDGWHosts' PublicSubnet1ID: !GetAtt 'VPCStack.Outputs.PublicSubnet1ID' PublicSubnet2ID: !GetAtt 'VPCStack.Outputs.PublicSubnet2ID' QSS3BucketName: !Ref 'QSS3BucketName' QSS3BucketRegion: !Ref 'QSS3BucketRegion' QSS3KeyPrefix: !Sub '${QSS3KeyPrefix}submodules/quickstart-microsoft-rdgateway/' RDGWInstanceType: !Ref 'RDGWInstanceType' RDGWCIDR: !Ref 'RDGWCIDR' VPCID: !GetAtt 'VPCStack.Outputs.VPCID' Macro: Type: AWS::CloudFormation::Macro Properties: Name: WorkSpaceDefaultRoleMacro FunctionName: !GetAtt WSIAMFunc.Arn WSIAMFunc: Type: AWS::Lambda::Function Properties: FunctionName: !Sub ${AWS::StackName} Handler: index.handler Runtime: python3.8 Role: !GetAtt LambdaExecutionRole.Arn Code: ZipFile: | import boto3 import json import logging logger = logging.getLogger() logger.setLevel(logging.INFO) client = boto3.client('iam') def handler(event, context): try: fragment = event['fragment'] client.get_role(RoleName='workspaces_DefaultRole') resp = {'requestId': event['requestId'], 'status': 'success','fragment': fragment} return resp except client.exceptions.NoSuchEntityException: resources_to_be_modified = {} resources_to_be_modified = event['fragment']['Resources'] resources_to_be_modified['WorkspaceDefaultRole'] = {'Properties':{'RoleName':'workspaces_DefaultRole','Tags':[{'Key':'Created_By','Value':'WorkSpacesQuickstart_SC1'}],'ManagedPolicyArns':['arn:aws:iam::aws:policy/AmazonWorkSpacesServiceAccess','arn:aws:iam::aws:policy/AmazonWorkSpacesSelfServiceAccess'],'AssumeRolePolicyDocument':{'Statement':[{'Action':['sts:AssumeRole'],'Effect':'Allow','Principal':{'Service':['workspaces.amazonaws.com']}}],'Version':'2012-10-17'},'Path':'/'}} resources_to_be_modified['WorkspaceDefaultRole']['Type'] = 'AWS::IAM::Role' resources_to_be_modified['CleanUpCustomResource']['DependsOn'] = 'WorkspaceDefaultRole' event['fragment']['Resources'] = resources_to_be_modified resp = {'requestId': event['requestId'], 'status': 'success','fragment': fragment} return resp LambdaPermission: Type: AWS::Lambda::Permission Properties: Action: 'lambda:InvokeFunction' Principal: cloudformation.amazonaws.com FunctionName: !GetAtt WSIAMFunc.Arn LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / Policies: - PolicyName: Fn::Sub: ${AWS::StackName}-lambda-execution-role-policy PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: - Fn::Sub: arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/* - Effect: Allow Action: - iam:GetRole Resource: - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/* NotifyStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/notification.template.yaml' - S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: QuickStartAdminEmail: !Ref QuickStartAdminEmail WorkSpaceStack: DependsOn: - ADStack - Macro - NotifyStack Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/workspace-1.template.yaml' - S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: DomainUser: !Ref 'DomainUser' FirstName: !Ref 'FirstName' LastName: !Ref 'LastName' VPCID: !GetAtt 'VPCStack.Outputs.VPCID' PrivateSubnet1ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet1AID' PrivateSubnet2ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet2AID' ADServer1PrivateIP: !Ref 'ADServer1PrivateIP' ADServer2PrivateIP: !Ref 'ADServer2PrivateIP' BundleId: !Ref 'BundleId' DomainDNSName: !Ref 'DomainDNSName' ADServer1NetBIOSName: !Ref 'ADServer1NetBIOSName' ADServer2NetBIOSName: !Ref 'ADServer2NetBIOSName' EnableWorkDocs: !Ref 'EnableWorkDocs' EnableSelfService: !Ref 'EnableSelfService' Tenancy: !Ref 'Tenancy' ComputeTypeName: !Ref 'ComputeTypeName' RunningMode: !Ref 'RunningMode' RootVolumeSizeGib: !Ref 'RootVolumeSizeGib' UserVolumeSizeGib: !Ref 'UserVolumeSizeGib' VolumeEncryptionKey: !If [KMSVolEncrptionCheck, !Ref 'VolumeEncryptionKey', !Ref AWS::NoValue] UserVolumeEncryptionEnabled: !Ref 'UserVolumeEncryptionEnabled' RootVolumeEncryptionEnabled: !Ref 'RootVolumeEncryptionEnabled' ADAltUserSecParamName: !GetAtt 'ADStack.Outputs.ADSecretsArn' DC1InstanceId: !GetAtt 'ADStack.Outputs.DC1InstanceId' DC2InstanceId: !GetAtt 'ADStack.Outputs.DC2InstanceId' DomainControllersSGID: !GetAtt 'ADStack.Outputs.DomainControllersSGID' PrivateSubnet1CIDR: !Ref PrivateSubnet1CIDR PrivateSubnet2CIDR: !Ref PrivateSubnet2CIDR PrivateSubnet3CIDR: !Ref PrivateSubnet3CIDR PublicSubnet1CIDR: !Ref PublicSubnet1CIDR PublicSubnet2CIDR: !Ref PublicSubnet2CIDR PublicSubnet3CIDR: !Ref PublicSubnet3CIDR SNSDeliveryLambdaExecutionRoleExportName: !Sub '${AWS::StackName}-LambdaSNSPublisherRole' SNSStackStatusTopicExportName: !Sub '${AWS::StackName}-SNSStackStatusTopic' SNSDeliveryLambdaExecutionRoleExportValue: !GetAtt 'NotifyStack.Outputs.SNSDeliveryLambdaExecutionRole' SNSStackStatusTopicExportValue: !GetAtt 'NotifyStack.Outputs.SNSStackTopic' QSS3BucketName: !Ref 'QSS3BucketName' QSS3KeyPrefix: !Ref 'QSS3KeyPrefix' RadiusStack: DependsOn: - ADStack - Macro - WorkSpaceStack Type: AWS::CloudFormation::Stack Properties: TemplateURL: !Sub - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/radius-1.template.yaml' - S3Region: !If [UsingDefaultBucket, !Ref AWS::Region, !Ref QSS3BucketRegion] S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] Parameters: VPCID: !GetAtt 'VPCStack.Outputs.VPCID' PrivateSubnet1ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet1AID' PrivateSubnet2ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet2AID' PublicSubnet1ID: !GetAtt 'VPCStack.Outputs.PublicSubnet1ID' PublicSubnet2ID: !GetAtt 'VPCStack.Outputs.PublicSubnet2ID' DomainUserSecretsArn: !GetAtt 'WorkSpaceStack.Outputs.DomainUserSecretsArn' VPCCIDR: !Ref 'VPCCIDR' LinOTPDBName: !Ref 'LinOTPDBName' LinOTPAdminPassword: !Ref 'LinOTPAdminPassword' LinOTPReamlName: !Ref 'LinOTPReamlName' KeyName: !Ref 'KeyPairName' RADIUSServerInstanceType: !Ref 'RADIUSServerInstanceType' SNSDeliveryLambdaExecutionRole: !Sub '${AWS::StackName}-LambdaSNSPublisherRole' SNSStackStatusTopic: !Sub '${AWS::StackName}-SNSStackStatusTopic'