AWS Security Blog

How to Configure Your EC2 Instances to Automatically Join a Microsoft Active Directory Domain

Seamlessly joining Windows EC2 instances in AWS to a Microsoft Active Directory domain is a common scenario, especially for enterprises building a hybrid cloud architecture. With AWS Directory Service, you can target an Active Directory domain managed on-premises or within AWS. How to Connect Your On-Premises Active Directory to AWS Using AD Connector takes you through the process of implementing that scenario.

In this blog post, I will first show you how to get the Amazon EC2 launch wizard to pick up your custom domain-join configuration by default—including an organizational unit—when launching new Windows instances. I also will show you how to enable an EC2 Auto Scaling group to automatically join newly launched instances to a target domain. The Amazon EC2 Simple Systems Manager (SSM) plays a central role in enabling both scenarios.

Prerequisites and assumptions

  • You have an Active Directory domain managed in AWS or an on-premise domain exposed via AD Connector.
  • You have properly installed and configured the AWS CLI on your computer.
  • This guide applies to Windows-based instances only.

Part 1: Change the default domain-join configuration in the EC2 launch wizard

First, let’s get to know SSM. SSM is a service that enables you to remotely manage the configuration of your Windows EC2 instances. Through SSM, you can remotely run administrative scripts or commands on your Windows instances.

SSM is configured via JSON documents. An SSM JSON document lists commands you want to run on an instance, such as aws:domainJoin, which instructs SSM to join a Windows EC2 instance to a domain.

The following is a sample SSM document with an aws:domainJoin command configuration. Based on this sample, you can author an SSM document that contains your own domain-join configuration, including the organizational unit to which you want the server to be added. (Throughout this blog post, placeholder values are presented in red text. You should replace those values with your AWS information.)

{
        "schemaVersion": "1.0",
        "description": "Sample configuration to join an instance to a domain",
        "runtimeConfig": {
           "aws:domainJoin": {
               "properties": {
                  "directoryId": "d-1234567890",
                  "directoryName": "test.example.com",
                  "directoryOU": "OU=test,DC=example,DC=com",
                  "dnsIpAddresses": [
                     "198.51.100.1",
                     "198.51.100.2"
                  ]
               }
           }
        }
}

In this configuration document:

  • directoryId is the ID of a directory (or AD Connector) you created in AWS Directory Service.
  • directoryName is the name of the domain (for example, example.com).
  • directoryOU is the organizational unit for the domain.
  • dnsIpAddresses includes the IP addresses for the DNS servers you specified when you created your directory (or AD Connector) in Directory Service.

But what is the connection between SSM and the EC2 launch wizard? The first time you specify a domain in the EC2 launch wizard, the wizard generates the domain’s default SSM document. The default SSM document contains the necessary domain-join configuration, but without the directoryOU property. The launch wizard names a default SSM document using this convention: awsconfig_Domain_<directoryId>_<directoryName>. As soon as an instance you launch from the wizard is up and running, the wizard associates the specified domain’s default SSM document with it. As a part of the instance’s boot-up process, the EC2Config service applies the SSM document associated with your instance.

Notes: The commands or scripts specified in SSM documents run with administrative privilege on your instances because the EC2Config service runs in the LocalSystem account on Windows. For more information about this security consideration, see Managing Windows Instance Configuration.

The domain-join command in the default SSM document is executed exactly once as part of the instance’s first boot-up process. The command is not executed again when an instance is stopped and started, or when the instance reboots.

Replace the default SSM document

The following steps show how to replace the default SSM document for your domain with your own SSM document that includes the directoryOU property. Before starting, ensure you have fulfilled the prerequisites for using SSM, including configuring an AWS Identity and Access Management (IAM) role, which allows your launched EC2 instances to communicate with the SSM API. Also, ensure that you have installed and configured the AWS CLI on a computer so that you can execute the AWS CLI commands that follow. Make sure the effective AWS region for your AWS CLI setup is the same region where your target Active Directory domain is configured and the same region where you will launch your Windows EC2 instances.

To replace the default SSM document:

  1. Author a new SSM document based on the JSON sample shown above. Make sure you include the organizational unit that you want to be the default for your target domain in the EC2 launch wizard. Save the document to a file for reference in later steps.
  2. Verify whether the default SSM document exists for your domain by running the following command.
aws ssm get-document --name "awsconfig_Domain_<directoryId>_<directoryName>"

If the default document for your target domain does not exist, the command output will indicate an “Invalid Document” error message. This is simply an indication that you have never attempted to launch EC2 instances from the wizard to join the target directory, so the default SSM document for the directory has not been created yet. In such a case, you should skip to Step 5.

If the default document exists, it is because you previously launched instances from the wizard to join a target domain. In this case, the command produces JSON. The Content attribute represents the compact JSON content of the default SSM document created by the wizard. Such a default SSM document for a domain includes the aws:domainJoin command properties directoryId, directoryName, and dnsIpAddresses. However, it leaves out directoryOU—the organizational unit—as shown in the following JSON from the Content attribute.

