Setup Account Factory for Terraform and enable default VPCs deletion (with bug fix on source code)
Published: 2023-10-02 14:37:13

In today's article, we will learn step by step how to deploy Account Factory for Terraform (AFT), alongside with that, we will enable Cloud Trail and default VPCs deletion feature to remove default VPC in all regions on every newly created account. After that we will have a little bug fix on `aws-ia` code since we are leveraging it.

I have raise the issue in here, you can check it out.
https://github.com/aws-ia/terraform-aws-control_tower_account_factory/issues/393

## Prerequisite
- An AWS Control Tower that already setup. If you haven't setup one, check it out [here](https://catalog.workshops.aws/control-tower/en-US/prerequisites)
- A Github account. 
- Terraform installed. If you haven't installed follow my guide on [this post] (https://dev.to/coangha21/eks-hand-on-series-introduction-and-setup-environment-b9h).

The following is what we will do in this article:
1. Setup OU and Account for AFT
2. Setup repositories
3. Deploy AFT to Control Tower
4. Enable Cloud Trail and default VPCs deletion feature with 
bugfix

Let's get into details!

## Setup OU and Account.
First, let's setup a separate OU and account for AFT as AWS recommended. Go to Control Tower console and in Organization tab, create a new OU and select `Root` as parent OU.
![Create new OU](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bkkqgyvts2556zjmkod5.png)

Next, choose Account Factory tab and provision a new account. Select account's OU as the OU you just created and skip `Account Factory customization` for now. 
![Provision new account](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9zv0a55ujitwy33xvejq.png)

Wait couple of minutes and you should have a new account in your organization.
## Setup repositories
Next, go to Github and create following 4 repositories:
- `aft-account-request` for handling account request
- `aft-global-customizations` for customizing all AFT managed accounts
- `aft-account-customizations` for specific customization on AFT managed accounts
- `aft-account-provisioning-customizations` for customizing account provision.
![Repositories](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/75yem194jeqm970fcxxq.png)

