AWS Architecture Blog
Field Notes: Enroll Existing AWS Accounts into AWS Control Tower
Originally published on April 21, 2020 to the Field Notes blog and updated in August 2020 with new prechecks to the account enrollment script.
Updated April 8, 2021 to reflect changes in the AWS Organizations service.
Last updated September 29, 2022: you can now enroll an existing account or register an organizational unit from the AWS Control Tower console. This blog can be used for enrolling the account(s) programmatically.
Since the launch of AWS Control Tower, customers have been asking for the ability to deploy AWS Control Tower in their existing AWS Organizations and to extend governance to those accounts in their organization.
We are happy that you can now deploy AWS Control Tower in your existing AWS Organizations. The accounts that you launched before deploying AWS Control Tower, what we refer to as unenrolled accounts, remain outside AWS Control Towers’ governance by default. These accounts must be enrolled in the AWS Control Tower explicitly.
When you enroll an account into AWS Control Tower, it deploys baselines and additional guardrails to enable continuous governance on your existing AWS accounts. However, you must perform proper due diligence before enrolling in an account. Refer to the Things to Consider section below for additional information.
In this blog, I show you how to enroll your existing AWS accounts and accounts within the unregistered OUs in your AWS organization under AWS Control Tower programmatically.
Background
Here’s a quick review of some terms used in this post:
- The Python script provided in this post. This script interacts with multiple AWS services, to identify, validate, and enroll the existing unmanaged accounts into AWS Control Tower.
- An unregistered organizational unit (OU) is created through AWS Organizations. AWS Control Tower does not manage this OU.
- An unenrolled account is an existing AWS account that was created outside of AWS Control Tower. It is not managed by AWS Control Tower.
- A registered organizational unit (OU) is an OU that was created in the AWS Control Tower service. It is managed by AWS Control Tower.
- When an OU is registered with AWS Control Tower, it means that specific baselines and guardrails are applied to that OU and all of its accounts.
- An AWS Account Factory account is an AWS account provisioned using account factory in AWS Control Tower.
- Amazon Elastic Compute Cloud (Amazon EC2) is a web service that provides secure, resizable compute capacity in the cloud.
- AWS Service Catalog allows you to centrally manage commonly deployed IT services. In the context of this blog, account factory uses AWS Service Catalog to provision new AWS accounts.
- AWS Organizations helps you centrally govern your environment as you grow and scale your workloads on AWS.
- AWS Single Sign-On (SSO) makes it easy to centrally manage access to multiple AWS accounts. It also provides users with single sign-on access to all their assigned accounts from one place.
Things to Consider
Enrolling an existing AWS account into AWS Control Tower involves moving an unenrolled account into a registered OU. The Python script provided in this blog allows you to enroll your existing AWS accounts into AWS Control Tower. However, it doesn’t have much context around what resources are running on these accounts. It assumes that you validated the account services before running this script to enroll the account.
Some guidelines to check before you decide to enroll the accounts into AWS Control Tower.
- An
AWSControlTowerExecution
role must be created in each account. If you are using the script provided in this solution, it creates the role automatically for you. - If AWS Config was ever enabled on the account you enroll, a
default
config recorder and delivery channel were created. Delete the configuration-recorder and delivery channel for the account enrollment to work. - Start with enrolling the dev/staging accounts to get a better understanding of any dependencies or impact of enrolling the accounts in your environment.
- Create a new Organizational Unit in AWS Control Tower and do not enable any additional guardrails until you enroll in the accounts. You can then enable guardrails one by one to check the impact of the guardrails in your environment.
- As an additional option, you can apply AWS Control Tower’s detective guardrails to an existing AWS account before moving them under AWS Control Tower governance. Instructions to apply the guardrails are discussed in detail in Extend AWS Control Tower governance using AWS Config Conformance Packs blog.
Prerequisites
Before you enroll your existing AWS account in to AWS Control Tower, check the prerequisites from AWS Control Tower documentation.
This Python script provided part of this blog, supports enrolling all accounts with in an unregistered OU in to AWS Control Tower. The script also supports enrolling a single account using both email address or account-id of an unenrolled account. Following are a few additional points to be aware of about this solution.
- Enable trust access with AWS Organizations for AWS CloudFormation StackSets.
- The email address associated with the AWS account is used as AWS SSO user name with default First Name Admin and Last Name User.
- Accounts that are in the root of the AWS Organizations can be enrolled one at a time only.
- While enrolling an entire OU using this script, the
AWSControlTowerExecution
role is automatically created on all the accounts on this OU. - You can enroll a single account with in an unregistered OU using the script. It checks for
AWSControlTowerExecution
role on the account. If the role doesn’t exist, the role is created on all accounts within the OU. - By default, you are not allowed to enroll an account that is in the root of the organization. You must pass an additional flag to launch a role creation stack set across the organization
- While enrolling a single account that is in the root of the organization, it prompts for additional flag to launch role creation stack set across the organization.
- The script uses CloudFormation Stack Set Service-Managed Permissions to create the
AWSControlTowerExecution
role in the unenrolled accounts.
How it works
The following diagram shows the overview of the solution.
- In your AWS Control Tower environment, access an Amazon EC2 instance running in the management account of the AWS Control Tower home Region.
- Get temporary credentials for
AWSAdministratorAccess
from AWS SSO login screen - Download and execute the
enroll_script.py
script - The script creates the
AWSControlTowerExecution
role on the target account using Automatic Deployments for a Stack Set feature. - On successful validation of role and organizational units that are given as input, the script launches a new product in Account Factory.
- The enrollment process creates an AWS SSO user using the same email address as the AWS account.
Setting up the environment
It takes up to 30 minutes to enroll each AWS account in to AWS Control Tower. The accounts can be enrolled only one at a time. Depending on number of accounts that you are migrating, you must keep the session open long enough. In this section, you see one way of keeping these long running jobs uninterrupted using Amazon EC2 using the screen
tool.
Optionally you may use your own compute environment where the session timeouts can be handled. If you go with your own environment, make sure you have python3
, screen
and a latest version of boto3
installed.
1. Prepare your compute environment:
- Log in to your AWS Control Tower with AWSAdministratorAccess role.
- Switch to the Region where you deployed your AWS Control Tower if needed.
- If necessary, launch a VPC using the stack here and wait for the stack to COMPLETE.
- If necessary, launch an Amazon EC2 instance using the stack here. Wait for the stack to COMPLETE.
- While you are on management account, increase the session time duration for AWS SSO as needed. Default is 1 hour and maximum is 12 hours.
2. Connect to the compute environment (one-way):
- Go to the EC2 Dashboard, and choose Running Instances.
- Select the EC2 instance that you just created and choose Connect.
- In Connect to your instance screen, under Connection method, choose EC2InstanceConnect (browser-based SSH connection) and Connect to open a session.
- Go to AWS Single Sign-On page in your browser. Click on your management account.
- Choose command line or programmatic access next to AWSAdministratorAccess.
- From Option 1 copy the environment variables and paste them in to your EC2 terminal screen in step 5 below.
3. Install required packages and variables. You may skip this step, if you used the stack provided in step-1 to launch a new EC2 instance:
- Install
python3
andboto3
on your EC2 instance. You may have to update boto3, if you use your own environment.
$ sudo yum install python3 -y
$ sudo pip3 install boto3
$ pip3 show boto3
Name: boto3
Version: 1.12.39
- Change to home directory and download the
enroll_account.py
script.
$ cd ~
$ wget https://raw.githubusercontent.com/aws-samples/aws-control-tower-reference-architectures/master/customizations/AccountFactory/EnrollAccount/enroll_account.py
- Set up your home Region on your EC2 terminal.
export AWS_DEFAULT_REGION=<AWSControlTower-Home-Region>
4. Start a screen
session in daemon mode. If your session gets timed out, you can open a new session and attach back to the screen.
$ screen -dmS SAM
$ screen -ls
There is a screen on:
585.SAM (Detached)
1 Socket in /var/run/screen/S-ssm-user.
$ screen -dr 585.SAM
5. On the screen terminal, paste the environmental variable that you noted down in step 2.
6. Identify the accounts or the unregistered OUs to migrate and run the Python script provide with below mentioned options.
- Python script usage:
usage: enroll_account.py -o -u|-e|-i -c
Enroll existing accounts to AWS Control Tower.
optional arguments:
-h, --help show this help message and exit
-o OU, --ou OU Target Registered OU
-u UNOU, --unou UNOU Origin UnRegistered OU
-e EMAIL, --email EMAIL
AWS account email address to enroll in to AWS Control Tower
-i AID, --aid AID AWS account ID to enroll in to AWS Control Tower
-c, --create_role Create Roles on Root Level
- Enroll all the accounts from an unregistered OU to a registered OU
$ python3 enroll_account.py -o MigrateToRegisteredOU -u FromUnregisteredOU
Creating cross-account role on 222233334444, wait 30 sec: RUNNING
Executing on AWS Account: 570395911111, USER+SCADMINT1@amazon.com
Launching Enroll-Account-vinjak-unmgd3
Status: UNDER_CHANGE. Waiting for 6.0 min to check back the Status
Status: UNDER_CHANGE. Waiting for 5.0 min to check back the Status
. .
Status: UNDER_CHANGE. Waiting for 1.0 min to check back the Status
SUCCESS: 111122223333 updated Launching Enroll-Account-vinjakSCchild
Status: UNDER_CHANGE. Waiting for 6.0 min to check back the Status
ERROR: 444455556666
Launching Enroll-Account-Vinjak-Unmgd2
Status: UNDER_CHANGE. Waiting for 6.0 min to check back the Status
. .
Status: UNDER_CHANGE. Waiting for 1.0 min to check back the Status
SUCCESS: 777788889999 updated
- Use AWS account ID to enroll a single account that is part of an unregistered OU.
$ python3 enroll_account.py -o MigrateToRegisteredOU -i 111122223333
- Use AWS account email address to enroll a single account from an unregistered OU.
$ python3 enroll_account.py -o MigrateToRegisteredOU -e JohnDoe+outside-ct-ou@amazon.com
You are not allowed by default to enroll an AWS account that is in the root of the organization. The script checks for the AWSControlTowerExecution
role in the account. If role doesn’t exist, you are prompted to use -c | --create-role
. Using -c
flag adds the stack instance to the parent organization root. Which means an AWSControlTowerExecution
role is created in all the accounts with in the organization.
Note: Ensure installing AWSControlTowerExecution
role in all your accounts in the organization, is acceptable in your organization before using -c
flag.
If you are unsure about this, follow the instructions in the documentation and create the AWSControlTowerExecution
role manually in each account you want to migrate. Rerun the script.
- Use AWS account ID to enroll a single account that is in root OU (need -c flag).
$ python3 enroll_account.py -o MigrateToRegisteredOU -i 111122223333 -c
- Use AWS account email address to enroll a single account that is in root OU (need -c flag).
$ python3 enroll_account.py -o MigrateToRegisteredOU -e JohnDoe+in-the-root@amazon.com -c
Cleanup steps
On successful completion of enrolling all the accounts into your AWS Control Tower environment, you could clean up the below resources used for this solution.
If you have used templates provided in this blog to launch VPC and EC2 instance, delete the EC2 CloudFormation stack and then VPC template.
Conclusion
Now you can deploy AWS Control Tower in an existing AWS Organization. In this post, I have shown you how to enroll your existing AWS accounts in your AWS Organization into AWS Control Tower environment. By using the procedure in this post, you can programmatically enroll a single account or all the accounts within an organizational unit into an AWS Control Tower environment.
Now that governance has been extended to these accounts, you can also provision new AWS accounts in just a few clicks and have your accounts conform to your company-wide policies.
Additionally, you can use Customizations for AWS Control Tower to apply custom templates and policies to your accounts. With custom templates, you can deploy new resources or apply additional custom policies to the existing and new accounts. This solution integrates with AWS Control Tower lifecycle events to ensure that resource deployments stay in sync with your landing zone. For example, when a new account is created using the AWS Control Tower account factory, the solution ensures that all resources attached to the account’s OUs are automatically deployed.