{
        "schemaVersion": "1.0",
        "description": "Automatic domain-join configuration created by the EC2 console.",
        "runtimeConfig": {
           "aws:domainJoin": {
               "properties": {
                  "directoryId": "d-1234567890",
                  "directoryName": "test.example.com",
                  "dnsIpAddresses": [
                     "198.51.100.1",
                     "198.51.100.2"
                  ]
               }
           }
        }
}

Save the command output to a file (for example, awsconfig_Domain_<directoryId>_<directoryName>.json) for future reference.

  1. Run the following command to see whether the default SSM document is already associated with any instances.
aws ssm list-associations --association-filter-list key=Name,value="awsconfig_Domain_<directoryId>_<directoryName>"

If you have never launched instances to join your domain from the wizard, the command output will be an empty list of associations. Otherwise, the command returns a list of all the instances that were launched to join your domain from the wizard. Save the output to a file for your reference.

  1. Delete the current default SSM document. When you delete an SSM document, the document and all its associations with instances are deleted. Note that deleting the default SSM document does not impact or change a running instance that is associated with it.

Run the following command to delete the default document.

aws ssm delete-document --name "awsconfig_Domain_<directoryId>_<directoryName>"
  1. Finally, upload the SSM document you authored in Step 1 as the default document. You can do that by running the following command.
aws ssm create-document --content file://path/to/new-ssm-doc-withOU.json --name "awsconfig_Domain_<directoryId>_<directoryName>"

