├── .gitignore ├── .gitmodules ├── .metadata ├── .nojekyll ├── .taskcat.yml ├── CODEOWNERS ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── docs ├── generated │ ├── parameters │ │ └── index.adoc │ ├── regions │ │ └── index.adoc │ └── services │ │ ├── index.adoc │ │ └── metadata.adoc ├── images │ ├── architecture_diagram.png │ ├── aws-quickstart-graphic.png │ ├── cfn_outputs.png │ ├── image1.png │ ├── image10.png │ ├── image11.png │ ├── image12.png │ ├── image13.png │ ├── image14.png │ ├── image15.png │ ├── image16.png │ ├── image17.png │ ├── image18.png │ ├── image3.png │ ├── image4.png │ ├── image5.png │ ├── image6.png │ ├── image7.png │ ├── image8.png │ └── image9.png └── partner_editable │ ├── _settings.adoc │ ├── additional_info.adoc │ ├── architecture.adoc │ ├── deploy_steps.adoc │ ├── deployment_options.adoc │ ├── faq_troubleshooting.adoc │ ├── licenses.adoc │ ├── overview_target_and_usage.adoc │ ├── pre-reqs.adoc │ ├── product_description.adoc │ ├── regions.adoc │ ├── service_limits.adoc │ └── specialized_knowledge.adoc ├── scripts ├── Archive │ ├── Install-ADFS.ps1 │ └── Install-WAP.ps1 └── Modules │ └── Module-WAPADFS │ ├── Module-WAPADFS.psd1 │ └── Module-WAPADFS.psm1 └── templates ├── wap-adfs-master.template └── wap-adfs.template /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/.gitignore -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submodules/quickstart-aws-vpc"] 2 | path = submodules/quickstart-aws-vpc 3 | url = ../../aws-quickstart/quickstart-aws-vpc.git 4 | branch = main 5 | [submodule "submodules/quickstart-microsoft-utilities"] 6 | path = submodules/quickstart-microsoft-utilities 7 | url = ../../aws-quickstart/quickstart-microsoft-utilities.git 8 | branch = main 9 | [submodule "submodules/quickstart-microsoft-rdgateway"] 10 | path = submodules/quickstart-microsoft-rdgateway 11 | url = ../../aws-quickstart/quickstart-microsoft-rdgateway.git 12 | branch = main 13 | [submodule "submodules/quickstart-microsoft-activedirectory"] 14 | path = submodules/quickstart-microsoft-activedirectory 15 | url = ../../aws-quickstart/quickstart-microsoft-activedirectory.git 16 | branch = main 17 | [submodule "docs/boilerplate"] 18 | path = docs/boilerplate 19 | url = https://github.com/aws-quickstart/quickstart-documentation-base-common.git 20 | branch = main 21 | 22 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | language_type: cloudformation 2 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/.nojekyll -------------------------------------------------------------------------------- /.taskcat.yml: -------------------------------------------------------------------------------- 1 | project: 2 | name: quickstart-microsoft-wapadfs 3 | owner: quickstart-eng@amazon.com 4 | package_lambda: false 5 | regions: 6 | - ap-northeast-1 7 | - ap-southeast-1 8 | # - ap-southeast-2 9 | - ca-central-1 10 | - eu-central-1 11 | - eu-west-1 12 | # - eu-west-2 13 | # - us-east-1 14 | # - us-west-1 15 | - us-west-2 16 | tests: 17 | wapadfs: 18 | parameters: 19 | AvailabilityZones: $[taskcat_genaz_2] 20 | DomainAdminPassword: $[taskcat_genpass_8S] 21 | KeyPairName: $[taskcat_getkeypair] 22 | QSS3BucketName: $[taskcat_autobucket] 23 | QSS3BucketRegion: $[taskcat_current_region] 24 | NumberOfRDGWHosts: '0' 25 | RDGWCIDR: 10.0.0.0/16 26 | template: ./templates/wap-adfs-master.template 27 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @davmayd @aws-quickstart/aws_quickstart_team 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at 4 | 5 | http://aws.amazon.com/apache2.0/ 6 | 7 | or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # quickstart-microsoft-wapadfs 2 | ## Deprecation Notice 3 | 4 | :x: This repository is subject to deprecation in Q4 2024. For more details, [please review this announcement](https://github.com/aws-ia/.announcements/issues/1). 5 | 6 | ## This repository has been deprecated in favor of https://github.com/aws-ia/cfn-ps-microsoft-wapadfs. 7 | ***We will archive this repository and keep it publicly available until May 1, 2024.*** 8 | -------------------------------------------------------------------------------- /docs/generated/parameters/index.adoc: -------------------------------------------------------------------------------- 1 | // placeholder 2 | -------------------------------------------------------------------------------- /docs/generated/regions/index.adoc: -------------------------------------------------------------------------------- 1 | // placeholder 2 | -------------------------------------------------------------------------------- /docs/generated/services/index.adoc: -------------------------------------------------------------------------------- 1 | // placeholder 2 | -------------------------------------------------------------------------------- /docs/generated/services/metadata.adoc: -------------------------------------------------------------------------------- 1 | // placeholder 2 | -------------------------------------------------------------------------------- /docs/images/architecture_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/architecture_diagram.png -------------------------------------------------------------------------------- /docs/images/aws-quickstart-graphic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/aws-quickstart-graphic.png -------------------------------------------------------------------------------- /docs/images/cfn_outputs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/cfn_outputs.png -------------------------------------------------------------------------------- /docs/images/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image1.png -------------------------------------------------------------------------------- /docs/images/image10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image10.png -------------------------------------------------------------------------------- /docs/images/image11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image11.png -------------------------------------------------------------------------------- /docs/images/image12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image12.png -------------------------------------------------------------------------------- /docs/images/image13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image13.png -------------------------------------------------------------------------------- /docs/images/image14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image14.png -------------------------------------------------------------------------------- /docs/images/image15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image15.png -------------------------------------------------------------------------------- /docs/images/image16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image16.png -------------------------------------------------------------------------------- /docs/images/image17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image17.png -------------------------------------------------------------------------------- /docs/images/image18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image18.png -------------------------------------------------------------------------------- /docs/images/image3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image3.png -------------------------------------------------------------------------------- /docs/images/image4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image4.png -------------------------------------------------------------------------------- /docs/images/image5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image5.png -------------------------------------------------------------------------------- /docs/images/image6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image6.png -------------------------------------------------------------------------------- /docs/images/image7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image7.png -------------------------------------------------------------------------------- /docs/images/image8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image8.png -------------------------------------------------------------------------------- /docs/images/image9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/docs/images/image9.png -------------------------------------------------------------------------------- /docs/partner_editable/_settings.adoc: -------------------------------------------------------------------------------- 1 | :quickstart-project-name: quickstart-microsoft-wapadfs 2 | :partner-product-name: Web Application Proxy and AD FS 3 | :partner-product-short-name: WAP and AD FS 4 | // :partner-company-name: Example Company Name, Ltd. 5 | :doc-month: September 6 | :doc-year: 2020 7 | // :partner-contributors: John Doe and Jane Doe - {partner-company-name} 8 | :quickstart-contributors: AWS Quick Start Reference Team 9 | :deployment_time: 1 hour and 30 minutes 10 | :default_deployment_region: us-east-1 11 | // Uncomment these two attributes if you are leveraging 12 | // - an AWS Marketplace listing. 13 | // Additional content will be auto-generated based on these attributes. 14 | // :marketplace_subscription: 15 | // :marketplace_listing_url: https://example.com/ 16 | -------------------------------------------------------------------------------- /docs/partner_editable/additional_info.adoc: -------------------------------------------------------------------------------- 1 | // Add steps as necessary for accessing the software, post-configuration, and testing. Don’t include full usage instructions for your software, but add links to your product documentation for that information. 2 | //Should any sections not be applicable, remove them 3 | 4 | == Post-deployment steps 5 | 6 | === Run Windows Updates 7 | 8 | In order to ensure the deployed servers' operating systems and installed applications have the latest Microsoft updates, run Windows Update on each server. 9 | 10 | 1. Create an RDP session from the Remote Desktop Gateway server to each deployed server. 11 | 2. Open the *Settings* application. 12 | 3. Open *Update & Security*. 13 | 4. Click *Check for updates*. 14 | 5. Install any updates and reboot if necessary. 15 | 16 | [[design-considerations]] 17 | == Design Considerations 18 | 19 | This Quick Start is designed for a highly available AD FS implementation that supports 1,000 to 15,000 users, but there are a number of options available for architecting an AD FS deployment. Here are Microsoft’s recommendations for determining the minimum number of servers to deploy: 20 | 21 | * *Fewer than 1,000 users* – A small environment can use existing infrastructure instead of running dedicated AD FS servers. If you need to support fewer than 1,000 users, you can install AD FS on at least two of your domain controllers. Ideally, these domain controllers should be in two separate Availability Zones. 22 | * *1,000 to 15,000 users* – In this scenario, Microsoft recommends using a dedicated AD FS and Web Application Proxy server infrastructure. The AD FS database can run using a Windows Internal Database (WID), so you’ll need four servers (two Web Application Proxy, two AD FS) in this architecture, as shown in Figure 1. 23 | * *15,000 to 60,000 users* – For large environments, Microsoft recommends using three to five dedicated AD FS servers, and at least two dedicated Web Application Proxy servers. Note that if you’re scaling beyond five dedicated AD FS servers, you’ll need a dedicated SQL Server instance instead of running a WID. 24 | 25 | These recommendations are based on a hardware profile that supports 8 CPU cores, 4 GiB of RAM, and a 1 gigabit network connection. 26 | 27 | [[selecting-an-instance-type]] 28 | === Selecting an Instance Type 29 | 30 | AD FS is considered a processor-bound workload, meaning that CPU resources are the highest in demand. This Quick Start uses C4 compute-optimized instances by default. 31 | 32 | Specifically, the *c4.2xlarge* instance type is used to provide 8 vCPUs and 15 GiB of memory to meet or exceed requirements, based on the recommendations in the previous section. Additionally, the c4.2xlarge instance type supports Amazon EBS optimization, enhanced networking, and high network performance, which results in higher packets per second, lower latency, and lower jitter. Although c4.2xlarge provides more memory than required, it’s a great candidate for workloads running in a production environment. 33 | 34 | [[database-options]] 35 | === Database Options 36 | 37 | The recommended topology for AD FS is to create a federation server farm that includes at least two AD FS servers. When you install AD FS on the first server, the federation server farm is created. You can join the next server to the farm, and then load-balance those servers. 38 | 39 | An AD FS federation server farm uses a database to hold configuration data. For farms with five or fewer servers, you can use a Windows Internal Database (WID). The primary AD FS server will have a read/write copy of this database. The secondary AD FS servers in the farm receive updates from the primary server to a read-only copy of the WID. If the primary AD FS server fails, the secondary server can still process authentication requests, but you cannot make configuration changes until either the primary server is brought back online or the secondary server is converted to primary. 40 | 41 | For federation server farms that have more than five AD FS servers, you’ll need to use a SQL Server database for the configuration database. When you use SQL Server for your AD FS database, all members in the federation server farm have write access to the configuration data. 42 | 43 | Microsoft recommends that you use WID until you scale past five AD FS servers. This Quick Start utilizes WID with AD FS by default. 44 | 45 | [[load-balancing]] 46 | === Load Balancing 47 | 48 | For production deployments, you should implement load balancing to make your Web Application Proxy and AD FS services highly available. You can use Elastic Load Balancing or a third-party virtual load balancer appliance. 49 | 50 | Both the Web Application Proxy and AD FS layers can be load balanced individually with Elastic Load Balancing. You can deploy an Internet-facing load balancer for the Web Application Proxy layer that will service users accessing published web applications over the Internet. In addition, you can configure an internal load balancer for the AD FS servers. You would then configure the Web Application Proxy layer to point to the load-balanced DNS name (e.g., sts.example.com) that resolves to the internal load balancer. 51 | 52 | In order to take advantage of header inspection, it is recommended that Application Load Balancers (rather than Network Load Balancers or Classic Load Balancers) be deployed. The Internet-facing load balancer for the Web Application Proxy layer should be configured to accept HTTPS requests on port 443 and forward these requests to the Web Application Proxy servers, and a certificate obtained from a trusted third-party Certificate Authority will need to be assigned to this listener. The internal load balancer will also be configured to accept HTTPS requests on port 443 but its listener can be assigned an internally-signed certificate. 53 | 54 | See https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-requirements[Microsoft AD FS Requirements] for detailed load balancing and health check requirements. 55 | 56 | [[certificates]] 57 | === Certificates 58 | 59 | Certificates are required to install both the Web Application Proxy and AD FS components. This Quick Start automates the deployment and installation of these components by using certificates issued from an internal enterprise certificate authority (CA), which runs on the domain controller infrastructure. You can replace these certificates in your own production deployments. The requirements and recommendations for both the Web Application Proxy and AD FS layers are discussed in the next two sections. 60 | 61 | [[web-application-proxy-certificates]] 62 | ==== Web Application Proxy Certificates 63 | 64 | * *Issuing CA* – Typically, the Web Application Proxy infrastructure will use certificates issued from a commercial or public CA, such as DigiCert or Verisign, which should be installed in the computer’s personal certificate store. Using a public CA generally prevents you from having to install root certificates on your client devices. You can use your own public key infrastructure (PKI) to issue the Web Application Proxy certificates, but you’ll need to ensure that client devices trust the issuing CA, which typically involves installing the root certificate on the devices as well as making the URL of your certificate revocation list externally accessible. 65 | * *Certificate FQDNs* – You can explicitly set the certificate subject and subject alternative name (SAN) fields, or you can choose to use a wildcard certificate (e.g., *.example.com). For explicit naming, you’ll need to set the subject field to the AD FS federation service name (e.g., sts.example.com). If you plan to use the Workplace Join feature, you’ll also need two SAN entries: one for the federation service name (e.g., sts.example.com) and one for enterprise registration in the format enterpriseregistration._yourdomain_.com. Additionally, you’ll want SAN entries for any fully qualified domain name (FQDN) that you will be publishing, such as externally facing SharePoint sites, OWA, etc. 66 | 67 | [[ad-fs-certificates]] 68 | ==== AD FS Certificates 69 | 70 | * *Issuing CA* – Typically, the AD FS infrastructure will use certificates issued from an internal PKI, such as an enterprise Active Directory CA, because the servers in the infrastructure are not internet facing. This is especially useful in an Active Directory domain environment where all domain-joined machines will trust the issuing CA by default. If you choose not to domain-join your Web Application Proxy servers, you can install the CA root certificate on those servers in the computer’s trusted root certificate authority store. If you do not have an existing PKI implementation, it’s probably easiest to use the same public certificate on both the Web Application Proxy and AD FS servers. 71 | * *Certificate FQDNs* – The AD FS certificate requires the federation service name to be set on the subject field (e.g., sts.example.com), or you can use a wildcard certificate. 72 | 73 | [[domain-joined-proxies]] 74 | === Domain-Joined Proxies 75 | 76 | You may choose not to domain-join your Web Application Proxy servers, because they will be placed in public virtual private cloud (VPC) subnets. This is a typical practice for server workloads running in a demilitarized zone (DMZ). However, if the web application you want to publish through Web Application Proxy must support Integrated Windows authentication, you should domain-join the Web Application Proxy server. 77 | 78 | This Quick Start automatically joins the Web Application Proxy servers to the Active Directory Domain Services environment. See the #_Appendix:_Publishing_Outlook[appendix] for an example of how to publish a web application that uses Integrated Windows authentication. 79 | 80 | [[authentication-scenarios]] 81 | === Authentication Scenarios 82 | 83 | Publishing web applications with Web Application Proxy supports three authentication scenarios: 84 | 85 | * *AD FS pre-authentication* – In this scenario, users authenticate against AD FS before gaining access to the published web application. This requires that you add an AD FS relying party trust to the federation service. For detailed coverage on AD FS pre-authentication flow, see https://technet.microsoft.com/en-us/library/dn383640.aspx[Publish Applications using AD FS Preauthentication] in the Microsoft TechNet Library. 86 | * *Client certificate pre-authentication* – In this scenario, one or more external servers connect to an on-premises web application through the Web Application Proxy infrastructure using a certificate for authentication. Despite the name, this scenario should not be used for client devices that connect to a published web application. For more information, see https://technet.microsoft.com/en-us/library/dn584096.aspx[Publish Applications using Client Certificate Preauthentication] in the Microsoft TechNet Library. 87 | * *Pass-through pre-authentication* – In this scenario, access to the web application is proxied directly to the back-end server without pre-authentication against AD FS. For example, this is the option you would use to make AD FS externally accessible. Subsequently published applications that use AD FS pre-authentication will access AD FS via pass-through pre-authentication. 88 | 89 | See the #_Appendix:_Publishing_Outlook[appendix] for an example that covers both AD FS and pass-through pre-authentication. 90 | 91 | == Security 92 | 93 | When you build systems on the AWS infrastructure, security responsibilities are shared between you and AWS. This shared model can reduce your operational burden as AWS operates, manages, and controls the components from the host operating system and virtualization layer down to the physical security of the facilities in which the services operate. In turn, you assume responsibility and management of the guest operating system (including updates and security patches), other associated applications, as well as the configuration of the AWS-provided security group firewall. For more information about security on AWS, visit the http://aws.amazon.com/security/[AWS Security Center]. 94 | 95 | [[operating-system-security]] 96 | === Operating System Security 97 | 98 | All the Windows Servers deployed by this Quick Start are domain-joined. You can authenticate to these instances by using the stackadmin@example.com domain administrator account. You can specify the password for this account as you launch the stack. You can retrieve the local administrator password for domain-joined instances by using the _KeyPairName_ parameter specified during the launch. Operating system patches are your responsibility and should be performed on a periodic basis. 99 | 100 | [[security-groups]] 101 | === Security Groups 102 | 103 | A _security group_ acts as a firewall that controls the traffic for one or more instances. When you launch an instance, you associate one or more security groups with the instance. You add rules to each security group that allow traffic to or from its associated instances. You can modify the rules for a security group at any time. The new rules are automatically applied to all instances that are associated with the security group. 104 | 105 | The security groups created and assigned to the individual instances as part of this solution are restricted as much as possible while allowing access to the various functions needed by AD FS and Web Application Proxy. We recommend that you review security groups and further restrict access as needed once the deployment is up and running. 106 | 107 | == Additional Resources 108 | 109 | *AWS services* 110 | 111 | * AWS CloudFormation + 112 | https://aws.amazon.com/documentation/cloudformation/ 113 | * Amazon EBS 114 | 115 | * User guide: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AmazonEBS.html 116 | * Volume types: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html 117 | * Optimized instances: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSOptimized.html 118 | 119 | * Amazon EC2 120 | 121 | * User guide for Microsoft Windows: https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ 122 | 123 | * Amazon VPC + 124 | http://aws.amazon.com/documentation/vpc/ 125 | 126 | *Microsoft Web Application Proxy and AD FS* 127 | 128 | * Planning for AD FS Server Capacity + 129 | https://technet.microsoft.com/en-us/library/gg749899.aspx 130 | * Planning to Publish Applications Using Web Application Proxy + 131 | https://technet.microsoft.com/en-us/library/dn383650.aspx 132 | * Configure the Web Application Proxy Infrastructure + 133 | https://technet.microsoft.com/en-us/library/dn383644.aspx 134 | * Install and Configure the Web Application Proxy Server + 135 | https://technet.microsoft.com/en-us/library/dn383662.aspx 136 | * Publish Applications using AD FS Preauthentication + 137 | https://technet.microsoft.com/en-us/library/dn383640.aspx 138 | * Publish Applications using Pass-through Preauthentication + 139 | https://technet.microsoft.com/en-us/library/dn383639.aspx 140 | * Enabling Federation to AWS using Windows Active Directory, ADFS, and SAML 2.0 + 141 | https://blogs.aws.amazon.com/security/post/Tx71TWXXJ3UI14/Enabling-Federation-to-AWS-using-Windows-Active-Directory-ADFS-and-SAML-2-0 142 | 143 | *Deploying Microsoft software on AWS* 144 | 145 | * Microsoft on AWS + 146 | https://aws.amazon.com/microsoft/ 147 | * Secure Microsoft applications on AWS + 148 | https://d0.awsstatic.com/whitepapers/aws-microsoft-platform-security.pdf 149 | * Microsoft Licensing Mobility + 150 | https://aws.amazon.com/windows/mslicensemobility/ 151 | * MSDN on AWS + 152 | https://aws.amazon.com/windows/msdn/ 153 | * AWS Windows and .NET Developer Center + 154 | https://aws.amazon.com/net/ 155 | 156 | *Tools* 157 | 158 | * Best Practices Analyzer for Web Application Proxy + 159 | https://technet.microsoft.com/en-us/library/dn383651.aspx 160 | * Load-balancing solutions in the AWS Marketplace + 161 | https://aws.amazon.com/marketplace/ 162 | 163 | *Associated Quick Start reference deployments* 164 | 165 | * Microsoft Active Directory on AWS + 166 | https://docs.aws.amazon.com/quickstart/latest/active-directory-ds/ 167 | * Microsoft Remote Desktop Gateway on AWS + 168 | https://docs.aws.amazon.com/quickstart/latest/rd-gateway/ 169 | * Additional reference deployments + 170 | https://aws.amazon.com/quickstart/ [[_Appendix:_Publishing_Outlook]] 171 | -------------------------------------------------------------------------------- /docs/partner_editable/architecture.adoc: -------------------------------------------------------------------------------- 1 | Deploying this Quick Start for a new virtual private cloud (VPC) with 2 | default parameters builds the following Web Application Proxy and AD FS environment in the 3 | AWS Cloud. 4 | 5 | // Replace this example diagram with your own. Send us your source PowerPoint file. Be sure to follow our guidelines here : http://(we should include these points on our contributors giude) 6 | [#architecture1] 7 | .Quick Start architecture for _{partner-product-short-name}_ on AWS 8 | [link=images/architecture_diagram.png] 9 | image::../images/architecture_diagram.png[Architecture,width=100%,height=100%] 10 | 11 | The AWS CloudFormation template creates a fully functional AD FS federation server farm with Web Application Proxy on the AWS Cloud. The template deploys the following components: 12 | 13 | * A virtual private cloud (VPC) with resources distributed across two Availability Zones for high availability.* 14 | * Public subnets in each Availability Zone that provide access to and from the internet. The public subnets include network address translation (NAT) gateway instances for outbound internet access, and Remote Desktop Gateway (RD Gateway) instances in an Auto Scaling group for inbound remote administrative access. Web Application Proxy servers are deployed in the public subnets to help provide secure inbound connectivity to web applications.* 15 | * Private subnets in each Availability Zone for running enterprise workloads such as Active Directory domain controllers and AD FS servers, shielded from direct access over the internet.* 16 | * In the private subnets, domain controllers that act as enterprise certificate authorities (CAs) that issue the required SSL certificates to the AD FS infrastructure. For production deployments, you might want to consider commercial certificates issued from a public CA, and we’ll cover this in greater detail later in this guide. 17 | * In the private subnets, two AD FS servers running on Windows Server 2022, which are deployed in each Availability Zone to support high availability and load distribution. 18 | * Security groups to tightly control the flow of traffic between your Amazon EC2 instances. 19 | 20 | *The template that deploys the Quick Start into an existing VPC skips 21 | the components marked by asterisks and prompts you for your existing VPC 22 | configuration. 23 | -------------------------------------------------------------------------------- /docs/partner_editable/deploy_steps.adoc: -------------------------------------------------------------------------------- 1 | // We need to work around Step numbers here if we are going to potentially exclude the AMI subscription 2 | === Sign in to your AWS account 3 | 4 | . Sign in to your AWS account at https://aws.amazon.com with an IAM user role that has the necessary permissions. For details, see link:#_planning_the_deployment[Planning the deployment] earlier in this guide. 5 | . Make sure that your AWS account is configured correctly, as discussed in the link:#_technical_requirements[Technical requirements] section. 6 | 7 | // Optional based on Marketplace listing. Not to be edited 8 | ifdef::marketplace_subscription[] 9 | === Subscribe to the {partner-product-short-name} AMI 10 | 11 | This Quick Start requires a subscription to the AMI for {partner-product-short-name} in AWS Marketplace. 12 | 13 | . Sign in to your AWS account. 14 | . {marketplace_listing_url}[Open the page for the {partner-product-short-name} AMI in AWS Marketplace], and then choose *Continue to Subscribe*. 15 | . Review the terms and conditions for software usage, and then choose *Accept Terms*. + 16 | A confirmation page loads, and an email confirmation is sent to the account owner. For detailed subscription instructions, see the https://aws.amazon.com/marketplace/help/200799470[AWS Marketplace documentation^]. 17 | 18 | . When the subscription process is complete, exit out of AWS Marketplace without further action. *Do not* provision the software from AWS Marketplace—the Quick Start deploys the AMI for you. 19 | endif::marketplace_subscription[] 20 | // \Not to be edited 21 | 22 | === Create a http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html[key pair] in your preferred Region. 23 | 24 | To do this, in the navigation pane of the Amazon EC2 console, choose *Key Pairs*, *Create Key Pair*, type a name, and then choose *Create*. 25 | 26 | [#Deploy1] 27 | .Creating a key pair 28 | [link=images/image4.png] 29 | image::../images/image4.png[Deploy1,image,width=634,height=307] 30 | 31 | Amazon EC2 uses public-key cryptography to encrypt and decrypt login information. To be able to log in to your instances, you must create a key pair. With Windows instances, we use the key pair to obtain the administrator password via the Amazon EC2 console and then log in using Remote Desktop Protocol (RDP) as explained in the http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html#having-ec2-create-your-key-pair[step-by-step instructions] in the _Amazon Elastic Compute Cloud User Guide_. 32 | 33 | === If necessary, https://console.aws.amazon.com/support/home#/case/create?issueType=service-limit-increase&limitType=service-code-[request a service limit increase] for the Amazon EC2 *c4.2xlarge* instance type. 34 | 35 | To do this, in the AWS Support Center, choose *Create Case*, *Service Limit Increase*, *EC2 instances*, and then complete the fields in the limit increase form, as shown in Figure 4. The current default limit is 20 instances. 36 | + 37 | You might need to request an increase if you already have an existing deployment that uses this instance type, and you think you might exceed the default limit with this reference deployment. It might take a few days for the new service limit to become effective. For more information, see http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html[Amazon EC2 Service Limits] in the AWS documentation. 38 | 39 | *Note* The Quick Start uses five Elastic IP addresses by default: two for the NAT gateways, two for the proxies, and one for the RD Gateway instance. The default limit for Elastic IP addresses is five per AWS Region. If you’re planning to deploy multiple RD Gateway instances by configuring the *Number of RDGW Hosts* parameter, we recommend that you also request an increase in the Elastic IP address limit: In the https://console.aws.amazon.com/support/home#/case/create?issueType=service-limit-increase&limitType=service-code-[AWS Support Center], choose *Create Case*, *Service Limit Increase*, *Elastic IPs*, and then complete the fields. 40 | 41 | [#Deploy2] 42 | .Requesting a service limit increase 43 | [link=images/image5.png] 44 | image::../images/image5.png[Deploy2,image,width=648,height=425] 45 | 46 | === Launch the Quick Start 47 | 48 | NOTE: You are responsible for the cost of the AWS services used while running this Quick Start reference deployment. There is no additional cost for using this Quick Start. For full details, see the pricing pages for each AWS service used by this Quick Start. Prices are subject to change. 49 | 50 | . Sign in to your AWS account, and choose one of the following options to launch the AWS CloudFormation template. For help with choosing an option, see link:#_deployment_options[deployment options] earlier in this guide. 51 | 52 | [cols=2*] 53 | |=== 54 | ^|https://fwd.aws/eN64n[Deploy {partner-product-short-name} into a new VPC on AWS^] 55 | ^|https://github.com/aws-quickstart/quickstart-microsoft-wapadfs/blob/main/templates/wap-adfs-master.template[View template^] 56 | 57 | ^|https://fwd.aws/jpzqA[Deploy {partner-product-short-name} into an existing VPC on AWS^] 58 | ^|https://github.com/aws-quickstart/quickstart-microsoft-wapadfs/blob/main/templates/wap-adfs.template[View template^] 59 | |=== 60 | 61 | WARNING: If you’re deploying {partner-product-short-name} into an existing VPC, make sure that your VPC has two private subnets in different Availability Zones for the workload instances, and that the subnets aren’t shared. This Quick Start doesn’t support https://docs.aws.amazon.com/vpc/latest/userguide/vpc-sharing.html[shared subnets^]. These subnets require https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html[NAT gateways^] in their route tables, to allow the instances to download packages and software without exposing them to the internet. 62 | 63 | Also, make sure that the domain name option in the DHCP options is configured as explained in the http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_DHCP_Options.html[Amazon VPC documentation^]. You provide your VPC settings when you launch the Quick Start. 64 | 65 | Each deployment takes about {deployment_time} to complete. 66 | 67 | [start=2] 68 | . Check the AWS Region that’s displayed in the upper-right corner of the navigation bar, and change it if necessary. This is where the network infrastructure for {partner-product-short-name} will be built. The template is launched in the {default_deployment_region} Region by default. 69 | 70 | // *Note:* This deployment includes Amazon EFS, which isn’t currently supported in all AWS Regions. For a current list of supported Regions, see the https://docs.aws.amazon.com/general/latest/gr/elasticfilesystem.html[endpoints and quotas webpage]. 71 | 72 | [start=3] 73 | . On the *Create stack* page, keep the default setting for the template URL, and then choose *Next*. 74 | . On the *Specify stack details* page, change the stack name if needed. Review the parameters for the template. Provide values for the parameters that require input. For all other parameters, review the default settings and customize them as necessary. 75 | 76 | // In the following tables, parameters are listed by category and described separately for the two deployment options: 77 | 78 | // * Parameters for deploying {partner-product-short-name} into a new VPC 79 | // * Parameters for deploying {partner-product-short-name} into an existing VPC -------------------------------------------------------------------------------- /docs/partner_editable/deployment_options.adoc: -------------------------------------------------------------------------------- 1 | // There are generally two deployment options. If additional are required, add them here 2 | 3 | This Quick Start provides two deployment options: 4 | 5 | * *Deploy {partner-product-short-name} into a new VPC (end-to-end deployment)*. This option builds a new AWS environment consisting of the VPC, subnets, NAT gateways, security groups, bastion hosts, and other infrastructure components. It then deploys {partner-product-short-name} into this new VPC. 6 | * *Deploy {partner-product-short-name} into an existing VPC*. This option provisions {partner-product-short-name} in your existing AWS infrastructure. 7 | 8 | The Quick Start provides separate templates for these options. It also lets you configure Classless Inter-Domain Routing (CIDR) blocks, instance types, and {partner-product-short-name} settings, as discussed later in this guide. -------------------------------------------------------------------------------- /docs/partner_editable/faq_troubleshooting.adoc: -------------------------------------------------------------------------------- 1 | // Add any tips or answers to anticipated questions. This could include the following troubleshooting information. If you don’t have any other Q&A to add, change “FAQ” to “Troubleshooting.” 2 | 3 | == FAQ 4 | 5 | *Q.* I encountered a *CREATE_FAILED* error when I launched the Quick Start. 6 | 7 | *A.* If AWS CloudFormation fails to create the stack, we recommend that you relaunch the template with *Rollback on failure* set to *Disabled*. (This setting is under *Advanced* in the AWS CloudFormation console, *Options* page.) With this setting, the stack’s state is retained and the instance is left running, so you can troubleshoot the issue. (For Windows, look at the log files in %ProgramFiles%\Amazon\EC2ConfigService and C:\cfn\log.) 8 | // If you’re deploying on Linux instances, provide the location for log files on Linux, or omit this sentence. 9 | 10 | WARNING: When you set *Rollback on failure* to *Disabled*, you continue to incur AWS charges for this stack. Please make sure to delete the stack when you finish troubleshooting. 11 | 12 | For additional information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/troubleshooting.html[Troubleshooting AWS CloudFormation^] on the AWS website. 13 | 14 | *Q.* I encountered a size limitation error when I deployed the AWS CloudFormation templates. 15 | 16 | *A.* We recommend that you launch the Quick Start templates from the links in this guide or from another S3 bucket. If you deploy the templates from a local copy on your computer or from a location other than an S3 bucket, you might encounter template size limitations. For more information about AWS CloudFormation quotas, see the http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html[AWS documentation^]. 17 | 18 | 19 | == Appendix: Publishing Outlook Web App to the Internet with AD FS Pre-Authentication 20 | 21 | Instead of using the nested AWS CloudFormation template to launch a new environment, you can use the https://fwd.aws/YAkEy[Web Application Proxy and AD FS template] included with this Quick Start to launch the components into an existing VPC. 22 | 23 | *Important* The sub-template for Web Application Proxy and AD FS provided with this guide is built to work with existing VPCs that have two public and two private subnets, and an existing Active Directory Domain Services implementation. More specifically, it is designed to work with the existing Microsoft-based AWS Quick Starts, such as Exchange Server, SharePoint Server, and Lync Server. 24 | 25 | In this appendix, we’ll show you how to launch the Web Application Proxy and AD FS infrastructure on top of the Exchange Server Quick Start. Then we’ll walk through the steps to publish Outlook Web App (OWA) to the internet using Web Application Proxy and AD FS. 26 | 27 | *Note* This walkthrough details the process of publishing OWA using Integrated Windows authentication. You can follow the same general process for Exchange Server 2010, or other web applications you want to publish with Integrated Windows authentication. It is also possible to publish OWA with claims-based authentication using Exchange Server 2013 SP1 or newer, but that scenario is beyond the scope of this guide. 28 | 29 | 1. Launch the https://fwd.aws/NvamP[Exchange Server Quick Start]. 30 | 31 | 2. Once the Exchange Server 2019 stack has been created successfully, launch the https://fwd.aws/5VrKP[Web Application Proxy and AD FS template]. As shown previously in this guide, you’ll need to specify the _KeyPairName_ for your chosen region. Additionally, you’ll need to specify the IDs for your existing VPC and for the public and private subnets. 32 | 33 | 3. Initiate a Remote Desktop Protocol (RDP) connection to one of the RD Gateway instances. You can retrieve the Elastic IP for the RD Gateway servers in the Amazon EC2 console. From there, use RDP to connect to the EXCH1 server. 34 | 35 | 4. On EXCH1, navigate to the Exchange Admin Center (https://exch1/ecp) in a web browser. Sign in by using the stackadmin user account and password you specified when building the stack. 36 | 37 | [#Additional1] 38 | .Logging into the Exchange Admin Center 39 | [link=images/image6.png] 40 | image::../images/image6.png[Additional1,image,width=532,height=299] 41 | 42 | [start=5] 43 | 5. In the left pane, choose *Servers*, *Virtual directories*. 44 | 45 | [#Additional2] 46 | .Viewing the virtual directories on EXCH1 47 | [link=images/image7.png] 48 | image::../images/image7.png[Additional2,image,width=546,height=308] 49 | 50 | [start=6] 51 | 6. Double-click *owa (Default Web Site)* on the EXCH1 server. Choose *Authentication*, *Integrated Windows authentication*, and then choose *Save*. You should also change the corresponding setting on the ECP virtual directory on EXCH1. 52 | 53 | [#Additional3] 54 | .Setting OWA authentication to Integrated Windows 55 | [link=images/image8.png] 56 | image::../images/image8.png[Additional3,image,width=480,height=302] 57 | 58 | *Note* In a load-balanced production environment, you would modify this setting on each Exchange server that is running the Client Access role. 59 | 60 | [start=7] 61 | 7. Establish an RDP connection to the ADFS1 server. In *Control Panel*, choose *Administrative Tools*, and then launch the *ADFS Management* snap-in. 62 | 63 | 8. Open the context (right-click) menu for *Trust Relationships*, and then choose *Add Non-Claims-Aware Relying Party Trust* to start the wizard. 64 | 65 | [#Additional4] 66 | .Adding a non-claims-aware relying party trust 67 | [link=images/image9.png] 68 | image::../images/image9.png[Additional4,image,width=446,height=241] 69 | 70 | [start=9] 71 | 9. On the welcome page of the wizard, choose *Start*, and type a display name such as *OWA*. Provide a unique identifier string for the non-claims-aware relying party trust. Use the default service name created by the Quick Start (e.g., http://sts.example.com/adfs/services/trust) for the URL. 72 | 73 | 10. Indicate that you do not want to configure multi-factor authentication, and then choose *Next*. 74 | 75 | 11. Go through the remaining screens without making changes. On the final screen, leave the *Open the Edit Issuance Authorization Rules* option selected, and then choose *Close*. 76 | 77 | 12. On the *Edit Claim Rules* screen, choose *Add Rule*, *Permit Access to All Users*, and then choose *Finish*. 78 | 79 | 13. Establish an RDP connection to the WAP1 server. In *Control Panel*, choose *Administrative Tools*, and then launch the *Remote Access Management* snap-in. 80 | 81 | [#Additional5] 82 | .Viewing the Remote Access Management console 83 | [link=images/image10.png] 84 | image::../images/image10.png[Additional5,image,width=603,height=145] 85 | 86 | To publish OWA to the internet, you’ll need to create two rules. The first rule will be a pass-through authentication rule to the AD FS server. This will allow users to pre-authenticate before being connected to OWA. 87 | 88 | [start=14] 89 | 14. Under *Tasks*, choose *Publish*. 90 | 91 | 15. On the Welcome screen, choose *Next*. On the *Preauthentication* tab, choose *Pass-through*. 92 | 93 | [#Additional6] 94 | .Selecting the pass-through pre-authentication method 95 | [link=images/image11.png] 96 | image::../images/image11.png[Additional6,image,width=486,height=183] 97 | 98 | [start=16] 99 | 16. Provide a name such as ADFS for the rule. Specify the external URL, the external certificate, and the back-end server URL as shown in Figure 11. 100 | 101 | [#Additional7] 102 | .Configuring the publishing rule 103 | [link=images/image12.png] 104 | image::../images/image12.png[Additional7,image,width=488,height=233] 105 | 106 | *Note* If you’ve implemented internal load balancing for the AD FS tier, you can set the back-end server URL to a load-balanced endpoint instead of an individual server name. 107 | 108 | [start=17] 109 | 17. Choose *Publish,* and then *Close* to exit the wizard. 110 | 111 | 18. Choose *Publish* again to create a new rule for OWA. This time, set the pre-authentication method to *Active Directory Federation Services (AD FS)*, and then choose *Next*. 112 | 113 | [#Additional8] 114 | .Selecting the AD FS pre-authentication method 115 | [link=images/image13.png] 116 | image::../images/image13.png[Additional8,image,width=488,height=233] 117 | 118 | [start=19] 119 | 19. For the relying party for the application, select the relying party trust you created on the AD FS server, and then choose *Next*. 120 | 121 | [#Additional9] 122 | .Selecting the relying party 123 | [link=images/image14.png] 124 | image::../images/image14.png[Additional9,image,width=488,height=233] 125 | 126 | [start=20] 127 | 20. Provide a name such as OWA for the rule. Specify the external URL, external certificate, back-end URL, and service principal name (SPN) for the back-end server, as shown in Figure 14. 128 | 129 | [#Additional10] 130 | .Configuring rule details 131 | [link=images/image15.png] 132 | image::../images/image15.png[Additional10,image,width=488,height=233] 133 | 134 | *Note* If you’ve implemented internal load balancing for the Exchange client access tier, you can set the back-end server URL and SPN to a load-balanced endpoint instead of an individual server name. 135 | 136 | [start=21] 137 | 21. Choose *Publish* and close the wizard. 138 | 139 | 22. Establish an RDP connection to DC1. In *Control Panel*, choose *Administrative Tools*, and then launch the *Active Directory Users and Computers* snap-in. 140 | 141 | 23. Navigate to the *Computers* container, right-click the WAP1 computer, and then choose *Properties*. On the *Delegation* tab, choose *Trust this computer for delegation to specified services only*. Check the option to use any authentication protocol, and add the HTTP service type on the EXCH1 computer to the list, as shown in Figure 15. Choose *Apply*, and then choose *OK*. 142 | 143 | [#Additional11] 144 | .Configuring Kerberos constrained delegation 145 | [link=images/image16.png] 146 | image::../images/image16.png[Additional11,image,width=315,height=353] 147 | 148 | Now you are ready to test accessing OWA from an external workstation or server over the internet. 149 | 150 | [start=24] 151 | 24. If you did not use your own domain name, you’ll need to edit the hosts file on your machine to allow your computer to resolve the endpoints at example.com: Add a mapping for *sts.example.com* and *mail.example.com* to your local hosts file, making sure that both hosts resolve to the public EIP of the WAP1 server. 152 | 153 | 25. Open a web browser from your external workstation or server. Navigate to *mail.example.com*. You should be redirected to the federation service and prompted for authentication. Provide the stackadmin user name and password, and then choose *Sign in*. 154 | 155 | [#Additional12] 156 | .Pre-authenticating to AD FS 157 | [link=images/image17.png] 158 | image::../images/image17.png[Additional12,image,width=315,height=353] 159 | 160 | If the authentication is successful, the connection should be proxied to the EXCH1 server through the Web Application Proxy, as shown in Figure 17. 161 | 162 | [#Additional13] 163 | .Connected to the published application 164 | [link=images/image18.png] 165 | image::../images/image18.png[Additional13,image,width=315,height=353] -------------------------------------------------------------------------------- /docs/partner_editable/licenses.adoc: -------------------------------------------------------------------------------- 1 | // Include details about the license and how they can sign up. If no license is required, clarify that. 2 | 3 | This Quick Start deploys AWS EC2 instances running Microsoft Windows, and the cost of the Windows licenses is included in the cost of the EC2 instances. 4 | All roles and functionality deployed on top of the Windows instances are included in the cost of the Windows licenses. 5 | -------------------------------------------------------------------------------- /docs/partner_editable/overview_target_and_usage.adoc: -------------------------------------------------------------------------------- 1 | // Replace the content in <> 2 | // Identify your target audience and explain how/why they would use this Quick Start. 3 | //Avoid borrowing text from third-party websites (copying text from AWS service documentation is fine). Also, avoid marketing-speak, focusing instead on the technical aspect. 4 | 5 | This Quick Start reference deployment guide discusses architectural considerations and configuration steps for deploying a Web Application Proxy and Active Directory Federation Services (AD FS) environment on the Amazon Web Services (AWS) Cloud. It also provides links for viewing and launching https://aws.amazon.com/cloudformation/[AWS CloudFormation] templates that automate the deployment. 6 | 7 | The guide is for IT infrastructure architects, administrators, and DevOps professionals who are planning to implement or extend their Web Application Proxy and AD FS workloads on the AWS Cloud. 8 | -------------------------------------------------------------------------------- /docs/partner_editable/pre-reqs.adoc: -------------------------------------------------------------------------------- 1 | // If no preperation is required, remove all content from here 2 | 3 | ==== Prepare for the deployment 4 | 5 | If you are deploying the WAP ADFS Quick Start into an existing VPC, ensure your Active Directory environment includes at least one certificate authority (CA). If you are using AWS Managed Microsoft Active Directory this will require you to have at least one domain-joined server that can be configured as the CA, since AWS Managed Microsoft Active Directory does not act as a CA natively. A domain-joined server can be promoted to a CA by executing the following PowerShell code from an elevated command prompt: 6 | 7 | ---- 8 | Add-WindowsFeature Adcs-Cert-Authority -IncludeManagementTools 9 | Install-AdcsCertificationAuthority -CAType EnterpriseRootCA 10 | ---- -------------------------------------------------------------------------------- /docs/partner_editable/product_description.adoc: -------------------------------------------------------------------------------- 1 | // Replace the content in <> 2 | // Briefly describe the software. Use consistent and clear branding. 3 | // Include the benefits of using the software on AWS, and provide details on usage scenarios. 4 | 5 | Microsoft Active Directory Federation Services (AD FS) is a Windows Server role that provides identity federation and single sign-on (SSO) capabilities for users accessing applications in an AD FS-secured environment, or with federated partner organizations. Put simply, AD FS authenticates users and provides security tokens to applications or federated partner applications that trust AD FS. 6 | 7 | For example, you could implement identity federation with AWS Identity and Access Management (IAM) and AD FS, and then use your Active Directory user name and password (instead of the AWS root account or IAM user credentials) to sign in to the AWS Management Console, or to make calls to AWS APIs. 8 | 9 | Like domain controllers and other internal server workloads, AD FS servers are deployed in a private virtual private cloud (VPC) subnet. In order to make AD FS accessible to external users, you can deploy the Web Application Proxy role on Windows Server 2022. The Web Application Proxy server can proxy requests to the AD FS infrastructure for users who are connecting from an external location, without the need for VPN connectivity. 10 | 11 | You can also use Web Application Proxy to selectively publish and pre-authenticate connections to internal web applications, allowing external users outside your organization to access those applications over the internet. 12 | 13 | In this guide, we’ll take a look at using your own Active Directory Domain Services (AD DS) infrastructure in AWS, along with AD FS and Web Application Proxy, to provide seamless external access to web applications running in AWS. 14 | 15 | Some of the benefits and features of publishing applications with Web Application Proxy and AD FS are: 16 | 17 | * *Network isolation* – Publishing web applications through Web Application Proxy means that back-end servers are never directly exposed to the internet. You can publish popular web-based workloads such as Microsoft SharePoint, Outlook Web App (OWA), Exchange ActiveSync, Lync (Skype for Business), and even custom web applications through Web Application Proxy. 18 | * *Denial-of-service (DoS) protection* – The Web Application Proxy infrastructure uses several mechanisms to implement basic DoS protection, such as throttling and queuing, before routing connections to back-end web applications. 19 | * *Multi-factor authentication* – Pre-authentication with AD FS provides support for smart cards, device authentication, and more. 20 | * *Single sign-on (SSO)* – This functionality provides users with seamless access to applications without re-prompting for credentials after initial authentication. 21 | * *Workplace Join* - Users can connect devices that are not typically domain-joined, such as personal laptops, tablets, and smartphones, to their company’s resources. Known devices can be granted conditional access to applications, and you can require that devices register before gaining access to published applications. 22 | 23 | For further details, see https://technet.microsoft.com/en-us/library/dn383650.aspx[Planning to Publish Applications Using Web Application Proxy] on Microsoft TechNet. 24 | 25 | This guide and associated AWS CloudFormation template can be used in conjunction with https://aws.amazon.com/quickstart/[other AWS Quick Starts] to securely publish web applications running on SharePoint, Exchange, Lync, or your own web-based applications. The infrastructure deployed by this Quick Start enables external users to pre-authenticate to AD FS to access these web applications, without exposing the applications or AD FS infrastructure directly to the internet. You can also use this infrastructure to enable federation with AWS. 26 | 27 | -------------------------------------------------------------------------------- /docs/partner_editable/regions.adoc: -------------------------------------------------------------------------------- 1 | This Quick Start is supported in all non-GovCloud AWS Regions 2 | -------------------------------------------------------------------------------- /docs/partner_editable/service_limits.adoc: -------------------------------------------------------------------------------- 1 | // Replace the in each row to specify the number of resources used in this deployment. Remove the rows for resources that aren’t used. 2 | |=== 3 | |Resource |This deployment uses 4 | 5 | // Space needed to maintain table headers 6 | |VPCs |1 7 | |Elastic IP addresses |1 8 | |AWS Identity and Access Management (IAM) security groups |2 9 | |IAM roles |2 10 | |EC2 instances |5 11 | |=== 12 | -------------------------------------------------------------------------------- /docs/partner_editable/specialized_knowledge.adoc: -------------------------------------------------------------------------------- 1 | // Replace the content in <> 2 | // Describe or link to specific knowledge requirements; for example: “familiarity with basic concepts in the areas of networking, database operations, and data encryption” or “familiarity with .” 3 | 4 | This Quick Start assumes familiarity with Microsoft Active Directory. 5 | 6 | 7 | -------------------------------------------------------------------------------- /scripts/Archive/Install-ADFS.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory = $true)][string]$DomainDNSName, 3 | [Parameter(Mandatory = $true)][string]$DomainNetBIOSName, 4 | [Parameter(Mandatory = $true)][string]$Username, 5 | [Parameter(Mandatory = $true)][string]$Password, 6 | [Parameter(Mandatory = $false)][switch]$FirstServer 7 | ) 8 | 9 | Start-Transcript -Path 'C:\cfn\log\Install-ADFS.ps1.txt' -Append 10 | 11 | Write-Output 'Creating Credential Object for Administrator' 12 | $Pass = ConvertTo-SecureString $Password -AsPlainText -Force 13 | $Credential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList ("$DomainNetBIOSName\$Username", $Pass) 14 | 15 | Write-Output 'Installing AD FS Binaries' 16 | Try { 17 | Install-WindowsFeature -Name 'ADFS-Federation' -IncludeManagementTools -ErrorAction Stop 18 | } Catch [System.Exception] { 19 | Write-Output "Failed to install AD FS Binaries $_" 20 | $_ | Write-AWSQuickStartException 21 | Exit 1 22 | } 23 | 24 | If ($FirstServer) { 25 | $FirstServerScriptBlock = { 26 | Function New-CertificateRequest { 27 | param ( 28 | [Parameter(Mandatory=$true, HelpMessage = "Please enter the subject beginning with CN=")] 29 | [ValidatePattern("CN=")] 30 | [string]$subject, 31 | [Parameter(Mandatory=$false, HelpMessage = "Please enter the SAN domains as a comma separated list")] 32 | [array]$SANs, 33 | [Parameter(Mandatory=$false, HelpMessage = "Please enter the Online Certificate Authority")] 34 | [string]$OnlineCA, 35 | [Parameter(Mandatory=$false, HelpMessage = "Please enter the Certificate Template")] 36 | [string]$CATemplate = "WebServer" 37 | ) 38 | 39 | ### Preparation 40 | $subjectDomain = $subject.split(',')[0].split('=')[1] 41 | if ($subjectDomain -match "\*.") { 42 | $subjectDomain = $subjectDomain -replace "\*", "star" 43 | } 44 | $CertificateINI = "$subjectDomain.ini" 45 | $CertificateREQ = "$subjectDomain.req" 46 | $CertificateRSP = "$subjectDomain.rsp" 47 | $CertificateCER = "$subjectDomain.cer" 48 | 49 | ### INI file generation 50 | new-item -type 'file' $CertificateINI -force 51 | add-content $CertificateINI '[Version]' 52 | add-content $CertificateINI 'Signature="$Windows NT$"' 53 | add-content $CertificateINI '' 54 | add-content $CertificateINI '[NewRequest]' 55 | $temp = 'Subject="' + $subject + '"' 56 | add-content $CertificateINI $temp 57 | add-content $CertificateINI 'Exportable=TRUE' 58 | add-content $CertificateINI 'KeyLength=2048' 59 | add-content $CertificateINI 'KeySpec=1' 60 | add-content $CertificateINI 'KeyUsage=0xA0' 61 | add-content $CertificateINI 'MachineKeySet=True' 62 | add-content $CertificateINI 'ProviderName="Microsoft RSA SChannel Cryptographic Provider"' 63 | add-content $CertificateINI 'ProviderType=12' 64 | add-content $CertificateINI 'SMIME=FALSE' 65 | if ($OnlineCA) { 66 | add-content $CertificateINI 'RequestType=PKCS10' 67 | } else { 68 | add-content $CertificateINI 'RequestType=Cert' 69 | } 70 | add-content $CertificateINI '[Strings]' 71 | add-content $CertificateINI 'szOID_ENHANCED_KEY_USAGE = "2.5.29.37"' 72 | add-content $CertificateINI 'szOID_PKIX_KP_SERVER_AUTH = "1.3.6.1.5.5.7.3.1"' 73 | add-content $CertificateINI 'szOID_PKIX_KP_CLIENT_AUTH = "1.3.6.1.5.5.7.3.2"' 74 | if ($SANs) { 75 | add-content $CertificateINI 'szOID_SUBJECT_ALT_NAME2 = "2.5.29.17"' 76 | add-content $CertificateINI '[Extensions]' 77 | add-content $CertificateINI '2.5.29.17 = "{text}"' 78 | 79 | foreach ($SAN in $SANs) { 80 | $temp = '_continue_ = "dns=' + $SAN + '&"' 81 | add-content $CertificateINI $temp 82 | } 83 | } 84 | 85 | ### Certificate request generation 86 | if (test-path $CertificateREQ) {del $CertificateREQ} 87 | & certreq.exe -new $CertificateINI $CertificateREQ > $null 88 | 89 | ### Online certificate request and import 90 | if ($OnlineCA) { 91 | if (test-path $CertificateCER) {del $CertificateCER} 92 | if (test-path $CertificateRSP) {del $CertificateRSP} 93 | & certreq.exe -submit -attrib "CertificateTemplate:$CATemplate" -config $OnlineCA $CertificateREQ $CertificateCER > $null 94 | & certreq.exe -accept $CertificateCER > $null 95 | } 96 | } 97 | 98 | Function Sync-ADDomain { 99 | $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain() 100 | $DCs = $domain.FindAllDiscoverableDomainControllers() 101 | foreach ($DC in $DCs) { 102 | foreach ($partition in $DC.Partitions) { 103 | Write-Host "Forcing replication on $DC from all servers for partition $partition" 104 | try { 105 | $DC.SyncReplicaFromAllServers($partition, 'CrossSite') 106 | } catch [System.Exception] { 107 | Write-Host $_ 108 | $foreach.Reset() 109 | continue 110 | } 111 | } 112 | } 113 | } 114 | 115 | Write-Output 'Installing AD RSAT Tools' 116 | Try { 117 | Install-WindowsFeature -Name 'RSAT-AD-Tools', 'RSAT-DNS-Server' -ErrorAction Stop 118 | } Catch [System.Exception] { 119 | Write-Output "Failed to install AD RSAT Tools $_" 120 | $_ | Write-AWSQuickStartException 121 | Exit 1 122 | } 123 | 124 | Write-Output 'Importing AD PS Module' 125 | Try { 126 | Import-Module -Name 'ActiveDirectory' -ErrorAction Stop 127 | } Catch [System.Exception] { 128 | Write-Output "Failed to importing AD PS Module $_" 129 | $_ | Write-AWSQuickStartException 130 | Exit 1 131 | } 132 | 133 | Write-Output 'Importing AD Domain Info' 134 | Try { 135 | $Domain = Get-ADDomain -ErrorAction Stop 136 | } Catch [System.Exception] { 137 | Write-Output "Failed to get AD domain $_" 138 | $_ | Write-AWSQuickStartException 139 | Exit 1 140 | } 141 | 142 | $BaseDn = $Domain.DistinguishedName 143 | $FQDN = $Domain.DNSRoot 144 | 145 | Write-Output 'Getting CA Information' 146 | Try{ 147 | $CA = Get-ADObject -SearchBase "CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,$BaseDn" -LDAPFilter '(objectclass=pKIEnrollmentService)' -Properties 'dNSHostName' -ErrorAction Stop 148 | } Catch [System.Exception] { 149 | Write-Output "Failed to get CA Information $_" 150 | $_ | Write-AWSQuickStartException 151 | Exit 1 152 | } 153 | 154 | If ($CA -eq $Null) { 155 | Write-Output "CA not present, please add and configure an Enterpise CA and try again $_" 156 | $_ | Write-AWSQuickStartException 157 | Exit 1 158 | } 159 | 160 | $CadNSHostName = $CA | Select-Object -ExpandProperty 'dNSHostName' 161 | $CaName = $CA | Select-Object -ExpandProperty 'Name' 162 | $CertificateAuthorities = "$CadNSHostName\$CaName" 163 | 164 | $CertificateADFSsubject = "*.$Using:DomainDNSName" 165 | $CertificateADFSsubjectCN = "CN=$CertificateADFSsubject" 166 | 167 | $newCertReqParams = @{ 168 | subject = $CertificateADFSsubjectCN 169 | } 170 | 171 | $newCertReqParams.Add("OnlineCA",$CertificateAuthorities) 172 | 173 | Write-Output 'Requesting a new certificate' 174 | New-CertificateRequest @newCertReqParams 175 | 176 | Write-Output 'Getting certificate information' 177 | Try { 178 | $ADFScertificate = Get-ChildItem -Path 'cert:\LocalMachine\My' -ErrorAction Stop | Where-Object { $_.Subject -eq "CN=*.$Using:DomainDNSName" } -ErrorAction Stop 179 | } Catch [System.Exception] { 180 | Write-Output "Failed to get certificate information $_" 181 | $_ | Write-AWSQuickStartException 182 | Exit 1 183 | } 184 | 185 | If ($ADFScertificate -eq $Null) { 186 | Write-Output "Certificate not present, try again $_" 187 | $_ | Write-AWSQuickStartException 188 | Exit 1 189 | } 190 | 191 | Write-Output 'Exporting certificate' 192 | Try { 193 | Export-PfxCertificate -Cert $ADFScertificate -FilePath "C:\cert\adfs.pfx" -Password $Using:Pass -ErrorAction Stop 194 | } Catch [System.Exception] { 195 | Write-Output "Failed to export certificate $_" 196 | $_ | Write-AWSQuickStartException 197 | Exit 1 198 | } 199 | 200 | Write-Output "Setting SPN on $Using:Username" 201 | & setspn.exe -s "host/sts.$Using:DomainDNSName" "$Using:Username" > $null 202 | 203 | $CertificateThumbprint = $ADFScertificate | Select-Object -ExpandProperty 'Thumbprint' 204 | 205 | Write-Output 'Installing ADFS farm' 206 | Try { 207 | Install-AdfsFarm -CertificateThumbprint $CertificateThumbprint -FederationServiceDisplayName 'ADFS' -FederationServiceName "sts.$Using:DomainDNSName" -ServiceAccountCredential $Using:Credential -OverwriteConfiguration 208 | } Catch [System.Exception] { 209 | Write-Output "Failed to install ADFS farm $_" 210 | $_ | Write-AWSQuickStartException 211 | Exit 1 212 | } 213 | 214 | Write-Output 'Getting IP address' 215 | Try{ 216 | $netip = Get-NetIPConfiguration -ErrorAction Stop | Select-Object -ExpandProperty 'IPv4Address' | Select-Object -ExpandProperty 'IpAddress' 217 | } Catch [System.Exception] { 218 | Write-Output "Failed to get IP address $_" 219 | $_ | Write-AWSQuickStartException 220 | Exit 1 221 | } 222 | 223 | Write-Output 'Getting DNS servers' 224 | Try { 225 | $dnsServers = Resolve-DnsName $Using:DomainDNSName -Type 'NS' -ErrorAction Stop | Select-Object -ExpandProperty 'Namehost' 226 | } Catch [System.Exception] { 227 | Write-Output "Failed to get DNS servers $_" 228 | $_ | Write-AWSQuickStartException 229 | Exit 1 230 | } 231 | 232 | Write-Output 'Creating STS DNS record' 233 | foreach ($dnsServer in $dnsServers) { 234 | $Counter = 0 235 | do { 236 | $ARecordPresent = Resolve-DnsName -Name "$sts.$FQDN" -DnsOnly -Server $dnsServer -ErrorAction SilentlyContinue 237 | If (-not $ARecordPresent) { 238 | $Counter ++ 239 | Write-Output 'STS record missing, creating it.' 240 | Add-DnsServerResourceRecordA -Name 'sts' -ZoneName $Using:DomainDNSName -IPv4Address $netip -Computername $dnsServer -ErrorAction SilentlyContinue 241 | If ($Counter -gt '1') { 242 | Start-Sleep -Seconds 10 243 | } 244 | } 245 | } Until ($ARecordPresent -or $Counter -eq 12) 246 | 247 | If ($Counter -ge 12) { 248 | Write-Output 'STS record never created' 249 | $_ | Write-AWSQuickStartException 250 | Exit 1 251 | } 252 | } 253 | 254 | Sync-ADDomain -ErrorAction Continue 255 | } 256 | Invoke-Command -Authentication 'Credssp' -Scriptblock $FirstServerScriptBlock -ComputerName $env:COMPUTERNAME -Credential $Credential 257 | } else { 258 | $ServerScriptBlock = { 259 | Write-Output 'Importing certificate' 260 | Try { 261 | Import-PfxCertificate –FilePath "\\ADFS1.$Using:DomainDNSName\cert\adfs.pfx" -CertStoreLocation cert:\localMachine\my -Password $Using:Pass -ErrorAction Stop 262 | } Catch [System.Exception] { 263 | Write-Output "Failed to import certificate $_" 264 | $_ | Write-AWSQuickStartException 265 | Exit 1 266 | } 267 | 268 | Write-Output 'Getting certificate information' 269 | Try { 270 | $ADFScertificate = Get-ChildItem -Path 'cert:\LocalMachine\My' -ErrorAction Stop | Where-Object { $_.Subject -eq "CN=*.$Using:DomainDNSName" } -ErrorAction Stop 271 | } Catch [System.Exception] { 272 | Write-Output "Failed to get certificate information $_" 273 | $_ | Write-AWSQuickStartException 274 | Exit 1 275 | } 276 | 277 | $CertificateThumbprint = $ADFScertificate | Select-Object -ExpandProperty 'Thumbprint' 278 | 279 | Write-Output "Setting SPN on $Using:Username" 280 | & setspn.exe -s "host/sts.$Using:DomainDNSName" "$Using:Username" > $null 281 | 282 | Write-Output 'Checking if ADFS1 DNS record is present' 283 | $Counter = 0 284 | Do { 285 | $ADFS1RecordPresent = Resolve-DnsName -Name "adfs1.$Using:DomainDNSName" -DnsOnly -ErrorAction SilentlyContinue 286 | If (-not $ADFS1RecordPresent) { 287 | $Counter ++ 288 | Write-Output "Unable to resolve adfs1.$Using:DomainDNSName. Waiting for 10 seconds before retrying." 289 | If ($Counter -gt '1') { 290 | Start-Sleep -Seconds 10 291 | } 292 | } 293 | } Until ($ADFS1RecordPresent -or $Counter -eq 12) 294 | 295 | If ($Counter -ge 12) { 296 | Write-Output 'ADFS1 record never created' 297 | $_ | Write-AWSQuickStartException 298 | Exit 1 299 | } 300 | 301 | Write-Output 'Adding server to ADFS farm' 302 | Try { 303 | Add-AdfsFarmNode -CertificateThumbprint $CertificateThumbprint -ServiceAccountCredential $Using:Credential -PrimaryComputerName "adfs1.$Using:DomainDNSName" -PrimaryComputerPort '80' -OverwriteConfiguration -ErrorAction Stop 304 | } Catch [System.Exception] { 305 | Write-Output "Failed to add server to ADFS farm $_" 306 | $_ | Write-AWSQuickStartException 307 | Exit 1 308 | } 309 | } 310 | 311 | Invoke-Command -Authentication 'Credssp' -Scriptblock $ServerScriptBlock -ComputerName $env:COMPUTERNAME -Credential $Credential 312 | } -------------------------------------------------------------------------------- /scripts/Archive/Install-WAP.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory = $true)][string]$DomainDNSName, 3 | [Parameter(Mandatory = $true)][string]$DomainNetBIOSName, 4 | [Parameter(Mandatory = $true)][string]$Username, 5 | [Parameter(Mandatory = $true)][string]$Password 6 | ) 7 | 8 | Start-Transcript -Path 'C:\cfn\log\Install-WAP.ps1.txt' -Append 9 | 10 | Write-Output 'Creating Credential Object for Administrator' 11 | $Pass = ConvertTo-SecureString $Password -AsPlainText -Force 12 | $Credential = New-Object -TypeName 'System.Management.Automation.PSCredential' -ArgumentList ("$DomainNetBIOSName\$Username", $Pass) 13 | 14 | $WAPScriptBlock = { 15 | 16 | Write-Output 'Importing certificate' 17 | Try { 18 | Import-PfxCertificate –FilePath "\\ADFS1.$Using:DomainDNSName\cert\adfs.pfx" -CertStoreLocation cert:\localMachine\my -Password $Using:Pass -ErrorAction Stop 19 | } Catch [System.Exception] { 20 | Write-Output "Failed to import certificate $_" 21 | $_ | Write-AWSQuickStartException 22 | Exit 1 23 | } 24 | 25 | Write-Output 'Getting certificate information' 26 | Try { 27 | $ADFScertificate = Get-ChildItem -Path 'cert:\LocalMachine\My' -ErrorAction Stop | Where-Object { $_.Subject -eq "CN=*.$Using:DomainDNSName" } -ErrorAction Stop 28 | } Catch [System.Exception] { 29 | Write-Output "Failed to get certificate information $_" 30 | $_ | Write-AWSQuickStartException 31 | Exit 1 32 | } 33 | 34 | $CertificateThumbprint = $ADFScertificate | Select-Object -ExpandProperty 'Thumbprint' 35 | 36 | Write-Output 'Installing Web App binaries' 37 | Try { 38 | Install-WindowsFeature -Name 'Web-Application-Proxy' -IncludeManagementTools -ErrorAction Stop 39 | } Catch [System.Exception] { 40 | Write-Output "Failed to install Web App binaries $_" 41 | $_ | Write-AWSQuickStartException 42 | Exit 1 43 | } 44 | 45 | Write-Output 'Checking if STS DNS record is present' 46 | $Counter = 0 47 | Do { 48 | $StsRecordPresent = Resolve-DnsName -Name "sts.$Using:DomainDNSName" -DnsOnly -ErrorAction SilentlyContinue 49 | If (-not $StsRecordPresent) { 50 | $Counter ++ 51 | Write-Output "Unable to resolve sts.$Using:DomainDNSName. Waiting for 10 seconds before retrying." 52 | If ($Counter -gt '1') { 53 | Start-Sleep -Seconds 10 54 | } 55 | } 56 | } Until ($StsRecordPresent -or $Counter -eq 12) 57 | 58 | If ($Counter -ge 12) { 59 | Write-Output 'sts record never appeared' 60 | $_ | Write-AWSQuickStartException 61 | Exit 1 62 | } 63 | 64 | Write-Output 'Installing WAP' 65 | Try { 66 | Install-WebApplicationProxy –CertificateThumbprint $CertificateThumbprint -FederationServiceName "sts.$Using:DomainDNSName" -FederationServiceTrustCredential $Using:Credential 67 | } Catch [System.Exception] { 68 | Write-Output "Failed to install WAP $_" 69 | $_ | Write-AWSQuickStartException 70 | Exit 1 71 | } 72 | } 73 | 74 | Invoke-Command -Authentication 'Credssp' -Scriptblock $WAPScriptBlock -ComputerName $env:COMPUTERNAME -Credential $Credential -------------------------------------------------------------------------------- /scripts/Modules/Module-WAPADFS/Module-WAPADFS.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-quickstart/quickstart-microsoft-wapadfs/444c2cc0a8cd52dac41034635003e7d739f6c5b6/scripts/Modules/Module-WAPADFS/Module-WAPADFS.psd1 -------------------------------------------------------------------------------- /templates/wap-adfs-master.template: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Description: >- 3 | This template deploys two Web Application Proxy servers into public subnets in each 4 | availability zone, as well as two ADFS servers into the private subnets in each 5 | availability zone. **WARNING** This template creates Amazon EC2 Windows instance 6 | and related resources. You will be billed for the AWS resources used if you create 7 | a stack from this template. (qs-1qup6rai1) 8 | Metadata: 9 | cfn-lint: 10 | config: 11 | ignore_checks: 12 | - W9006 13 | QuickStartDocumentation: 14 | EntrypointName: "Launch into a new VPC" 15 | Order: "1" 16 | AWS::CloudFormation::Interface: 17 | ParameterGroups: 18 | - Label: 19 | default: Network Configuration 20 | Parameters: 21 | - AvailabilityZones 22 | - VPCCIDR 23 | - PrivateSubnet1CIDR 24 | - PrivateSubnet2CIDR 25 | - PublicSubnet1CIDR 26 | - PublicSubnet2CIDR 27 | - RDGWCIDR 28 | - Label: 29 | default: Amazon EC2 Configuration 30 | Parameters: 31 | - KeyPairName 32 | - ADServerInstanceType 33 | - ADServer1NetBIOSName 34 | - ADServer1PrivateIP 35 | - ADServer2NetBIOSName 36 | - ADServer2PrivateIP 37 | - DataDriveSizeGiB 38 | - RDGWInstanceType 39 | - WAPADFSInstanceType 40 | - WAPADFSEnableAdvancedAudtingandMetrics 41 | - Label: 42 | default: Microsoft Active Directory Configuration 43 | Parameters: 44 | - DomainDNSName 45 | - DomainNetBIOSName 46 | - DomainAdminUser 47 | - DomainAdminPassword 48 | - ADEnableAdvancedAudtingandMetrics 49 | - Label: 50 | default: Microsoft Active Directory Certificate Services Configuration 51 | Parameters: 52 | - PKI 53 | - OrCaServerNetBIOSName 54 | - EntCaServerNetBIOSName 55 | - PKIEnableAdvancedAudtingandMetrics 56 | - Label: 57 | default: Microsoft Remote Desktop Gateway Configuration 58 | Parameters: 59 | - NumberOfRDGWHosts 60 | - Label: 61 | default: AWS Quick Start Configuration 62 | Parameters: 63 | - QSS3BucketName 64 | - QSS3BucketRegion 65 | - QSS3KeyPrefix 66 | ParameterLabels: 67 | ADEnableAdvancedAudtingandMetrics: 68 | default: Advanced Auditing and Metrics for Domain Controller Instance 69 | ADServerInstanceType: 70 | default: Domain Controller 1 instance type 71 | ADServer1NetBIOSName: 72 | default: Domain Controller 1 NetBIOS name 73 | ADServer1PrivateIP: 74 | default: Domain Controller 1 private IP address 75 | ADServer2NetBIOSName: 76 | default: Domain Controller 2 NetBIOS Name 77 | ADServer2PrivateIP: 78 | default: Domain Controller 2 private IP address 79 | AvailabilityZones: 80 | default: Availability Zones 81 | DataDriveSizeGiB: 82 | default: Size of the domain controller data drive 83 | DomainAdminPassword: 84 | default: Domain Admin password 85 | DomainAdminUser: 86 | default: Domain Admin username 87 | DomainDNSName: 88 | default: Domain DNS name 89 | DomainNetBIOSName: 90 | default: Domain NetBIOS name 91 | EntCaServerNetBIOSName: 92 | default: Enterprise Root CA NetBIOS name 93 | KeyPairName: 94 | default: Key Pair name 95 | NumberOfRDGWHosts: 96 | default: Number of RDGW hosts 97 | OrCaServerNetBIOSName: 98 | default: Offline Root CA NetBIOS name 99 | PKI: 100 | default: Deploy PKI infrastructure 101 | PKIEnableAdvancedAudtingandMetrics: 102 | default: Advanced Auditing and Metrics for PKI Instance(s) 103 | PrivateSubnet1CIDR: 104 | default: Private Subnet 1 CIDR 105 | PrivateSubnet2CIDR: 106 | default: Private Subnet 2 CIDR 107 | PublicSubnet1CIDR: 108 | default: Public Subnet 1 CIDR 109 | PublicSubnet2CIDR: 110 | default: Public Subnet 2 CIDR 111 | QSS3BucketName: 112 | default: Quick Start S3 bucket name 113 | QSS3BucketRegion: 114 | default: Quick Start S3 bucket region 115 | QSS3KeyPrefix: 116 | default: Quick Start S3 key prefix 117 | RDGWCIDR: 118 | default: Allowed Remote Desktop Gateway external access CIDR 119 | RDGWInstanceType: 120 | default: Remote Desktop Gateway instance type 121 | VPCCIDR: 122 | default: VPC CIDR 123 | WAPADFSInstanceType: 124 | default: WAP and ADFS Server instance type 125 | WAPADFSEnableAdvancedAudtingandMetrics: 126 | default: Advanced Auditing and Metrics for WAP and ADFS Instances 127 | Parameters: 128 | ADEnableAdvancedAudtingandMetrics: 129 | AllowedValues: 130 | - 'true' 131 | - 'false' 132 | Default: 'false' 133 | Description: Enable advanced auditing and metrics and upload them to CloudWatch using the Amazon Kinesis Agent for Microsoft Windows 134 | Type: String 135 | ADServerInstanceType: 136 | AllowedValues: 137 | - t3.medium 138 | - t3.large 139 | - t3.xlarge 140 | - t3.2xlarge 141 | - m5.large 142 | - m5.xlarge 143 | - m5.2xlarge 144 | - m5.4xlarge 145 | Default: m5.large 146 | Description: Amazon EC2 instance type for the Active Directory instances 147 | Type: String 148 | ADServer1NetBIOSName: 149 | AllowedPattern: '[a-zA-Z0-9\-]+' 150 | Default: DC1 151 | Description: NetBIOS name of the first Active Directory server (up to 15 characters) 152 | MaxLength: '15' 153 | MinLength: '1' 154 | Type: String 155 | ADServer1PrivateIP: 156 | 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])$ 157 | Default: 10.0.0.10 158 | Description: Fixed private IP for the first Active Directory server located in Availability Zone 1 159 | Type: String 160 | ADServer2NetBIOSName: 161 | AllowedPattern: '[a-zA-Z0-9\-]+' 162 | Default: DC2 163 | Description: NetBIOS name of the second Active Directory server (up to 15 characters) 164 | MaxLength: '15' 165 | MinLength: '1' 166 | Type: String 167 | ADServer2PrivateIP: 168 | 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])$ 169 | Default: 10.0.32.10 170 | Description: Fixed private IP for the second Active Directory server located in Availability Zone 2 171 | Type: String 172 | AvailabilityZones: 173 | Description: 'List of Availability Zones to use for the subnets in the VPC. Note: The logical order is preserved and only 2 AZs are used for this deployment.' 174 | Type: List 175 | DataDriveSizeGiB: 176 | Default: '20' 177 | Description: Size of data drive that contains SYSVOL and NTDS 178 | Type: Number 179 | DomainAdminPassword: 180 | 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]))^.* 181 | Description: Password for the alternate domain admin user. Must be at least 8 characters containing letters, numbers and symbols 182 | MaxLength: '32' 183 | MinLength: '8' 184 | NoEcho: 'true' 185 | Type: String 186 | DomainAdminUser: 187 | AllowedPattern: '[a-zA-Z0-9]*' 188 | Default: Admin 189 | Description: User name for the account that will be added as alternate Domain Administrator. This is separate from the default "Administrator" account 190 | MaxLength: '25' 191 | MinLength: '5' 192 | Type: String 193 | DomainDNSName: 194 | AllowedPattern: '^([a-zA-Z0-9]+[\.\-])+([a-zA-Z0-9])+$' 195 | Default: example.com 196 | Description: Fully qualified domain name (FQDN) of the forest root domain e.g. example.com 197 | MaxLength: '25' 198 | MinLength: '3' 199 | Type: String 200 | DomainNetBIOSName: 201 | AllowedPattern: '[a-zA-Z0-9\-]+' 202 | Default: example 203 | Description: NetBIOS name of the domain (up to 15 characters) for users of earlier versions of Windows e.g. EXAMPLE 204 | MaxLength: '15' 205 | MinLength: '1' 206 | Type: String 207 | EntCaServerNetBIOSName: 208 | AllowedPattern: '[a-zA-Z0-9\-]+' 209 | Default: ENTCA1 210 | Description: NetBIOS name of the Enterprise Root or Subordinate CA server (up to 15 characters) 211 | MaxLength: '15' 212 | MinLength: '1' 213 | Type: String 214 | KeyPairName: 215 | Description: Public/private key pairs allow you to securely connect to your instance after it launches 216 | Type: AWS::EC2::KeyPair::KeyName 217 | NumberOfRDGWHosts: 218 | AllowedValues: 219 | - '0' 220 | - '1' 221 | - '2' 222 | - '3' 223 | - '4' 224 | Default: '0' 225 | Description: Enter the number of Remote Desktop Gateway hosts to create 226 | Type: String 227 | OrCaServerNetBIOSName: 228 | AllowedPattern: '[a-zA-Z0-9\-]+' 229 | Default: ORCA1 230 | Description: NetBIOS name of the Offline Root CA server (Only Used For Two Tier PKI) (up to 15 characters) 231 | MaxLength: '15' 232 | MinLength: '1' 233 | Type: String 234 | PKI: 235 | AllowedValues: 236 | - One-Tier 237 | - Two-Tier 238 | - 'No' 239 | Default: One-Tier 240 | Description: Do you want to Deploy PKI Infrastructure if so what kind, Two Tier or One Tier 241 | Type: String 242 | PKIEnableAdvancedAudtingandMetrics: 243 | AllowedValues: 244 | - 'true' 245 | - 'false' 246 | Default: 'false' 247 | Description: Enable advanced auditing and metrics and upload them to CloudWatch using the Amazon Kinesis Agent for Microsoft Windows 248 | Type: String 249 | PrivateSubnet1CIDR: 250 | 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]))$ 251 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 252 | Default: 10.0.0.0/19 253 | Description: CIDR block for private subnet 1 located in Availability Zone 1. 254 | Type: String 255 | PrivateSubnet2CIDR: 256 | 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]))$ 257 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 258 | Default: 10.0.32.0/19 259 | Description: CIDR block for private subnet 2 located in Availability Zone 2. 260 | Type: String 261 | PublicSubnet1CIDR: 262 | 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]))$ 263 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 264 | Default: 10.0.128.0/20 265 | Description: CIDR Block for the public DMZ subnet 1 located in Availability Zone 1 266 | Type: String 267 | PublicSubnet2CIDR: 268 | 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]))$ 269 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 270 | Default: 10.0.144.0/20 271 | Description: CIDR Block for the public DMZ subnet 2 located in Availability Zone 2 272 | Type: String 273 | QSS3BucketName: 274 | AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$ 275 | ConstraintDescription: Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). 276 | Default: aws-quickstart 277 | 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 (-). 278 | Type: String 279 | QSS3BucketRegion: 280 | Default: us-east-1 281 | Description: The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value. 282 | Type: String 283 | QSS3KeyPrefix: 284 | AllowedPattern: ^[0-9a-zA-Z-/]*$ 285 | ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). 286 | Default: quickstart-microsoft-wapadfs/ 287 | Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). 288 | Type: String 289 | RDGWCIDR: 290 | 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]))$ 291 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/x 292 | Description: Allowed CIDR Block for external access to the Remote Desktop Gateways 293 | Type: String 294 | RDGWInstanceType: 295 | AllowedValues: 296 | - t2.small 297 | - t2.medium 298 | - t2.large 299 | - t3.micro 300 | - t3.small 301 | - t3.medium 302 | - t3.large 303 | - t3.xlarge 304 | - t3.2xlarge 305 | - t3a.micro 306 | - t3a.small 307 | - t3a.medium 308 | - t3a.large 309 | - t3a.xlarge 310 | - t3a.2xlarge 311 | - m5.large 312 | - m5.xlarge 313 | - m5.2xlarge 314 | - m5.4xlarge 315 | - m5a.large 316 | - m5a.xlarge 317 | - m5a.2xlarge 318 | Default: m5.large 319 | Description: Amazon EC2 instance type for the Remote Desktop Gateway instances 320 | Type: String 321 | VPCCIDR: 322 | 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]))$ 323 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 324 | Default: 10.0.0.0/16 325 | Description: CIDR Block for the VPC 326 | Type: String 327 | WAPADFSInstanceType: 328 | AllowedValues: 329 | - t3.medium 330 | - t3.large 331 | - t3.xlarge 332 | - t3.2xlarge 333 | - m5.large 334 | - m5.xlarge 335 | - m5.2xlarge 336 | - m5.4xlarge 337 | Default: m5.large 338 | Description: Amazon EC2 instance type for the WAP and ADFS servers 339 | Type: String 340 | WAPADFSEnableAdvancedAudtingandMetrics: 341 | AllowedValues: 342 | - 'true' 343 | - 'false' 344 | Default: 'false' 345 | Description: Enable advanced auditing and metrics and upload them to CloudWatch using the Amazon Kinesis Agent for Microsoft Windows 346 | Type: String 347 | Conditions: 348 | IncludeRDGW: !Not 349 | - !Equals 350 | - !Ref NumberOfRDGWHosts 351 | - '0' 352 | UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] 353 | Resources: 354 | VPCStack: 355 | Type: AWS::CloudFormation::Stack 356 | Properties: 357 | TemplateURL: 358 | !Sub 359 | - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-aws-vpc/templates/aws-vpc.template.yaml' 360 | - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] 361 | S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] 362 | Parameters: 363 | AvailabilityZones: !Join 364 | - ',' 365 | - !Ref 'AvailabilityZones' 366 | NumberOfAZs: '2' 367 | PrivateSubnet1ACIDR: !Ref 'PrivateSubnet1CIDR' 368 | PrivateSubnet2ACIDR: !Ref 'PrivateSubnet2CIDR' 369 | PublicSubnet1CIDR: !Ref 'PublicSubnet1CIDR' 370 | PublicSubnet2CIDR: !Ref 'PublicSubnet2CIDR' 371 | VPCCIDR: !Ref 'VPCCIDR' 372 | ADStack: 373 | Type: AWS::CloudFormation::Stack 374 | Properties: 375 | TemplateURL: 376 | !Sub 377 | - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-activedirectory/templates/ad-1.template' 378 | - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] 379 | S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] 380 | Parameters: 381 | ADServer1InstanceType: !Ref 'ADServerInstanceType' 382 | ADServer1NetBIOSName: !Ref 'ADServer1NetBIOSName' 383 | ADServer1PrivateIP: !Ref 'ADServer1PrivateIP' 384 | ADServer2InstanceType: !Ref 'ADServerInstanceType' 385 | ADServer2NetBIOSName: !Ref 'ADServer2NetBIOSName' 386 | ADServer2PrivateIP: !Ref 'ADServer2PrivateIP' 387 | DataDriveSizeGiB: !Ref 'DataDriveSizeGiB' 388 | DomainAdminPassword: !Ref 'DomainAdminPassword' 389 | DomainAdminUser: !Ref 'DomainAdminUser' 390 | DomainDNSName: !Ref 'DomainDNSName' 391 | DomainNetBIOSName: !Ref 'DomainNetBIOSName' 392 | EnableAdvancedAudtingandMetrics: !Ref ADEnableAdvancedAudtingandMetrics 393 | PKI: !Ref 'PKI' 394 | PKIEnableAdvancedAudtingandMetrics: !Ref PKIEnableAdvancedAudtingandMetrics 395 | OrCaServerNetBIOSName: !Ref 'OrCaServerNetBIOSName' 396 | EntCaServerNetBIOSName: !Ref 'EntCaServerNetBIOSName' 397 | KeyPairName: !Ref 'KeyPairName' 398 | PrivateSubnet1ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet1AID' 399 | PrivateSubnet2ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet2AID' 400 | QSS3BucketName: !Ref 'QSS3BucketName' 401 | QSS3BucketRegion: !Ref 'QSS3BucketRegion' 402 | QSS3KeyPrefix: !Sub '${QSS3KeyPrefix}submodules/quickstart-microsoft-activedirectory/' 403 | VPCCIDR: !Ref 'VPCCIDR' 404 | VPCID: !GetAtt 'VPCStack.Outputs.VPCID' 405 | RDGWStack: 406 | Condition: IncludeRDGW 407 | Type: AWS::CloudFormation::Stack 408 | Properties: 409 | TemplateURL: 410 | !Sub 411 | - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}submodules/quickstart-microsoft-rdgateway/templates/rdgw-domain.template' 412 | - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] 413 | S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] 414 | Parameters: 415 | DomainAdminPassword: !Ref 'DomainAdminPassword' 416 | DomainAdminUser: !Ref 'DomainAdminUser' 417 | DomainDNSName: !Ref 'DomainDNSName' 418 | DomainMemberSGID: !GetAtt 'ADStack.Outputs.DomainMemberSGID' 419 | DomainNetBIOSName: !Ref 'DomainNetBIOSName' 420 | KeyPairName: !Ref 'KeyPairName' 421 | NumberOfRDGWHosts: !Ref 'NumberOfRDGWHosts' 422 | PublicSubnet1ID: !GetAtt 'VPCStack.Outputs.PublicSubnet1ID' 423 | PublicSubnet2ID: !GetAtt 'VPCStack.Outputs.PublicSubnet2ID' 424 | QSS3BucketName: !Ref 'QSS3BucketName' 425 | QSS3BucketRegion: !Ref 'QSS3BucketRegion' 426 | QSS3KeyPrefix: !Sub '${QSS3KeyPrefix}submodules/quickstart-microsoft-rdgateway/' 427 | RDGWInstanceType: !Ref 'RDGWInstanceType' 428 | RDGWCIDR: !Ref 'RDGWCIDR' 429 | VPCID: !GetAtt 'VPCStack.Outputs.VPCID' 430 | WAPADFSStack: 431 | Type: AWS::CloudFormation::Stack 432 | Properties: 433 | TemplateURL: 434 | !Sub 435 | - 'https://${S3Bucket}.s3.${S3Region}.${AWS::URLSuffix}/${QSS3KeyPrefix}templates/wap-adfs.template' 436 | - S3Region: !If [UsingDefaultBucket, !Ref 'AWS::Region', !Ref QSS3BucketRegion] 437 | S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] 438 | Parameters: 439 | DomainAdminUserSecret: !GetAtt 'ADStack.Outputs.ADSecretsArn' 440 | DomainController1IP: !Ref 'ADServer1PrivateIP' 441 | DomainController2IP: !Ref 'ADServer2PrivateIP' 442 | DomainDNSName: !Ref 'DomainDNSName' 443 | DomainMemberSGID: !GetAtt 'ADStack.Outputs.DomainMemberSGID' 444 | DomainNetBIOSName: !Ref 'DomainNetBIOSName' 445 | EnableAdvancedAudtingandMetrics: !Ref WAPADFSEnableAdvancedAudtingandMetrics 446 | KeyPairName: !Ref 'KeyPairName' 447 | PrivateSubnet1ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet1AID' 448 | PrivateSubnet2ID: !GetAtt 'VPCStack.Outputs.PrivateSubnet2AID' 449 | PublicSubnet1ID: !GetAtt 'VPCStack.Outputs.PublicSubnet1ID' 450 | PublicSubnet2ID: !GetAtt 'VPCStack.Outputs.PublicSubnet2ID' 451 | QSS3BucketName: !Ref 'QSS3BucketName' 452 | QSS3BucketRegion: !Ref 'QSS3BucketRegion' 453 | QSS3KeyPrefix: !Ref 'QSS3KeyPrefix' 454 | VPCCIDR: !Ref 'VPCCIDR' 455 | VPCID: !GetAtt 'VPCStack.Outputs.VPCID' 456 | WAPADFSInstanceType: !Ref 'WAPADFSInstanceType' 457 | -------------------------------------------------------------------------------- /templates/wap-adfs.template: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Description: >- 3 | This template deploys two Web Application Proxy servers into public subnets in each 4 | availability zone, as well as two ADFS servers into the private subnets in each 5 | availability zone. The Active Directory domain being joined to must include a server 6 | with the Certificate Authority role and the Secret ARN account must be able to create and deploy certificates. 7 | **WARNING** This template creates Amazon EC2 Windows instances and related resources. You will 8 | be billed for the AWS resources used if you create a stack from this template. (qs-1qup6rai9) 9 | Metadata: 10 | cfn-lint: 11 | config: 12 | ignore_checks: 13 | - W9006 14 | - E9101 15 | QuickStartDocumentation: 16 | EntrypointName: "Launch into an existing VPC" 17 | Order: "2" 18 | AWS::CloudFormation::Interface: 19 | ParameterGroups: 20 | - Label: 21 | default: Network configuration 22 | Parameters: 23 | - VPCCIDR 24 | - VPCID 25 | - PrivateSubnet1ID 26 | - PrivateSubnet2ID 27 | - PublicSubnet1ID 28 | - PublicSubnet2ID 29 | - Label: 30 | default: Amazon EC2 configuration 31 | Parameters: 32 | - KeyPairName 33 | - LatestAmiId 34 | - EbsEncryptionKmsKeyId 35 | - Label: 36 | default: Microsoft Active Directory Domain Services configuration 37 | Parameters: 38 | - DirectoryType 39 | - DomainController1IP 40 | - DomainController2IP 41 | - DomainDNSName 42 | - DomainNetBIOSName 43 | - DomainAdminUserSecret 44 | - DomainMemberSGID 45 | - Label: 46 | default: ADFS and WAP configuration 47 | Parameters: 48 | - WAPADFSInstanceType 49 | - Adfs1NetBIOSName 50 | - Adfs2NetBIOSName 51 | - Wap1NetBIOSName 52 | - Wap2NetBIOSName 53 | - EnableAdvancedAudtingandMetrics 54 | - Label: 55 | default: AWS Quick Start configuration 56 | Parameters: 57 | - QSS3BucketName 58 | - QSS3BucketRegion 59 | - QSS3KeyPrefix 60 | ParameterLabels: 61 | Adfs1NetBIOSName: 62 | default: ADFS server 1 NetBIOS name 63 | Adfs2NetBIOSName: 64 | default: ADFS server 2 NetBIOS name 65 | Wap1NetBIOSName: 66 | default: WAP server 1 NetBIOS name 67 | Wap2NetBIOSName: 68 | default: WAP server 2 NetBIOS name 69 | DirectoryType: 70 | default: Active Directory Domain Services type 71 | DomainController1IP: 72 | default: IP the instances will use for DNS (must be accessible) 73 | DomainController2IP: 74 | default: IP the instances will use for DNS (must be accessible) 75 | DomainAdminUserSecret: 76 | default: Secret ARN containing Administrator credentials 77 | DomainDNSName: 78 | default: Domain DNS name 79 | DomainMemberSGID: 80 | default: Domain member security group ID 81 | DomainNetBIOSName: 82 | default: Domain NetBIOS name 83 | EbsEncryptionKmsKeyId: 84 | default: KMS Key for EBS encryption 85 | EnableAdvancedAudtingandMetrics: 86 | default: Advanced Auditing and Metrics for WAP and ADFS Instances 87 | KeyPairName: 88 | default: Key pair name 89 | LatestAmiId: 90 | default: SSM parameter to for latest AMI ID 91 | PrivateSubnet1ID: 92 | default: Private subnet 1 ID 93 | PrivateSubnet2ID: 94 | default: Private subnet 2 ID 95 | PublicSubnet1ID: 96 | default: Public subnet 1 ID 97 | PublicSubnet2ID: 98 | default: Public subnet 2 ID 99 | QSS3BucketName: 100 | default: Quick Start S3 bucket name 101 | QSS3BucketRegion: 102 | default: Quick Start S3 bucket region 103 | QSS3KeyPrefix: 104 | default: Quick Start S3 key prefix 105 | VPCCIDR: 106 | default: VPC CIDR 107 | VPCID: 108 | default: VPC ID 109 | WAPADFSInstanceType: 110 | default: WAP and ADFS server instance type 111 | Parameters: 112 | Adfs1NetBIOSName: 113 | Default: ADFS1 114 | Description: First ADFS Server NetBIOS Name 115 | Type: String 116 | Adfs2NetBIOSName: 117 | Default: ADFS2 118 | Description: Second ADFS Server NetBIOS Name 119 | Type: String 120 | DirectoryType: 121 | AllowedValues: 122 | - AWSManaged 123 | - SelfManaged 124 | Default: SelfManaged 125 | Description: Type of Active Directory the WAP / ADFS deployment will be integrated with, AWS Managed Microsoft AD or Self Managed AD 126 | Type: String 127 | DomainAdminUserSecret: 128 | Description: ARN for the Administrator credentials Secret with "username" and "password" key pairs. This account must be a member of Domain Admins with Self-Managed directories or a member of AWS Delegated Administrators with AWS Managed Microsoft AD. 129 | Type: String 130 | DomainController1IP: 131 | 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])$ 132 | Default: 10.0.0.10 133 | Description: IP of DNS server that can resolve Active Directory domain (Must be accessible) 134 | Type: String 135 | DomainController2IP: 136 | 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])$ 137 | Default: 10.0.32.10 138 | Description: IP of DNS server that can resolve Active Directory domain (Must be accessible) 139 | Type: String 140 | DomainDNSName: 141 | AllowedPattern: '^([a-zA-Z0-9]+[\.\-])+([a-zA-Z0-9])+$' 142 | Default: example.com 143 | Description: Fully qualified domain name (FQDN) of the domain the WAP / ADFS instances will join e.g. corp.example.com 144 | MaxLength: '25' 145 | MinLength: '3' 146 | Type: String 147 | DomainMemberSGID: 148 | Description: ID of the Domain Member Security Group (e.g., sg-7f16e910) 149 | Type: AWS::EC2::SecurityGroup::Id 150 | DomainNetBIOSName: 151 | AllowedPattern: '[a-zA-Z0-9\-]+' 152 | Default: example 153 | Description: NetBIOS name of the domain the WAP / ADFS instances will join (up to 15 characters) for users of earlier versions of Windows e.g. CORP 154 | MaxLength: '15' 155 | MinLength: '1' 156 | Type: String 157 | EbsEncryptionKmsKeyId: 158 | Default: alias/aws/ebs 159 | Description: The identifier of the AWS KMS key to use for Amazon EBS encryption. You can specify the KMS key using any of the following; Key ID, Key alias, Key ARN, Alias ARN 160 | Type: String 161 | EnableAdvancedAudtingandMetrics: 162 | AllowedValues: 163 | - 'true' 164 | - 'false' 165 | Default: 'false' 166 | Description: Enable advanced auditing and metrics and upload them to CloudWatch using the Amazon Kinesis Agent for Microsoft Windows 167 | Type: String 168 | KeyPairName: 169 | Description: Public/private key pairs allow you to securely connect to your instance after it launches 170 | Type: AWS::EC2::KeyPair::KeyName 171 | LatestAmiId: 172 | Default: /aws/service/ami-windows-latest/Windows_Server-2022-English-Full-Base 173 | Description: Systems Manager parameter value for latest Windows Server AMI 174 | Type: AWS::SSM::Parameter::Value 175 | PrivateSubnet1ID: 176 | Description: ID of the private subnet 1 in Availability Zone 1 (e.g., subnet-a0246dcd) 177 | Type: AWS::EC2::Subnet::Id 178 | PrivateSubnet2ID: 179 | Description: ID of the private subnet 2 in Availability Zone 2 (e.g., subnet-a0246dcd) 180 | Type: AWS::EC2::Subnet::Id 181 | PublicSubnet1ID: 182 | Description: ID of the public subnet 1 in Availability Zone 1 (e.g., subnet-e3246d8e) 183 | Type: AWS::EC2::Subnet::Id 184 | PublicSubnet2ID: 185 | Description: ID of the public subnet 2 in Availability Zone 2 (e.g., subnet-e3246d8e) 186 | Type: AWS::EC2::Subnet::Id 187 | QSS3BucketName: 188 | AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$ 189 | ConstraintDescription: Quick Start bucket name can include numbers, lowercase letters, uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). 190 | Default: aws-quickstart 191 | 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 (-). 192 | Type: String 193 | QSS3BucketRegion: 194 | Default: us-east-1 195 | Description: The AWS Region where the Quick Start S3 bucket (QSS3BucketName) is hosted. When using your own bucket, you must specify this value. 196 | Type: String 197 | QSS3KeyPrefix: 198 | AllowedPattern: ^[0-9a-zA-Z-/]*$ 199 | ConstraintDescription: Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). 200 | Default: quickstart-microsoft-wapadfs/ 201 | Description: S3 key prefix for the Quick Start assets. Quick Start key prefix can include numbers, lowercase letters, uppercase letters, hyphens (-), and forward slash (/). 202 | Type: String 203 | VPCCIDR: 204 | 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]))$ 205 | ConstraintDescription: CIDR block parameter must be in the form x.x.x.x/16-28 206 | Default: 10.0.0.0/16 207 | Description: CIDR Block of the VPC 208 | Type: String 209 | VPCID: 210 | Description: ID of the VPC (e.g., vpc-0343606e) 211 | Type: AWS::EC2::VPC::Id 212 | WAPADFSInstanceType: 213 | AllowedValues: 214 | - t3.medium 215 | - t3.large 216 | - t3.xlarge 217 | - t3.2xlarge 218 | - m5.large 219 | - m5.xlarge 220 | - m5.2xlarge 221 | - m5.4xlarge 222 | Default: m5.large 223 | Description: Amazon EC2 instance type for the WAP and ADFS Instances 224 | Type: String 225 | Wap1NetBIOSName: 226 | Default: WAP1 227 | Description: First WAP Server NetBIOS Name 228 | Type: String 229 | Wap2NetBIOSName: 230 | Default: WAP2 231 | Description: Second WAP Server NetBIOS Name 232 | Type: String 233 | Rules: 234 | SubnetsInVPC: 235 | Assertions: 236 | - Assert: !EachMemberIn 237 | - !ValueOfAll 238 | - AWS::EC2::Subnet::Id 239 | - VpcId 240 | - !RefAll 'AWS::EC2::VPC::Id' 241 | AssertDescription: All subnets must in the VPC 242 | Conditions: 243 | UsingDefaultBucket: !Equals [!Ref QSS3BucketName, 'aws-quickstart'] 244 | Resources: 245 | ServerRole: 246 | Type: AWS::IAM::Role 247 | Properties: 248 | Policies: 249 | - PolicyDocument: 250 | Version: '2012-10-17' 251 | Statement: 252 | - Effect: Allow 253 | Action: s3:GetObject 254 | Resource: 255 | - !Sub arn:${AWS::Partition}:s3:::aws-ssm-${AWS::Region}/* 256 | - !Sub arn:${AWS::Partition}:s3:::aws-windows-downloads-${AWS::Region}/* 257 | - !Sub arn:${AWS::Partition}:s3:::amazon-ssm-${AWS::Region}/* 258 | - !Sub arn:${AWS::Partition}:s3:::amazon-ssm-packages-${AWS::Region}/* 259 | - !Sub arn:${AWS::Partition}:s3:::${AWS::Region}-birdwatcher-prod/* 260 | - !Sub arn:${AWS::Partition}:s3:::patch-baseline-snapshot-${AWS::Region}/* 261 | - !Sub arn:${AWS::Partition}:s3:::aws-ssm-distributor-file-${AWS::Region}/* 262 | - !Sub arn:${AWS::Partition}:s3:::aws-ssm-document-attachments-${AWS::Region}/* 263 | PolicyName: SSMAgent 264 | - PolicyDocument: 265 | Version: '2012-10-17' 266 | Statement: 267 | - Effect: Allow 268 | Action: s3:ListBucket 269 | Resource: !Sub 270 | - 'arn:${AWS::Partition}:s3:::${S3Bucket}' 271 | - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] 272 | - Effect: Allow 273 | Action: s3:GetObject 274 | Resource: !Sub 275 | - 'arn:${AWS::Partition}:s3:::${S3Bucket}/${QSS3KeyPrefix}*' 276 | - S3Bucket: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Ref QSS3BucketName] 277 | - Effect: Allow 278 | Action: ssm:StartAutomationExecution 279 | Resource: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${WapAdfsAutomationDoc}:$DEFAULT 280 | - Effect: Allow 281 | Action: ssm:SendCommand 282 | Resource: 283 | - !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:*:document/AWS-RunRemoteScript 284 | - !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:*:document/AWS-RunPowerShellScript 285 | - Effect: Allow 286 | Action: ssm:SendCommand 287 | Resource: !Sub arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/* 288 | Condition: 289 | StringEquals: 290 | 'ssm:ResourceTag/aws:cloudformation:stack-name': !Ref AWS::StackName 291 | - Sid: ReadOperations 292 | Effect: Allow 293 | Action: 294 | - ec2:DescribeInstances 295 | - ssm:DescribeInstanceInformation 296 | - ssm:ListCommands 297 | - ssm:ListCommandInvocations 298 | Resource: '*' 299 | - Effect: Allow 300 | Action: cloudformation:SignalResource 301 | Resource: !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${AWS::StackName}/*' 302 | PolicyName: AWS-Mgmt-Quick-Start-Policy 303 | - PolicyDocument: 304 | Version: '2012-10-17' 305 | Statement: 306 | - Effect: Allow 307 | Action: 308 | - secretsmanager:GetSecretValue 309 | - secretsmanager:DescribeSecret 310 | Resource: 311 | - !Ref 'DomainAdminUserSecret' 312 | PolicyName: AWS-Mgd-AD-Secret-Policy 313 | Path: / 314 | ManagedPolicyArns: 315 | - !Sub 'arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore' 316 | - !Sub 'arn:${AWS::Partition}:iam::aws:policy/CloudWatchAgentServerPolicy' 317 | Tags: 318 | - Key: StackName 319 | Value: !Ref AWS::StackName 320 | AssumeRolePolicyDocument: 321 | Statement: 322 | - Effect: Allow 323 | Action: sts:AssumeRole 324 | Principal: 325 | Service: 326 | - ec2.amazonaws.com 327 | Version: '2012-10-17' 328 | ServerProfile: 329 | Type: AWS::IAM::InstanceProfile 330 | Properties: 331 | Roles: 332 | - !Ref 'ServerRole' 333 | Path: / 334 | WAP1EIP: 335 | Type: AWS::EC2::EIP 336 | Properties: 337 | InstanceId: !Ref 'WAP1' 338 | Domain: vpc 339 | WAP2EIP: 340 | Type: AWS::EC2::EIP 341 | Properties: 342 | InstanceId: !Ref 'WAP2' 343 | Domain: vpc 344 | WapAdfsAutomationDoc: 345 | Type: AWS::SSM::Document 346 | Properties: 347 | DocumentType: Automation 348 | Tags: 349 | - Key: StackName 350 | Value: !Ref AWS::StackName 351 | Content: 352 | schemaVersion: '0.3' 353 | description: 'Deploy WAP Instances with SSM Automation' 354 | parameters: 355 | Adfs1NetBIOSName: 356 | description: ADFS1 NetBIOS Name 357 | type: String 358 | Adfs2NetBIOSName: 359 | description: ADFS1 NetBIOS Name 360 | type: String 361 | DirectoryType: 362 | description: Type of Active Directory ADFS will be deployed to. 363 | type: String 364 | DomainAdminUserSecret: 365 | description: Secret ARN containing Administrator credentials 366 | type: String 367 | DomainController1IP: 368 | description: IP of DNS server that can resolve domain (Must be accessible) 369 | type: 'String' 370 | DomainController2IP: 371 | description: IP of DNS server that can resolve domain (Must be accessible) 372 | type: 'String' 373 | DomainDNSName: 374 | description: Domain DNS Name 375 | type: String 376 | DomainNetBIOSName: 377 | description: Domain NetBIOS Name 378 | type: String 379 | EnableAdvancedAudtingandMetrics: 380 | allowedValues: 381 | - 'true' 382 | - 'false' 383 | default: 'false' 384 | description: Enable advanced auditing and metrics 385 | type: String 386 | QSS3BucketName: 387 | description: Quick Start S3 Bucket Name 388 | type: String 389 | QSS3BucketRegion: 390 | description: Quick Start S3 bucket region 391 | type: String 392 | QSS3KeyPrefix: 393 | description: Quick Start S3 Key Prefix 394 | type: String 395 | StackName: 396 | description: CF Stack Name Input for cfn resource signal 397 | type: String 398 | URLSuffix: 399 | default: amazonaws.com 400 | description: AWS URL suffix 401 | type: String 402 | Wap1NetBIOSName: 403 | description: WAP1 NetBIOS Name 404 | type: String 405 | Wap2NetBIOSName: 406 | description: WAP2 NetBIOS Name 407 | type: String 408 | mainSteps: 409 | - name: InstanceIds 410 | action: aws:executeAwsApi 411 | onFailure: step:signalfailure 412 | inputs: 413 | Service: ec2 414 | Api: DescribeInstances 415 | Filters: 416 | - Name: 'tag:Name' 417 | Values: ['{{Adfs1NetBIOSName}}', '{{Adfs2NetBIOSName}}', '{{Wap1NetBIOSName}}', '{{Wap2NetBIOSName}}'] 418 | - Name: 'tag:aws:cloudformation:stack-name' 419 | Values: ['{{StackName}}'] 420 | - Name: 'instance-state-name' 421 | Values: ['running'] 422 | outputs: 423 | - Name: InstanceIds 424 | Selector: '$.Reservations..Instances..InstanceId' 425 | Type: 'StringList' 426 | nextStep: adfs1InstanceId 427 | - name: adfs1InstanceId 428 | action: aws:executeAwsApi 429 | onFailure: step:signalfailure 430 | inputs: 431 | Service: ec2 432 | Api: DescribeInstances 433 | Filters: 434 | - Name: 'tag:Name' 435 | Values: ['{{Adfs1NetBIOSName}}'] 436 | - Name: 'tag:aws:cloudformation:stack-name' 437 | Values: ['{{StackName}}'] 438 | - Name: 'instance-state-name' 439 | Values: ['running'] 440 | outputs: 441 | - Name: InstanceId 442 | Selector: '$.Reservations[0].Instances[0].InstanceId' 443 | Type: 'String' 444 | nextStep: adfs2InstanceId 445 | - name: adfs2InstanceId 446 | action: aws:executeAwsApi 447 | onFailure: step:signalfailure 448 | inputs: 449 | Service: ec2 450 | Api: DescribeInstances 451 | Filters: 452 | - Name: 'tag:Name' 453 | Values: ['{{Adfs2NetBIOSName}}'] 454 | - Name: 'tag:aws:cloudformation:stack-name' 455 | Values: ['{{StackName}}'] 456 | - Name: 'instance-state-name' 457 | Values: ['running'] 458 | outputs: 459 | - Name: InstanceId 460 | Selector: '$.Reservations[0].Instances[0].InstanceId' 461 | Type: 'String' 462 | nextStep: wap1InstanceId 463 | - name: wap1InstanceId 464 | action: aws:executeAwsApi 465 | onFailure: step:signalfailure 466 | inputs: 467 | Service: ec2 468 | Api: DescribeInstances 469 | Filters: 470 | - Name: 'tag:Name' 471 | Values: ['{{Wap1NetBIOSName}}'] 472 | - Name: 'tag:aws:cloudformation:stack-name' 473 | Values: ['{{StackName}}'] 474 | - Name: 'instance-state-name' 475 | Values: ['running'] 476 | outputs: 477 | - Name: InstanceId 478 | Selector: '$.Reservations[0].Instances[0].InstanceId' 479 | Type: 'String' 480 | nextStep: wap2InstanceId 481 | - name: wap2InstanceId 482 | action: aws:executeAwsApi 483 | onFailure: step:signalfailure 484 | inputs: 485 | Service: ec2 486 | Api: DescribeInstances 487 | Filters: 488 | - Name: 'tag:Name' 489 | Values: ['{{Wap2NetBIOSName}}'] 490 | - Name: 'tag:aws:cloudformation:stack-name' 491 | Values: ['{{StackName}}'] 492 | - Name: 'instance-state-name' 493 | Values: ['running'] 494 | outputs: 495 | - Name: InstanceId 496 | Selector: '$.Reservations[0].Instances[0].InstanceId' 497 | Type: 'String' 498 | nextStep: intializeInstances 499 | - name: intializeInstances 500 | action: aws:runCommand 501 | inputs: 502 | DocumentName: AWS-RunPowerShellScript 503 | InstanceIds: 504 | - '{{InstanceIds.InstanceIds}}' 505 | Parameters: 506 | commands: |- 507 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 508 | 509 | $S3BucketName = '{{ QSS3BucketName }}' 510 | $S3KeyPrefix = '{{ QSS3KeyPrefix }}' 511 | $S3BucketRegion = '{{QSS3BucketRegion}}' 512 | 513 | $CustomModules = @( 514 | 'Module-WAPADFS.psd1', 515 | 'Module-WAPADFS.psm1' 516 | ) 517 | 518 | $Modules = @( 519 | @{ 520 | Name = 'NetworkingDsc' 521 | Version = '8.2.0' 522 | }, 523 | @{ 524 | Name = 'ComputerManagementDsc' 525 | Version = '8.5.0' 526 | }, 527 | @{ 528 | Name = 'AuditPolicyDsc' 529 | Version = '1.4.0.0' 530 | } 531 | ) 532 | 533 | Write-Output 'Creating AWSQuickstart Directory' 534 | Try { 535 | $Null = New-Item -Path 'C:\AWSQuickstart\Module-WAPADFS' -ItemType 'Directory' -ErrorAction Stop 536 | } Catch [System.Exception] { 537 | Write-Output "Failed to create AWSQuickstart directory $_" 538 | Exit 1 539 | } 540 | 541 | $S3KeyPrefix = $S3KeyPrefix.Substring(0,$S3KeyPrefix.Length -1) 542 | Write-Output 'Downloading ADFS PowerShell Module' 543 | Foreach ($CustomModule in $CustomModules) { 544 | Try { 545 | $Null = Read-S3Object -BucketName $S3BucketName -Key "$($S3KeyPrefix)/scripts/Modules/Module-WAPADFS/$CustomModule" -File "C:\AWSQuickstart\Module-WAPADFS\$CustomModule" -Region $S3BucketRegion 546 | } Catch [System.Exception] { 547 | Write-Output "Failed to read and download $CustomModule.Name from S3 $_" 548 | Exit 1 549 | } 550 | } 551 | 552 | Write-Output 'Installing NuGet Package Provider' 553 | Try { 554 | $Null = Install-PackageProvider -Name 'NuGet' -MinimumVersion '2.8.5' -Force -ErrorAction Stop 555 | } Catch [System.Exception] { 556 | Write-Output "Failed to install NuGet Package Provider $_" 557 | Exit 1 558 | } 559 | 560 | Write-Output 'Setting PSGallery Respository to trusted' 561 | Try { 562 | Set-PSRepository -Name 'PSGallery' -InstallationPolicy 'Trusted' -ErrorAction Stop 563 | } Catch [System.Exception] { 564 | Write-Output "Failed to set PSGallery Respository to trusted $_" 565 | Exit 1 566 | } 567 | 568 | Write-Output 'Installing the needed Powershell DSC modules for this Quick Start' 569 | Foreach ($Module in $Modules) { 570 | Try { 571 | Install-Module -Name $Module.Name -RequiredVersion $Module.Version -ErrorAction Stop 572 | } Catch [System.Exception] { 573 | Write-Output "Failed to Import Modules $_" 574 | Exit 1 575 | } 576 | } 577 | 578 | $OS = Get-CimInstance -ClassName 'Win32_OperatingSystem' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty 'Caption' 579 | If ($OS -like 'Microsoft Windows Server 2022 *') { 580 | Write-Output 'Disabling TLS 1.3 client due to bug in ADFS Deployment on Windows Server 2022.' 581 | Try { 582 | New-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Client' -Force -ErrorAction Stop 583 | New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Client' -Name 'Enabled' -Value 0 –PropertyType DWORD -ErrorAction Stop 584 | New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Client' -Name 'DisabledByDefault' -Value 1 –PropertyType DWORD -ErrorAction Stop 585 | } Catch [System.Exception] { 586 | Write-Output "Failed to disable TLS 1.3 client $_" 587 | Exit 1 588 | } 589 | } 590 | CloudWatchOutputConfig: 591 | CloudWatchOutputEnabled: 'true' 592 | CloudWatchLogGroupName: !Sub '/aws/Quick_Start/${AWS::StackName}' 593 | nextStep: configureInstances 594 | - name: configureInstances 595 | action: aws:runCommand 596 | inputs: 597 | DocumentName: AWS-RunPowerShellScript 598 | InstanceIds: 599 | - '{{InstanceIds.InstanceIds}}' 600 | Parameters: 601 | commands: |- 602 | Try { 603 | Import-Module -Name 'C:\AWSQuickstart\Module-WAPADFS\Module-WAPADFS.psm1' -Force 604 | } Catch [System.Exception] { 605 | Write-Output "Failed to importing WAPADFS PS Module $_" 606 | Exit 1 607 | } 608 | Invoke-PreConfig 609 | Invoke-LcmConfig 610 | CloudWatchOutputConfig: 611 | CloudWatchOutputEnabled: 'true' 612 | CloudWatchLogGroupName: !Sub '/aws/Quick_Start/${AWS::StackName}' 613 | nextStep: configureMofs 614 | - name: configureMofs 615 | action: aws:runCommand 616 | inputs: 617 | DocumentName: AWS-RunPowerShellScript 618 | InstanceIds: 619 | - '{{InstanceIds.InstanceIds}}' 620 | Parameters: 621 | commands: |- 622 | Try { 623 | Import-Module -Name 'C:\AWSQuickstart\Module-WAPADFS\Module-WAPADFS.psm1' -Force 624 | } Catch [System.Exception] { 625 | Write-Output "Failed to importing WAPADFS PS Module $_" 626 | Exit 1 627 | } 628 | $EniConfig = Get-EniConfig 629 | $Secret = Get-SecretInfo -DomainNetBIOSName '{{ DomainNetBIOSName }}' -SecretArn '{{ DomainAdminUserSecret }}' 630 | $InstanceId = Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id' -UseBasicParsing | Select-Object -ExpandProperty Content 631 | $NameFromTag = Get-EC2Instance $InstanceId -ErrorAction Stop | Select-Object -ExpandProperty 'Instances' | Select-Object -ExpandProperty 'Tags' | Where-Object {$_.Key -eq 'Name'} | Select-Object -ExpandProperty 'Value' 632 | Set-DscConfiguration -Credentials $Secret.Credentials -DomainController1IP '{{DomainController1IP}}' -DomainController2IP '{{DomainController2IP}}' -DomainDNSName '{{ DomainDNSName }}' -GatewayAddress $EniConfig.GatewayAddress -InstanceNetBIOSName $NameFromTag -IpAddress $EniConfig.IpAddress -MacAddress $EniConfig.MacAddress 633 | CloudWatchOutputConfig: 634 | CloudWatchOutputEnabled: 'true' 635 | CloudWatchLogGroupName: !Sub '/aws/Quick_Start/${AWS::StackName}' 636 | nextStep: runMofs 637 | - name: runMofs 638 | action: aws:runCommand 639 | onFailure: step:signalfailure 640 | inputs: 641 | DocumentName: AWS-RunPowerShellScript 642 | InstanceIds: 643 | - '{{InstanceIds.InstanceIds}}' 644 | CloudWatchOutputConfig: 645 | CloudWatchOutputEnabled: 'true' 646 | CloudWatchLogGroupName: !Sub '/aws/Quick_Start/${AWS::StackName}' 647 | Parameters: 648 | commands: |- 649 | Try { 650 | Import-Module -Name 'C:\AWSQuickstart\Module-WAPADFS\Module-WAPADFS.psm1' -Force 651 | } Catch [System.Exception] { 652 | Write-Output "Failed to importing WAPADFS PS Module $_" 653 | Exit 1 654 | } 655 | Start-DscConfiguration 'C:\AWSQuickstart\ConfigInstance' -Wait -Verbose -Force 656 | 657 | Invoke-DscStatusCheck 658 | nextStep: InstallAdsf1 659 | - name: InstallAdsf1 660 | action: aws:runCommand 661 | inputs: 662 | DocumentName: AWS-RunPowerShellScript 663 | InstanceIds: 664 | - '{{adfs1InstanceId.InstanceId}}' 665 | Parameters: 666 | commands: |- 667 | Try { 668 | Import-Module -Name 'C:\AWSQuickstart\Module-WAPADFS\Module-WAPADFS.psm1' -Force 669 | } Catch [System.Exception] { 670 | Write-Output "Failed to importing WAPADFS PS Module $_" 671 | Exit 1 672 | } 673 | $Secret = Get-SecretInfo -DomainNetBIOSName '{{ DomainNetBIOSName }}' -SecretArn '{{ DomainAdminUserSecret }}' 674 | Install-FirstADFS -Credential $Secret.Credentials -DirectoryType '{{ DirectoryType }}' -Password $Secret.UserPassword -Username $Secret.Username 675 | If ('{{EnableAdvancedAudtingandMetrics}}' -eq 'true') { 676 | Set-DcAuditDscConfiguration 677 | Set-LogsAndMetricsCollection -Role "ADFS" -Stackname '{{StackName}}' 678 | } 679 | Start-CleanUp 680 | CloudWatchOutputConfig: 681 | CloudWatchOutputEnabled: 'true' 682 | CloudWatchLogGroupName: !Sub '/aws/Quick_Start/${AWS::StackName}' 683 | nextStep: InstallAdsf2 684 | - name: InstallAdsf2 685 | action: aws:runCommand 686 | inputs: 687 | DocumentName: AWS-RunPowerShellScript 688 | InstanceIds: 689 | - '{{adfs2InstanceId.InstanceId}}' 690 | Parameters: 691 | commands: |- 692 | Try { 693 | Import-Module -Name 'C:\AWSQuickstart\Module-WAPADFS\Module-WAPADFS.psm1' -Force 694 | } Catch [System.Exception] { 695 | Write-Output "Failed to importing WAPADFS PS Module $_" 696 | Exit 1 697 | } 698 | $Secret = Get-SecretInfo -DomainNetBIOSName '{{ DomainNetBIOSName }}' -SecretArn '{{ DomainAdminUserSecret }}' 699 | Install-AdditionalADFS -Credential $Secret.Credentials -DirectoryType '{{ DirectoryType }}' -FirstAdfsServerBIOSName '{{ Adfs1NetBIOSName }}' -Password $Secret.UserPassword 700 | If ('{{EnableAdvancedAudtingandMetrics}}' -eq 'true') { 701 | Set-DcAuditDscConfiguration 702 | Set-LogsAndMetricsCollection -Role "ADFS" -Stackname '{{StackName}}' 703 | } 704 | Start-CleanUp 705 | CloudWatchOutputConfig: 706 | CloudWatchOutputEnabled: 'true' 707 | CloudWatchLogGroupName: !Sub '/aws/Quick_Start/${AWS::StackName}' 708 | nextStep: InstallWap 709 | - name: InstallWap 710 | action: aws:runCommand 711 | inputs: 712 | DocumentName: AWS-RunPowerShellScript 713 | InstanceIds: 714 | - '{{wap1InstanceId.InstanceId}}' 715 | - '{{wap2InstanceId.InstanceId}}' 716 | Parameters: 717 | commands: |- 718 | Try { 719 | Import-Module -Name 'C:\AWSQuickstart\Module-WAPADFS\Module-WAPADFS.psm1' -Force 720 | } Catch [System.Exception] { 721 | Write-Output "Failed to importing WAPADFS PS Module $_" 722 | Exit 1 723 | } 724 | $Secret = Get-SecretInfo -DomainNetBIOSName '{{ DomainNetBIOSName }}' -SecretArn '{{ DomainAdminUserSecret }}' 725 | Install-WAP -Credential $Secret.Credentials -FirstAdfsServerBIOSName '{{ Adfs1NetBIOSName }}' -Password $Secret.UserPassword 726 | If ('{{EnableAdvancedAudtingandMetrics}}' -eq 'true') { 727 | Set-DcAuditDscConfiguration 728 | Set-LogsAndMetricsCollection -Role "WAP" -Stackname '{{StackName}}' 729 | } 730 | Start-CleanUp 731 | CloudWatchOutputConfig: 732 | CloudWatchOutputEnabled: 'true' 733 | CloudWatchLogGroupName: !Sub '/aws/Quick_Start/${AWS::StackName}' 734 | nextStep: CFNSignalEnd 735 | - name: CFNSignalEnd 736 | action: aws:branch 737 | inputs: 738 | Choices: 739 | - NextStep: signalsuccess 740 | Not: 741 | Variable: '{{StackName}}' 742 | StringEquals: '' 743 | - NextStep: sleepend 744 | Variable: '{{StackName}}' 745 | StringEquals: '' 746 | - name: signalsuccess 747 | action: aws:executeAwsApi 748 | isEnd: True 749 | inputs: 750 | Service: cloudformation 751 | Api: SignalResource 752 | LogicalResourceId: 'ADFS2' 753 | StackName: '{{StackName}}' 754 | Status: SUCCESS 755 | UniqueId: '{{adfs2InstanceId.InstanceId}}' 756 | - name: sleepend 757 | action: aws:sleep 758 | isEnd: True 759 | inputs: 760 | Duration: PT1S 761 | - name: signalfailure 762 | action: aws:executeAwsApi 763 | inputs: 764 | Service: cloudformation 765 | Api: SignalResource 766 | LogicalResourceId: 'ADFS2' 767 | StackName: '{{StackName}}' 768 | Status: FAILURE 769 | UniqueId: '{{adfs2InstanceId.InstanceId}}' 770 | WAP1: 771 | Type: AWS::EC2::Instance 772 | Properties: 773 | ImageId: !Ref 'LatestAmiId' 774 | IamInstanceProfile: !Ref 'ServerProfile' 775 | InstanceType: !Ref 'WAPADFSInstanceType' 776 | SubnetId: !Ref 'PublicSubnet1ID' 777 | Tags: 778 | - Key: Name 779 | Value: !Ref 'Wap1NetBIOSName' 780 | - Key: Domain 781 | Value: !Ref 'DomainDNSName' 782 | - Key: Role 783 | Value: Web Application Proxy 784 | BlockDeviceMappings: 785 | - DeviceName: /dev/sda1 786 | Ebs: 787 | VolumeSize: 60 788 | VolumeType: gp3 789 | Encrypted: true 790 | KmsKeyId: !Ref 'EbsEncryptionKmsKeyId' 791 | DeleteOnTermination: true 792 | SecurityGroupIds: 793 | - !Ref 'WAPSecurityGroup' 794 | - !Ref 'DomainMemberSGID' 795 | KeyName: !Ref 'KeyPairName' 796 | WAP2: 797 | Type: AWS::EC2::Instance 798 | Properties: 799 | ImageId: !Ref 'LatestAmiId' 800 | IamInstanceProfile: !Ref 'ServerProfile' 801 | InstanceType: !Ref 'WAPADFSInstanceType' 802 | SubnetId: !Ref 'PublicSubnet2ID' 803 | Tags: 804 | - Key: Name 805 | Value: !Ref 'Wap2NetBIOSName' 806 | - Key: Domain 807 | Value: !Ref 'DomainDNSName' 808 | - Key: Role 809 | Value: Web Application Proxy 810 | BlockDeviceMappings: 811 | - DeviceName: /dev/sda1 812 | Ebs: 813 | VolumeSize: 60 814 | VolumeType: gp3 815 | Encrypted: true 816 | KmsKeyId: !Ref 'EbsEncryptionKmsKeyId' 817 | DeleteOnTermination: true 818 | SecurityGroupIds: 819 | - !Ref 'WAPSecurityGroup' 820 | - !Ref 'DomainMemberSGID' 821 | KeyName: !Ref 'KeyPairName' 822 | ADFS1: 823 | Type: AWS::EC2::Instance 824 | Properties: 825 | ImageId: !Ref 'LatestAmiId' 826 | IamInstanceProfile: !Ref 'ServerProfile' 827 | InstanceType: !Ref 'WAPADFSInstanceType' 828 | SubnetId: !Ref 'PrivateSubnet1ID' 829 | Tags: 830 | - Key: Name 831 | Value: !Ref 'Adfs1NetBIOSName' 832 | - Key: Domain 833 | Value: !Ref 'DomainDNSName' 834 | - Key: Role 835 | Value: Active Directory Federation Services 836 | BlockDeviceMappings: 837 | - DeviceName: /dev/sda1 838 | Ebs: 839 | VolumeSize: 60 840 | VolumeType: gp3 841 | Encrypted: true 842 | KmsKeyId: !Ref 'EbsEncryptionKmsKeyId' 843 | DeleteOnTermination: true 844 | SecurityGroupIds: 845 | - !Ref 'ADFSSecurityGroup' 846 | - !Ref 'DomainMemberSGID' 847 | KeyName: !Ref 'KeyPairName' 848 | ADFS2: 849 | CreationPolicy: 850 | ResourceSignal: 851 | Timeout: PT60M 852 | Count: 1 853 | DependsOn: 854 | - ADFS1 855 | - WAP1 856 | - WAP2 857 | Type: AWS::EC2::Instance 858 | Properties: 859 | ImageId: !Ref 'LatestAmiId' 860 | IamInstanceProfile: !Ref 'ServerProfile' 861 | InstanceType: !Ref 'WAPADFSInstanceType' 862 | SubnetId: !Ref 'PrivateSubnet2ID' 863 | Tags: 864 | - Key: Name 865 | Value: !Ref 'Adfs2NetBIOSName' 866 | - Key: Domain 867 | Value: !Ref 'DomainDNSName' 868 | - Key: Role 869 | Value: Active Directory Federation Services 870 | BlockDeviceMappings: 871 | - DeviceName: /dev/sda1 872 | Ebs: 873 | VolumeSize: 60 874 | VolumeType: gp3 875 | Encrypted: true 876 | KmsKeyId: !Ref 'EbsEncryptionKmsKeyId' 877 | DeleteOnTermination: true 878 | SecurityGroupIds: 879 | - !Ref 'ADFSSecurityGroup' 880 | - !Ref 'DomainMemberSGID' 881 | KeyName: !Ref 'KeyPairName' 882 | UserData: 883 | Fn::Base64: !Sub 884 | - | 885 | 886 | $Params = @{ 887 | Adfs1NetBIOSName = '${Adfs1NetBIOSName}' 888 | Adfs2NetBIOSName = '${Adfs2NetBIOSName}' 889 | DirectoryType = '${DirectoryType}' 890 | DomainAdminUserSecret = '${DomainAdminUserSecret}' 891 | DomainController1IP = '${DomainController1IP}' 892 | DomainController2IP = '${DomainController2IP}' 893 | DomainDNSName = '${DomainDNSName}' 894 | DomainNetBIOSName = '${DomainNetBIOSName}' 895 | EnableAdvancedAudtingandMetrics = '${EnableAdvancedAudtingandMetrics}' 896 | QSS3BucketName = '${QSS3BucketName}' 897 | QSS3BucketRegion = '${QSS3BucketRegion}' 898 | QSS3KeyPrefix = '${QSS3KeyPrefix}' 899 | StackName = '${AWS::StackName}' 900 | URLSuffix = '${AWS::URLSuffix}' 901 | Wap1NetBIOSName = '${Wap1NetBIOSName}' 902 | Wap2NetBIOSName = '${Wap2NetBIOSName}' 903 | } 904 | Start-SSMAutomationExecution -DocumentName '${WapAdfsAutomationDoc}' -Parameter $Params 905 | 906 | - QSS3BucketName: !If [UsingDefaultBucket, !Sub '${QSS3BucketName}-${AWS::Region}', !Sub '${QSS3BucketName}'] 907 | QSS3BucketRegion: !If [UsingDefaultBucket, !Sub '${AWS::Region}', !Sub '${QSS3BucketRegion}'] 908 | WAPSecurityGroup: 909 | Type: AWS::EC2::SecurityGroup 910 | Properties: 911 | GroupDescription: Enable traffic to WAP Servers from the internet 912 | VpcId: !Ref 'VPCID' 913 | SecurityGroupIngress: 914 | - IpProtocol: tcp 915 | FromPort: 443 916 | ToPort: 443 917 | CidrIp: '0.0.0.0/0' 918 | - IpProtocol: tcp 919 | FromPort: 3389 920 | ToPort: 3389 921 | SourceSecurityGroupId: !Ref 'DomainMemberSGID' 922 | Tags: 923 | - Key: Name 924 | Value: WAPSecurityGroup 925 | ADFSSecurityGroup: 926 | Type: AWS::EC2::SecurityGroup 927 | Properties: 928 | GroupDescription: Enable traffic to ADFS servers 929 | VpcId: !Ref 'VPCID' 930 | SecurityGroupIngress: 931 | - IpProtocol: tcp 932 | FromPort: 443 933 | ToPort: 443 934 | CidrIp: !Ref 'VPCCIDR' 935 | - IpProtocol: tcp 936 | FromPort: 80 937 | ToPort: 80 938 | CidrIp: !Ref 'VPCCIDR' 939 | - IpProtocol: tcp 940 | FromPort: 445 941 | ToPort: 445 942 | CidrIp: !Ref 'VPCCIDR' 943 | - IpProtocol: tcp 944 | FromPort: 3389 945 | ToPort: 3389 946 | SourceSecurityGroupId: !Ref 'DomainMemberSGID' 947 | Tags: 948 | - Key: Name 949 | Value: ADFSSecurityGroup --------------------------------------------------------------------------------