Govern Multi Account Account Closure and Suspension using custom solutions for Account Factory for Terraform (AFT)
The primary goal of this APG is to introduce a solution that leverages AWS Control Tower Account Factory Terraform (AFT) to streamline the account closure and suspension process. The solution aims to provide a reliable, efficient, and fast way to manage the decommissioning of AWS accounts from organizations.
The APG will highlight the integration of account closure and suspension custom solution with AFT to automate the account decommissioning process, eliminating the need for manual interventions. This approach will enhance the overall operational efficiency and ensure a standardized, secure, and consistent decommissioning process for AWS Control Tower.
By automating the account decommissioning using AWS Lambda function, the solution addresses the crucial need for rapid and secure decommissioning of AWS accounts at scale, without compromising on security standards.
As per documentation here, AFT sets up a Terraform pipeline that helps you provision and customize your accounts in AWS Control Tower. AFT follows a GitOps model to automate the processes of account provisioning in AWS Control Tower. You'll create an account request Terraform file, commit to repository, which provides the necessary input that triggers the AFT workflow for account provisioning. After account provisioning is complete, AFT can run additional customization steps, automatically.
The above architecture workflow digram illustrates both AWS Account creation as well as account closure workflow. This custom solution discussed here is for the account closure or suspension workflow because account closure and/or suspension is not part of standard AFT product. This custom solution enables that facility by creating an AWS Lambda Function which gets triggered by Amazon DynamoDB Streams
to close an existing AWS account created/imported by AFT (Account Factory for Terraform) and then finally moves the closed account to a designated Suspended OU
. Step by step solution workflow is as below -
The initial request to close an AWS Account can be initiated as soon as an account is fully created by AFT or imported by AFT.
The Operator initiates account closure request using AFT repository aft-account-request
. This is the repository informs AFT about all the metadata Operator has provided for account creation and/or closure. The Account metadata in aft-request-metadata
DynamoDB table. This table contains all the metadata operator has provided in the account-requests.tf table.
User pushes Terraform Code (Operator removes specific account module (module "account_request" {} from account-requests.tf)
which then informs AFT to remove an AWS account from AFT management control and finally close and move the account to an designated Suspended OU to Git repository (for example GitHub, Amazon CodeCommit etc).
The above operation triggers AFT to record account removal request in the aft-request-audit
DynamoDB table. This table has a DynamoDB stream (All AFT DynamoDB tables have streams enabled) already enabled which thereby triggers an AWS Lambda Function aft_suspend_account_ou
.
This Lambda function aft_suspend_account_ou ( which resides in the AFT Management Account ) now fetches below account metadata from aft-request-audit using new images of DDB streams -
AccName = newImage['control_tower_parameters']['M']['AccountName']['S'] # Account Name (required)
AccEmail = newImage['control_tower_parameters']['M']['AccountEmail']['S'] # Account Email (required)
SSOEmail = newImage['control_tower_parameters']['M']['SSOUserEmail']['S'] # SSO registration Email (optional)
SSOFirstName = newImage['control_tower_parameters']['M']['SSOUserFirstName']['S'] # SSO registration First Name (optional)
SSOLastName = newImage['control_tower_parameters']['M']['SSOUserLastName']['S'] # SSO registration Last Name (optional)
DDEvent = newImage['ddb_event_name']['S'] # DDB Event Name (required)
SourceOU = newImage['control_tower_parameters']['M']['ManagedOrganizationalUnit']['S'] # Parent OU information (required)
If Lambda function finds the value as REMOVE
for the DDEvent
parameter value, it fetches the relevant Account ID
by using the email
value from the aft-request-metadata
DynamoDB table and matching with AccEmail
parameter fetched from the aft-account-request
to confirm the Account
to be closed/suspended.
At this stage Lambda Function knows the right combination of Account ID
and the ParentOU
under which the Account is placed.
The Lambda Function now performs cross-account jump from AFT Management Account to the AWS Control Tower Account to perform AWS Organisation BOTO3 Calls to close the Account first and then finally move the account to a designation Suspended OU.
Name | Version |
---|---|
terraform | >= 0.15.0 |
aws | >= 3.15 |
Name | Version |
---|---|
archive | n/a |
aws | >= 3.15 |
No modules.
Name | Description | Type | Default | Required |
---|---|---|---|---|
aft-request-audit-table-encrption-key-id | DynamoDB table aft-request-audit table stream ARN | string |
"" |
no |
aft-request-audit-table-stream-arn | DynamoDB table aft-request-audit table stream ARN | string |
"" |
no |
aft_to_ct_cross_account_role_name | AFT Cross Account Role | string |
"AFTCrossAccountRole" |
no |
cloudwatch_log_group_retention | Lambda CloudWatch log group retention period | string |
"0" |
no |
ct_account_id | AFT Account ID | string |
"" |
no |
ct_destination_ou | Destination OU into which Account will be moved | string |
"" |
no |
ct_root_ou_id | CT Account Root OU ID | string |
"" |
no |
default_tags | Default tags for the module | map(string) |
{ |
no |
private1_subnet_id | Private Subnet 1 | string |
"" |
no |
private2_subnet_id | Private Subnet 2 | string |
"" |
no |
private_sg_id | Private Subnet Security Group | string |
"" |
no |
region | Default Region | string |
"us-west-2" |
no |
Name | Description |
---|---|
aft_alternate_sso_extract_lambda_arn | aft-alternate-sso-extract Lambda ARN |