Accounts & Organizations
Tags: aws, terraform, devops
Published: 2023-03-31 13:44:14

When setting up your AWS account, it's easy to jump right in and start deploying resources, following tutorials, and becoming familiar with your account. 

Pause though! 

It's important to remember to remove specific resources when you're finished with them to avoid surprise bills later.

## Billing Alerts

To avoid this unpleasant surprise, it's a good idea to set up a billing alert for a specific amount each month. You can do this by navigating to AWS Billing Budgets and creating a budget using AWS's preconfigured templates. Choose an amount that you're comfortable with, such as $100 per month.

Navigate to `[AWS Billing Budgets](https://console.aws.amazon.com/billing/home?#/budgets/overview)` where you can easily create a Budget using AWS configured templates. 

![Create a Budget Alert](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hm95rxtag1noiiru2ddy.png)

Now that you won't be caught off guard by unexpected charges, let's configure your organization.

## AWS Organizations

While you have your primary account, it's recommended to create a separate AWS account for each project. This keeps everything related to the project grouped together, both from a budget and resource perspective. When you're finished with a project, you can simply delete the resources in the account and shut it down.

To manage multiple AWS accounts more easily, you can use [AWS Organizations](https://console.aws.amazon.com/organizations/v2/home/accounts), which allows you to consolidate multiple accounts and centrally manage and control them. There is no additional cost to set up AWS Organizations, so it's highly recommended.

### Project OUs

Within AWS Organizations you can organize your multiple accounts into Organizational Units, i.e OUs. These are like folders to keep all of your related accounts in. 

When kicking off a project, I look at having the following three main AWS accounts:

- Production
- Development
- Shared Services

The Production and Development accounts are straightforward: code is deployed to the Development account, tested, and then promoted to Production. The Shared Services account is more complex, as it hosts resources used by both the Production and Development accounts. 

For example, if you're purchasing a domain name, you would register it within the Shared Services account, which would then point the domain to the appropriate accounts so that they can use the primary domain. This keeps the Production account from pointing subdomains back down to Development.

When creating an account, there are a few rules of thumb:

1. Add tags - I usually add a project and environment tag.
2. Account Email - I will use email subaddressing, also known as plus sign (+), to create accounts with; but don't login and setup a password with them. We will utilize AWS SSO service for that.

![Adding an AWS Account](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g6l6doh92v6fv7qfsrbr.png)

Now after setting up my accounts, I have the following organization unit:

![Organization Unit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42bumy5sfn6bf2zi1r7o.png)

## Infrastructure As Code

While setting up accounts I tend to do manually, you can also programmatically do this using Terraform. You could build out scripts that allow you to have a project template which you can run each time you have a new project idea.

```
provider "aws" {
  region = "us-east-1"
}

resource "aws_organizations_account" "root" {
  name = "my-root-account"
  email = "my-root-account@fake.com"
}

resource "aws_organizations_organizational_unit" "ou" {
  name = "holy city paddle"
  parent_id = aws_organizations_account.root.id
}

resource "aws_organizations_account" "prod" {
  name = "hcp-prod"
  email = "my-root-account+hcp-prod@fake.com"
  parent_id = aws_organizations_organizational_unit.ou.id
}

resource "aws_organizations_account" "dev" {
  name = "hcp-dev"
  email = "my-root-account+hcp-dev@fake.com"
  parent_id = aws_organizations_organizational_unit.ou.id
}

resource "aws_organizations_account" "shared" {
  name = "hcp-shared"
  email = "my-root-account+hcp-shared@fake.com"
  parent_id = aws_organizations_organizational_unit.ou.id
}
```