Windows 2016: Auto Domain Join using EC2Launch and Sysprep
Sysprep is a utility used by Microsoft Windows servers as a way to strip all of an images unique properties such as the server SID, the server name, the event logs, specific drivers, etc.. from an image, allowing you to then bundle the operating system in a way that will allow a new server to be auto configured upon its first boot when instantiated using the bundled image. Sysprep allows a windows server to set properties like the host name, joining an Active Directory domain, and setting other unique properties automatically, on first boot, that usually take configuration time from a systems administrator when a new server is provisioned.
The purpose of this tutorial is to create a Windows based AMI that has been packaged properly using EC2Launch combined with the Micorosoft Sysprep utility. On instance provisioning, the instance will perform the specified Sysprep tasks, and then automatically join the instance to your organizations Active Directory Domain. Automatically joining a domain in AWS can be accomplished in a variety of ways. The recommended way would be to use Secure Systems Manager (SSM) to automatically join a domain that has been extended via the the use of one of the AWS AD Directory Services or the AWS AD connector. However if your organization doesn't utilize either SSM, AD Directory Services, or the AD Connector proxy then we still can enable the automatic domain join capabilities of Windows by using traditional methods.
EC2Launch Directory Location
For the purpose of this tutorial, or any document referencing the EC2Launch application directory, it should be understood that the ProgramData directory is hidden by default. Browsing your C:\ by default will not reveal the ProgramData directory. In order to see the contents of the directory, you can manually browse to the directory location of C:\ProgramData in your explorer window.
When you run Sysprep with the EC2Launch service, the system prevents drivers from being removed because the PersistAllDeviceInstalls setting is set to true in the C:\ProgramData\Amazon\EC2-Windows\Launch\Sysprep/Unattend file by default. This file is later referenced and utilized as the unattend.xml file used during the Sysprep provisioning process.
1. Active AWS Account:
As the purpose of this tutorial is to provide a way for Windows based instance launches to automatically join an Active Directory domain, we will need an active AWS account that we can log into in order to both create a Syspreped Server AMI, as well as test the auto Domain Join upon instance instantiation.
2. Active Directory Domain Controller:
In order to perform the following steps, access to an Active Directory Domain Controller (AD DC) is required. All of the steps outlined in this tutorial will be performed on a standalone Windows server image, that will enable the image to automatically join the Active Directory domain on instance launch.
3. AD Service Account:
The third thing that we will need is a service account that will has been provided rights to perform domain join operations. If a service account already exists, then your ready to go. If there is currently no service user account, or you wish to start with a fresh service user account, then follow the steps outlined here
Secrets Manager Credentials
Because we want to enable our newly provisioned Windows instances to possess the ability to automatically be joined to the domain on launch, and because we don't want to hard code the service account credentials into a file on the image, we are going to store our credentials instead, in the Secrets Manager service. Secrets Manager provides an encrypted store that securely stores credentials or other data, while still allowing authorized resources to easily retrieve those credentials or data easily. In order to store the service account credentials, follow the tutorial found here to store a secret containing a ServiceAccount and Password key with their appropriate values. Once you have created the secret, notate the name you selected for the secret, it will be used in a later step.. In the Secrets Manager Document, the secret name for example was Windows/ServiceAccount/DomainJoin.
Creating an EC2 Role for AD
The next thing we need to do is to create a custom policy, and a new role that we will assign to our Windows EC2 instances that we are launching. The policy that will be included in the role, will simply allow the launched EC2 instance access to the Secrets Manager service which will use later in this tutorial. The Secrets Manager is where we are storing our Active Directory Service Account Credentials as noted in the previous step.
1. Create Custom Secrets Manager Policy:
In order to create a Role that our Windows EC2 instances will use, first we need to construct a custom managed policy that will allow read only access to the Secrets Manager Service. By default the only Secrets Manager policy that AWS provides is a Read/Write Policy. Because we want to be as restrictive as possible, we need to create a custom policy that will allow Read Only access. In order to create the policy, follow the steps outlined in the Creating Policies Tutorial Found Here.. Construct the policy to allow all List and Read operations on the Secrets Manager service.
2. Create Custom EC2 Role:
Now that we have our Policy, Follow the steps outlined in the Creating Roles Tutorial Found Here to create a custom EC2 role that will utilize the policy that we just created. When creating the Role, Choose EC2 as the service, then choose the new custom policy that we created in the last step as the policy to be applied. Finally Review and Create the new Role.
Instantiate Windows 2016
The next step will we will need to perform is to launch a Windows Server 2016 or Newer EC2 Instance. This instance will become the base image that we will use to Sysprep and prepare for automatic domain registration upon launch.
1. Log into your AWS account:
Open a browser window and visit the AWS Console Page
2. Locate and navigate to the EC2 Service:
From the top left side of the navigational menu bar, click on the Services menu, and then choose EC2 by either navigating to the section of the listed services, or by typing the first few letters of the service name in the search box, and then choosing it from the filtered list.
3. Launch Windows 2016 Instance:
First we need to launch an Instance of using the Windows 2016 or Newer AMI. To do this, from the EC2 dashboard click the Launch Instance button. In the AMI selection view, choose an AMI containing Windows Server 2016 or a version newer to 2016. For the rest of the settings you can choose whats appropriate and launch the instance.
Windows 2012 Instances:
The process for Windows Server 2012 is slightly different then this process. The tutorial to sysprep on Windows Server 2012 R2 or earlier versions can be found here.
Apply Custom Role
Be sure that during the launch process you select the custom Role that we created earlier to be applied to the instance. If you forget to perform this step, then your instance will not be able to retrieve the service account credentials from the Secrets Manager, and the domain join operation will fail. If you forget to select the Role during the creation process, then the role can be added and/or modified post launch from the EC2 dashboard.
DC Security Group
Active Directory requires that the following ports are open to allow DC to DC communication on a domain controller. Ensure that you have a security group set to allow traffic to the required ports from our VPC. To keep things simple, we will construct a single security group that allows access from our local subnet, and ensure that it is applied to our domain controller(s). This will ensure any new computer that we provision in our VPC will be able to connect with Active Directory.
|tcp-udp/53||DNS (TCP used for Zone Transfers, UDP for standard queries)|
|udp/138||DFS, Group Policy|
|tcp/139||NetLogon, User Authentication|
|tcp-udp/445||SMB, CIFS, SMB2, NetLogin|
|tcp-udp/464||Kerberos modify password|
|tcp/3268-3269||LDAP, GC, Replication|
|tcp/9389||AD-DS Web, SOAP|
|tcp-udp/49152-65535||LDAP service Response ports|
Windows RDP Connection Details
Now that we have successfully launched our new Windows Server 2016 or newer version of Windows, we need to connect to the instance to configure it, prep it for domain join on instantiation, Sysprep it, and then create an AMI from the image for additional Windows Server provisioning.
1. Select Windows 2016 Instance:
Once the instance has been launched, from the EC2 dashboard, select the instance that was just launched from the Windows Server 2016 AMI. Once selected, from the Actions menu, choose Connect.
2. Get Password:
Once the Connect To Your Instance modal windows appears, click the button that says Get Password
3. Decrypt Password:
The password that is set on the Administrator account is a hash of the PEM key that was selected when the instance was launched. In order to decrypt the password that is set on the instance, either upload the PEM key used, or copy your private key value and paste it into the dialog box. Once pasted, click the Decrypt Password button.
4. Display Connection Details:
The last modal should display the connection information in its entirety. It also gives you the option of downloading the RDP file that has all of the connection information pre-populated. Once you have copied the details, or downloaded the RDP connection file, click the Close button.
Build your Windows 2016 Image
Now that we have the connection details, we can use our RDP application of choice to initiate a connection to the server. Once connected to the server, install the applications and configurations required for your image. Once the image is updated, with all applications installed and configured, it's time to prepare the image to be sysprepped or bundled for distribution.
1. Check for AWS PowerShell Tools:
One component that will need to be installed for later use is the AWS PowerShell tools. The PowerShell tools are required to make the request for the credentials stored in the Secrets Manager that the domain join process will utilize to perform the domain join. By default if you are using an image based off one of the AWS provided Windows AMI's then the PowerShell tools should be already installed. We can check to ensure that its installed by running the following cmdlet from the Windows PowerShell console:
Get-Module -ListAvailable *AWS*
PowerShell AWS Tools Installation:
If the PowerShell AWS tools are not installed, you can follow the documentation found here to install and set up the AWS PowerShell tools for Windows.
2. Administrator Credentials:
Once we have verified that the AWS PowerShell Tools are correctly installed, we need to devise a strategy around the local Administrative Login. When you sysprep the image, the Administrator password will be changed. In order to ensure that we always have a local administrator account to use to login and troubleshoot the instance, create a new user, and make that user a member of the Administrators group. The Sysprep process will not alter any other local users other than the Administrator User account. Because we are configuring a secondary Administrator we could change the Sysprep configuration to disable the Local Administrator password if we so desired. For now, create a new account, and add that account to the Administrators group. Be sure that the password set on the user is documented somewhere safe in an encrypted format.
3. Configure DNS:
Another thing that we will want to optionally do is to set the server images DNS settings to point its Primary DNS to our Active Directory Domain Controller. This will ensure that when the instance makes the request to join our domain, that it can resolve both the domain name as well as requests for domain service records from our domain. In order to do this, go into the Network Adapter Settings, right click on the primary adapter and select properties, then from the adapter properties, click on Internet Protocol Version 4(TCP/IPv4) and once highlighted, click on the Properties button. Last, in the General tab, leave the top section set to Obtain an IP address automatically, on the bottom, choose the option Use the following DNS server addresses and input the Preferred and Alternate DNS server settings. Unless you are specifying multiple domain controllers, the Alternate DNS server should be pointed to your VPC's default IP of x.x.x.2.
Sysprep DomainJoin Script:
Once we have verified that we have the AWS PowerShell tools install, next we need to add a script to our Windows instance image that will be called during the provisioning process when we launch new instances to perform the actual domain join operation.
1. Open the PowerShell Editor:
In order to add our script, lets first open the installed PowerShell Editor, or an editor of your choice. From the start menu, type PowerShell to search for all things powerShell related and from the list of options, choose the PowerShell Integrated Scripting Environment (ISE).
2. Create and Save the DomainJoin Script:
Now that we have the editor open, we can paste our script into the editor and save the file so that its saved on the instance image. Copy the script contents below and paste it into the PowerShell ISE. Once pasted, Save the file as:
# Domain name and the tld. In this example the domain is starfleet.aws $domain_name = "starfleet".ToUpper() $domain_tld = "aws" $secrets_manager_secret_id = "Windows/ServiceAccounts/DomainJoin" # Make a request to the secret manager $secret_manager = Get-SECSecretValue -SecretId $secrets_manager_secret_id # Parse the response and convert the Secret String JSON into an object $secret = $secret_manager.SecretString | ConvertFrom-Json # Construct the domain credentials $username = $domain_name.ToUpper() + "\" + $secret.ServiceAccount $password = $secret.Password | ConvertTo-SecureString -AsPlainText -Force # Set PS credentials $credential = New-Object System.Management.Automation.PSCredential($username,$password) # Get the Instance ID from the metadata store, we will use this as our computer name during domain registration. $instanceID = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/instance-id # Perform the domain join Add-Computer -DomainName "$domain_name.$domain_tld" -NewName "$instanceID" -Credential $credential -Passthru -Verbose -Force -Restart
PowerShell DomainJoin Script:
To see a detailed script explanation of this script and the actions performed within it, please see the Windows DomainJoin PowerShell Script documentation
3. Configure the DomainJoin Script to run on boot:
Next, now that we have the domain join script saved, we need to ensure that it is called during the provisioning phase of our EC2 instance launch. To ensure that the script gets fired off as part of the post Sysprep provisioning phase (Sysprep Specialize Phase), locate and open the SetupComplete.cmd file located in the C:\Windows\Setup\Scripts\SetupComplete.cmd directory path. This file can be opened with something simple like notepad. Once opened, add the following command to the very end of the SetupComplete.cmd file.
@REM *************** @REM Runs the Domain Join script to join this box to the Active Directory Domain powershell.exe -noexit -ExecutionPolicy Bypass "& 'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\DomainJoin.ps1'"
SetupComplete file Syntax:
Make sure to double check the path and file name of the DomainJoin Script that we created earlier. If you named the script anything other then DomainJoin.ps1, or if you put it in a different path then C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\ then update the powershell.exe command statement above accordingly.
Sysprep with EC2Launch
Now that we have the new domain join script and execution command configured, the next step is to bundle the OS for AMI distribution. To do so, first we have to kick off the Sysprep process to strip all of the unique properties of the image and complete the final bundling action.
1. Open the EC2Launch Properties Tool:
In order to start the Sysprep process, first we must set a few configuration options in the EC2Launch properties tool, that will define how our image is bundled and how Sysprep will operate when launched. From the Windows Start menu, type EC2 and look for the EC2LaunchService Settings application. Once found, launch the settings application so that we can set our EC2Launch properties.
2. EC2Launch General Properties:
Once the EC2Launch Service Property Tool opens, you will see a single tab across the top of the tool. To set our General options, first select the Set Wallpaper property. This option allows the instance information overlay to be displayed on top of the configured wallpaper.
Next, check the box next to Extend Boot Volume if not already selected. This option will ensure that if we launch an instance with a bigger root volume then our image currently has configured(30GB), that the excess storage on the root volume can be utilized by the launched instance. Last, choose the appropriate Administrator Password setting. For this example, because we created a secondary Administrator, and there is no Keep Existing option like there was in EC2Config used with earlier versions of Windows, we have 3 valid potential options. We don't want to store an unencrypted password in the Unattend.xml file (Specify), and we also don't want to pawn the process off to standard Sysprep (Do Nothing), so instead lets choose the Random option. Choosing Random, will tell the image to randomize the password based on the hash of the PEM file that we selected on launch. The password can then be un-encrypted from within the AWS console, just like it was in the Windows RDP Connection Details section above.
Administrator Password Setting
If the Specify option is selected for the Administrator Password, the specified password will be stored in the Sysprep answer file in its unencrypted clear text form.
If the Do Nothing option is selected, EC2Launch will do nothing and allow you to customize the Administrative Password handling through the Sysprep Unattend.xml file. If you don't specify a password in unattend.xml, the administrator account is disabled.
Once set, click the Shutdown with Sysprep button to start the Sysprep bundling process. Once you click the Shutdown with Sysprep button, a dialog will appear asking you to confirm that you want to start the Sysprep bundling process. Click Yes, and then wait for Sysprep to run through its bundling process.
Windows Sysprep Stages
When you click the Shutdown with Sysprep button and confirm that you want Sysprep to package the image, you will see a command window kick off that shows Windows performing the Sysprep bundle operations required to package up the Operating System. The instance will start Sysprep by first running the
C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule script. This script schedules the instance to initialize during the next boot and must be ran before initializing and running the second command
C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\SysprepInstance.ps1, which kicks off the actual Sysprep Process.
Sysprep performs the following steps:
1. Generalize: The tool removes image-specific information and configurations. For example, Sysprep removes the security identifier (SID), the computer name, the event logs, and specific drivers, to name a few. After this phase is completed, the operating system (OS) is ready to create an AMI.
2. Specialize: Plug and Play scans the computer and installs drivers for any detected devices. The tool generates OS requirements like the computer name and SID. Optionally, you can execute commands in this phase.
3. Out-of-Box Experience (OOBE): The system runs an abbreviated version of Windows Setup and asks the user to enter information such as a system language, the time zone, and a registered organization. When you run Sysprep with EC2Config, the answer file automates this phase.
4. Sysprep Drivers NOTE: When you run Sysprep with the EC2Config service, the system prevents drivers from being removed because the PersistAllDeviceInstalls setting is set to true by default.
Create a Sysprep Image AMI
Once completed, your image instance will be in a stopped state. Before we are ready to start launching instances off with this base, we need to create an AMI (Amazon Machine Image).
1. Create Image:
In order to create a usable AMI, navigate back to the EC2 Console in your AWS Account, and from the EC2 dashboard, select the stopped instance. From the Actions Menu, Click on the Image menu option, and from the sub menu, choose Create Image.
2. Name the AMI:
Next, in the modal pop up window, Name the Image, and type an Image description. Once complete Click the Create Image button to begin the AMI creation process.
3. Wait for the AMI to Bake:
Once the Create Image button has been clicked, a confirmation window will pop up. You can click the link in the confirmation window to be brought to the AMI view where you can monitor the process of your AMI creation process. Once the Status of the image changes from pending to available, the AMI is ready to be used to launch new instances.
Provisioning Windows Instances
Once the AMI status changes from pending status to available, we can now test out our new AMI by launching off a new instance using that AMI as the base AMI. To so, from the EC2 dashboard, Click the Launch Instance button to launch a new instance. In the Choose an Amazon Machine Image (AMI) screen, select My AMIs from the left side menu. Then from the list of available AMIs, choose the AMI that we just created and click the Select button. For the rest of the Instance options, select the instance type, and instance details, and launch the instance like any normal instance launch. Be sure that in the Configure Instance Details section, choose the Secrets Manager RO Role that we created in an earlier step to ensure that then newly launched instance can talk to the Secrets Manager Service, in order to get the domain credentials needed to auto join this instance to the domain.
Secrets Manager Access
In order for the automatic Domain Join to work properly, newly provisioned instances of Windows will need to have access to the Secrets Manager Service. Instances MUST either be launched with a public IP, have access to a NAT or IGW, or you must have a Secrets Manager VPC Endpoint configured. There must be a way for Windows to reach the Secrets Manager Service or the Domain Join operation will fail.
Instance Instantiation Time
Note that newly provisioned instances may take 5ish minutes to come on-line fully after provisioning. When the instance launches, it will run through the Sysprep operation, join itself to the domain, and reboot. This process can take a little time to complete normally.
Verify Automatic Domain Join
Once the instance has initialized and come online, it should now run through the Sysprep operation, and then automatically join itself to the domain. We can verify that this operation occurred successfully in 2 different ways.
1. Active Directory Users and Computers Console:
The first is checking Active Directory Users and Computers on one of our Domain Controllers. To do this, first log into your AWS console, and navigate to the EC2 console. Once there, look for the launched instance and note the instance-id. During the Sysprep process, the PowerShell script launched a call to the metadata service and grabbed the instance's instance-id. It used this ID to name the computer in AD on provisioning. Next, RDP into one of your DC's and open the Active Directory Users and Computers console. From the console, navigate to the Computers UO, and look for the noted test instance's ID.
2. Windows Instance:
The second way that we can verify that the domain join occurred successfully would be to attempt to log into the instance using a domain user. Once logged in via a domain user or a local Administrator account, from the start menu, Start to type This until This PC appears in the menu. Once located, right click and choose Properties
In the properties window of the Computer console, look at the Domain setting to ensure that its joined to the domain, and no longer part of the default Workgroup.
Perform the following steps in order to remove any computers that were automatically joined to the domain.
1. Terminate Windows Instances:
Log into your AWS console, and select any instances that were either used during the setup process outlined in this tutorial, or any other unwanted Windows instances. From the Actions menu, click on Instance State and then from the sub menu, select Terminate.
2. Remove Computer Objects from AD:
In your Active Directory Domain Controller, open Active Directory Users and Computers. From the main console, right click on the Computers OU, and from the list of computer objects, find and select the computer that has been terminated. Right click on the computer object, and from the available context menu, choose Delete. This will delete the object from Active Directory.
3. CleanUp Old Snapshots:
Next, navigate back to the EC2 console and click on Snapshots, browse through the list available Snapshots and select, any outdated or unwanted Snapshots that you want removed. Once selected, from the Actions menu, choose Delete.
4. CleanUp Old AMIs:
The last area we want to look is again in the AWS EC2 console. Navigate to the EC2 console and click on AMIs, browse through the list of available AMIs and select, any outdated or unwanted AMIs that you want removed. Once selected, from the Actions menu, choose Deregister.
By following the steps outlined in this tutorial, we should be all set to start provisioning Windows Instances without the administrative overhead of having to manually join them to our Active Directory domain !! Any new instance that is instantiated should automatically join our Windows Active Directory domain automatically at the time of provisioning.
No Additional Resources.