Note: If you are issuing the previous CLI command from a Linux or Mac computer, you must add a “/” at the beginning of the path (for example, file:///Users/username/new-ssm-doc-withOU.json).

After the create-document command successfully executes, you are done replacing the default SSM document with the SSM document you authored. The EC2 launch wizard will apply your new SSM configuration by default to any Windows instance launched to join your domain under the specified OU.

Now, let’s move to Part 2 of this blog post!

Part 2: Enable automatically joining an Active Directory domain for EC2 instances in an Auto Scaling group

Auto Scaling is a service that helps you ensure that you have the correct number of EC2 instances available to handle the load for your applications. Collections of EC2 instances are called Auto Scaling groups, and you can specify the minimum number of instances in each Auto Scaling group. Auto Scaling ensures that your group never goes below this size. Similarly, you can specify the maximum number of instances in each Auto Scaling group, and Auto Scaling ensures that your group never exceeds this size.

What if you want instances to join an Active Directory domain automatically when they are launched in an Auto Scaling group? What if you still need to set the organizational unit? The following steps show you how you can accomplish this by invoking SSM from a Windows PowerShell script when you boot up your instances.

Before proceeding, you must first author and upload an SSM document containing your domain-join configuration using the SSM create-document command, as described in Steps 1 and 5 in the Part 1 of this post. For the sake of clarity, I will use the name awsconfig_Domain_<directoryId>_<directoryName> to refer to the uploaded SSM document.

Step 1: Create a new IAM policy, copying the AmazonEC2RoleforSSM policy

In this step, you will create a new IAM policy with permissions to allow your instances to perform the ssm:CreateAssociation action, which will join each instance to your domain. The new policy will be based on the AWS-managed policy, AmazonEC2RoleforSSM.

To create this new IAM policy:

  1. Open the IAM console, and then click Policies. Click Create Policy.
  2. On the Create Policy page, click Copy an AWS Managed Policy.
  3. In the Search Policies field, type AmazonEC2RoleforSSM, and then click Select.
  4. In the Policy Name field, type the name AmazonEC2RoleforSSM-ASGDomainJoin.
  5. In the Policy Document editor, add the ssm:CreateAssociation permission, as highlighted in the following screenshot.Screenshot of adding the ssm:CreateAssociation permission
  6. Finally, click Validate Policy. If the policy is valid, click Create Policy.

Step 2: Create a new IAM role for EC2 instances in your Auto Scaling group

Next, you will create a new IAM role and attach the AmazonEC2RoleforSSM-ASGDomainJoin policy to it. This role and its attached policy will give permissions to your EC2 instances to communicate with the SSM service and execute different SSM service APIs. You will specify this role later on in the Auto Scaling launch configuration wizard.

To create this new IAM role:

  1. Open the IAM console, click Roles in the left pane, and then click Create New Role.
  2. On the Select Role Type page in the AWS Service Role section, choose Amazon EC2. This takes you to the Attach Policy page.
  3. In the Filter box, type AmazonEC2RoleforSSM-ASGDomainJoin. Choose the check box next to your policy, and then choose Attach Policy. This takes you to the Set Role Name and Review page.
  4. In the Role Name field, type EC2SSMRole-ASG, and then type a role description.
  5. Review the role details, and then choose Create Role.

Step 3: Create a new Auto Scaling launch configuration

This is the step where it all comes together. First, create an Auto Scaling launch configuration, which uses the IAM role you created:

  1. Open the EC2 console, and then click Launch Configurations under Auto Scaling in the left pane.
  2. Click Create Launch Configuration to start the Launch Configuration creation wizard. Choose a Windows Server Amazon Machine Image (AMI) and proceed to Step 2 of the wizard. Choose an instance type that matches your needs, and then proceed to Step 3 of the wizard, Configure Details.
  3. Type the appropriate configuration details, starting with the Name Of your launch configuration. For IAM role, select EC2SSMRole-ASG.
  4. Expand the Advanced Details section. Add a Windows PowerShell script that is to be executed when new instances are launched as the Auto Scaling group scales out. Customize the following script, copy it, and paste it in the User data field.
    <powershell>
    Set-DefaultAWSRegion -Region <region>
    Set-Variable -name instance_id -value (Invoke-Restmethod -uri http://169.254.169.254/latest/meta-data/instance-id)
    New-SSMAssociation -InstanceId $instance_id -Name "<ssmDocumentName>"
    </powershell>

To customize the preceding script:

  • <region> is the region in which you are creating your Auto Scaling launch configuration (for example, us-east-1).
  • <ssmDocumentName> is the name of the SSM document that you created earlier.

The script joins each instance to your domain by issuing the SSM API action ssm:CreateAssociation behind the scenes. This happens as a part of the boot-up process executed by EC2Config service. An important benefit of this approach is that you do not have to expose any domain credentials.

  1. Proceed to Step 4 of the Launch Configuration wizard, Add Storage. Specify your storage requirement, and then proceed to Step 5, Configure Security Group. In Step 5, you can either create a new security group or select an existing one and modify it. Whichever you choose, ensure that the security groups selected allow outbound access to the Internet over port 443 (HTTPS). This is necessary for EC2 instances in the Auto Scaling group to communicate with the SSM service. For more information about configuring security groups, see Amazon EC2 Security Groups for Windows Instances.

Step 4: Create an Auto Scaling group

In this step, you create an Auto Scaling group to launch one or more instances automatically based on the launch configuration you created:

  1. Open the EC2 console, and then choose Launch Configurations under Auto Scaling in the navigation pane.
  2. In the list of launch configurations, choose the launch configuration you created in Step 3.
  3. Choose Create Auto Scaling Group to start the Auto Scaling Group creation wizard.
  4. Type a Name for your Auto Scaling group. In the Network box, choose the VPC in which your Active Directory server or connector is deployed. In the Subnet box, choose a subnet in the VPC. Make sure the subnet you choose does not have network access control list rules to prevent it from communicating with your Active Directory server or connector.
  5. Choose Next: Configure Scaling Policies to configure the scaling policy.
  6. Choose Next: Configure Notifications to configure notifications for your Auto Scaling group.
  7. Configure tags to make it easier to identify auto scaled instances in the EC2 console. For example, you could type Name for a key and Auto Scaled for a value.
  8. Finish creating your Auto Scaling group. Choose Review and then click Create Auto Scaling Group.

Step 5: Verify Active Directory domain auto join

In this final step, you verify that your auto scaled instances are joined to your Active Directory domain:

  1. Open the EC2 console and click Instances in the navigation pane.
  2. Note the InstanceIds of all instances that have Name of Auto Scaled (based on the tag you specified in Step 4). Wait until Auto Scaled instances are in the Running state and their Status Checks show 2/2 Checks Passed (this means initialization is complete) before proceeding.
  3. Run the following AWS CLI command to list current associations of your new SSM document with running EC2 instances.
aws ssm list-associations --association-filter-list key=Name,value="awsconfig_Domain_<directoryId>_<directoryName>"
  1. Carefully review the JSON list of associations returned by the preceding command. For every association, check if the InstanceId attribute matches one of your auto scaled instances. If there’s a match, check the Overview. It should contain a subattribute named Status with a value of Success. If so, congratulations! This indicates that the SSM AD join command was executed successfully.
  2. Double-check with Microsoft Active Directory tools to ensure the auto scaled instances joined your domain.

Step 6: Schedule automatic cleanup of stale domain objects in your directory

As an Auto Scaling group scales out, instances are created and joined to your domain. It is important to note that as the Auto Scaling group scales in, instances are terminated, and the instances’ corresponding computer objects are not removed from your directory. Therefore, terminated instances will result in stale entries.

Though Active Directory can hold a large number of computer objects, it is a good practice to schedule a script to remove stale entries from your directory. Alternatively, you can set up a script to unjoin a computer from your domain, and have that script run before instance shutdown. The underlying assumption of the second approach is that instances in an Auto Scaling group are only shut down (and terminated) when they are no longer needed.

How you do this cleanup is up to you, and practices will differ from one administrator to another.

Conclusion

In this blog post, I showed you how to use your custom domain-join configuration with the EC2 launch wizard. I also explained how EC2 instances in Auto Scaling groups can be automatically joined to an Active Directory domain upon launch, and how it is necessary to schedule regular cleanup of stale computer objects in your directory. Central to all the above scenarios is SSM, which continues to evolve and add administrative control features over Windows and Linux EC2 instances alike.

If you have comments about this blog post, submit them in the “Comments” section below. If you have questions, please start a new forum thread on the EC2 forum.

– Moataz