After that, please use the code that I already prepare to the repositories:
- [aft-account-request](https://github.com/vippr1237/aft-account-request)
- [aft-global-customization](https://github.com/vippr1237/aft-global-customizations)
- [aft-account-customizations](https://github.com/vippr1237/aft-account-customizations)
- [aft-account-provisioning-customizations](https://github.com/vippr1237/aft-account-provisioning-customizations)

Finally, clone `aws-ia` [AFT repository](https://github.com/aws-ia/terraform-aws-control_tower_account_factory) to your Github to create custom version for our own. I will show you later.

## Deploy AFT to Control Tower
Now, the main step, we will deploy AFT to our Control Tower. Before you start, you need to prepare:
- An account or role with Administrator policy on Control Tower management account (account that you deploy AWS Control Tower) and create access key for it.
- A terraform environment with the access key above.

If you have never done 2 things above, no worry, check out my [post] (https://dev.to/coangha21/eks-hand-on-series-introduction-and-setup-environment-b9h), it will guide you 
step by step how to do it.

After it all setup, create `main.tf` file and call to `aws-ia` module that you just clone in previous step. You can use the following code.
```
module "aft" {
  source = "github.com/<Your-Github-Org>/terraform-aws-control_tower_account_factory"
  # Required Vars
  ct_management_account_id    = "<your-ct-management-account-id"
  log_archive_account_id      = "<your-ct-logging-account-id>"
  audit_account_id            = "<your-ct-audit-account-id>"
  aft_management_account_id   = "<aft-management-account-id>"
  ct_home_region              = "<your-region>"
  # VCS Vars
  vcs_provider                                  = "github"
  account_request_repo_name                     = "<your-github-org>/aft-account-request"
  global_customizations_repo_name               = "<your-github-org>/aft-global-customizations"
  account_customizations_repo_name              = "<your-github-org>/aft-account-customization"
  account_provisioning_customizations_repo_name = "<your-github-org>/aft-account-provisioning-customization"
}
```
Insert correct information and run `terraform apply` to deploy the infrastructure, it will provision for us resources like Codebuild, CodePipeline, Step Function, Lambda, S3,... You can see overview architecture with picture below.
![AFT Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sk20wns9o8cup5rcq6a3.png)

Before moving to next step, you will need to update Codestar connection. AFT will automatically trigger by committing code to `aft-account-request` repo, in order for AFT to track the code change, it will use [AWS Codestar](https://docs.aws.amazon.com/codestar/).

**Access AFT Management account**, then go to `CodeCommit`
![Access CodeCommit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6t67pbe14h541mgggpho.png)

On the left, choose Settings > Connections, you will see a pending connection. Click on the connection and choose `Update pending connection`.
![Codestar conneciton](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axhb6nk53uwqwb00g5b0.png)

As you can see, I already enabled the connection, the steps is quite easy, so you can take it on yourself, just a few click and you will get it done.

Finally, go to `Codepipeline` and re-run the `ct-aft-account-provisioning-customizations` pipeline, it will create a step function for account provisioning customization, we need to do this so our account provisioning step funciton won't failed.
![Re-run pipeline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/obahztxqkdebfg6wjud4.png)

You can ignore the first pipeline, I created it for testing.

## Enable Cloud Trail and default VPCs deletion feature with 
bugfix
Enable Cloud Trail and default VPCs deletion feature by adding this 2 lines to the code block.
```
  aft_feature_delete_default_vpcs_enabled = true
  aft_feature_cloudtrail_data_events      = true
```
Run `terraform apply` to apply the infrastructure.
Now, let's create an account by AFT to see if everything is working as expected.
Edit `terraform/main.tf` file in `aft-account-request` repo, you should use the example code I provided on previous section.
```
module "sandbox_account_01" {
  source = "./modules/aft-account-request"

  control_tower_parameters = {
    AccountEmail = "<email-for-new-account>"
    AccountName  = "sandbox-account-01"
    # Syntax for top-level OU
    ManagedOrganizationalUnit = "Sandbox""
    SSOUserEmail     = "<email-for-sso>"
    SSOUserFirstName = "<sso first name>"
    SSOUserLastName  = "<sso last name>"
  }

  account_tags = {
    "ABC:Owner"       = "john.doe@amazon.com"
    "ABC:Division"    = "ENT"
    "ABC:Environment" = "Dev"
    "ABC:CostCenter"  = "123456"
    "ABC:Vended"      = "true"
    "ABC:DivCode"     = "102"
    "ABC:BUCode"      = "ABC003"
    "ABC:Project"     = "123456"
  }

  change_management_parameters = {
    change_requested_by = "John Doe"
    change_reason       = "testing the account vending process"
  }

  custom_fields = {
    custom1 = "a"
    custom2 = "b"
  }

  # account_customizations_name = "sandbox-customizations"
}
```
Commit code to the main branch and observe the pipeline. You should see the pipeline is running and new account is being provisioned.
![Account request pipeline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/debmnrwu37txsblollze.png)

After the pipeline have run successfully, it will add an record to `DynamoDB` table and trigger a list of functions to provisioned new account. You can check `CloudWatch Logs` to see how it run.
![Cloudwatch Logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u9yq7imuq9ybfxmccgz5.png)

![Request processor logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghfnt5e6f2ufvde700jb.png)

After couple of minutes, you should see your account had been provisioned, let check it if everything is good.
![Cloud Trail enabled](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59o80oxxbtp0jahwe27l.png)

Cloud Trail have been enabled, that's good news. Next, let's see if default VPCs have been delete in all regions.
![Default VPCs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/229kli14kck9pn4l0eqv.png)

Seem like it's not working, as mentioned above there is a bug in the function so we need to edit it a little bit. Go to file `src/aft_lambda/aft_feature_options/aft_delete_default_vpc.py` and in the part where we will iterate through regions to delete default VPCs, change the session like below:
![Fixing session bug](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59ahvqxdg4els1zxj3fq.png)

You can also check this [link](https://github.com/vippr1237/terraform-aws-control_tower_account_factory/commit/ac0d90ec231c48750cb8e09bed5917e21404b90e) for clearer view.
Now create another new account, you will see the default VPCs have been deleted.
![Default VPCs deleted in all regions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yf1lsz5hgxzlsuuzdz6z.png)

Ignore the region which have 1 VPC, I created it for testing.

Congrats! Now you have officially deployed your Account Factory for Terraform.

## Conclusion
This article just only guide you steps to deploy your first Account Factory for Terraform, you should read the [document](https://docs.aws.amazon.com/controltower/latest/userguide/aft-overview.html) to learn more about the tool. It's a very interesting tool, I recommend you to have a deep dive look into it and the value it bring to us.

You can checkout the code in here:
[AFT Deployment Repo](https://github.com/vippr1237/aft-deployment).
[Custom AFT module Repo](https://github.com/vippr1237/terraform-aws-control_tower_account_factory).
Also, check out my [Github](https://github.com/vippr1237?tab=repositories)!

See you in next post! Happy Hacking!