Create AWS Accounts with CloudFormation

Create AWS Accounts with CloudFormation

September 10, 2018 8 By Eric Shanks

In a previous post, we covered how to use an AWS Custom Resource in a CloudFormation template to deploy a very basic Lambda function. To expand upon this ability, lets use this knowledge to deploy something more useful than a basic Lambda function. How about we use it to create an AWS account? To my knowledge, the only way to create a new AWS account is to use the CLI or manually through the console. How about we use a custom resource to deploy a new account for us in our AWS Organization? Once this ability is available in a CloudFormation template, we could even publish it in the AWS Service Catalog and give our users an account vending machine capability.

Create the Lambda Function

Just as we did in the previous post, we’ll create a Lambda function, zip it up and place it into our S3 bucket. My function is Python 2.7 and can be found below.

As before, lets break down a few of the relevant sections of the code so you can see whats happening. To begin, lets look at the main lambda_handler. First we’ll initialize some of our variables and set our boto3 client to organizations so that we can create our accounts. After this, we’re going to set some variables in our Lambda function that will be passed in from our CloudFormation template (shown later in this post). After we set our variables, we’ll log them so that we can see what CloudFormation actually passed to our function.

Next, we’ll use boto3 to create an Organizational Unit on the fly. We’ll pass in the name of this OU from our CloudFormation template. To do this we’ll use the create_organizational_unit method and we’ll need to pass in the parent OU and the name of our new OU. When we’re done, we’ll log the ID of this OU and I’m setting a variable with the ID of this OU as well for later on in the function.

Now that we’ve created an OU, lets create the account. Again, we’ll use boto3 to call the create_account method. We’ll pass in an email address to be used for the new account and an account name. Again, when this is done, we’ll log the response which is the account status. After this, we’ll initiate a loop to check on the status of the account while it’s being created. Account creation isn’t an immediate thing, so its good to check on it until its either Successful or Failed. The loop checks the status, logs it and waits until its no longer IN_PROGRESS.

With any luck, our account has been created and we’ve got one more thing to do. Lets move the new account, into the new OU we created. Again, we’ll use boto3, but this time with the move_account method. I’m passing in the new AccountId we stored from our new create_account method, and the OUID we stored from our create_organizational_unit. I’m also specifying my root OU which will be different in your case. Fill it in, or do a search to find it in the Lambda function.

The account stuff is done, now we’re just setting some return data to be sent back to CloudFormation. The info I want sent back to CFn as an output is the accountID of our new account we created. After which we’ll send the data back to our signed S3 URL as we explained in the previous post about Custom Resorces.


Create the CloudFormation Template

If you’re following from the previous post, the only changes to the CloudFormation template are the variables being passed back and forth. For that reason we won’t go into much detail here, but the full template I used is found below.



Now that the coding is done, we can deploy the CloudFormation template. I’ve chosen to do this through the command line but you could do it through the console as well. My command line execution is as follows:



After a minute, you’ll see that the CFn stack has been deployed successfully, and that the output for the stack is the account number for the new AWS account.

If we open up the AWS Organizations console, we’ll see that the new account was created and the account number matches our output from the screenshot above.

As we look through the organizational units, we’ll see that a new OU was created and that our new account lives within that OU.


I hope that this post has shown you what kind of cool stuff you can do with a CloudFormation custom resource. Now think how neat this might be to put in AWS Service Catalog to deploy new accounts on demand. I will admit that this method does have some drawbacks, such as not being able to delete the stack and have the account deleted, but it is what it is.