Add more AWS Accounts ¶
Brief ¶
You can add new AWS accounts to your Leverage project by following the steps in this page.
Important
In the examples below, we will be using apps-prd as the account we will be adding and it will be created in the us-east-1 region.
Create the new account in your AWS Organization ¶
- Go to
management/global/organizations. - Edit the
locals.tffile to add the account to the localaccountsvariable.Note that theaccounts = { ... ... apps-prd = { email = "aws+apps-prd@yourcompany.com", parent_ou = "apps" } }appsorganizational unit (OU) is being used as the parent OU of the new account. If you need to use a new OU you can add it toorganizational_unitsvariable in the same file. - Run the OpenTofu workflow to apply the new changes. Typically that would be this:
leverage tofu init leverage tofu apply
Authentication error
Note this layer was first applied before using the boostrap user. Now, that we are working with SSO, credentials have changed. So, if this is the first account you add you'll probably get this error applying: "Error: error configuring S3 Backend: no valid credential sources for S3 Backend found."
In this case running leverage tf init -reconfigure will fix the issue.
-
Add the new account to the
<project>/config/common.tfvarsfile. The new account ID should have been displayed in the output of the previous step, e.g.:Note the id,aws_organizations_account.accounts["apps-prd"]: Creation complete after 14s [id=999999999999]999999999999....so please grab it from there and use it to update the file as shown below:
5. Since you are using SSO in this project, permissions on the new account must be granted before we can move forward. Add the right permissions to theaccounts = { [...] apps-prd = { email = "<aws+apps-prd@yourcompany.com>", id = "<add-the-account-id-here>" } }management/global/sso/account_assignments.tffile. For the example:Note your needs can vary, these permissions are just an example, please be careful with what you are granting here.# ------------------------------------------------------------------------- # apps-prd account # ------------------------------------------------------------------------- { account = var.accounts.apps-prd.id, permission_set_arn = module.permission_sets.permission_sets["Administrator"].arn, permission_set_name = "Administrator", principal_type = local.principal_type_group principal_name = local.groups["administrators"].name }, { account = var.accounts.apps-prd.id, permission_set_arn = module.permission_sets.permission_sets["DevOps"].arn, permission_set_name = "DevOps", principal_type = local.principal_type_group principal_name = local.groups["devops"].name },Apply these changes:
And you must update your AWS config file accordingly by running this:leverage tofu applyleverage aws configure sso
Good! Now you are ready to create the initial directory structure for the new account. The next section will guide through those steps.
Create and deploy the layers for the new account ¶
In this example we will create the apps-prd account structure by using the shared as a template.
Create the initial directory structure for the new account ¶
- Ensure you are at the root of this repository
- Now create the directory structure for the new account:
mkdir -p apps-prd/{global,us-east-1} - Set up the config files:
- Create the config files for this account:
cp -r shared/config apps-prd/config - Open
apps-prd/config/backend.tfvarsand replace any occurrences ofsharedwithapps-prd. - Do the same with
apps-prd/config/account.tfvars
- Create the config files for this account:
Create the OpenTofu Backend layer ¶
-
Copy the layer from an existing one:
cp -r shared/us-east-1/base-tf-backend apps-prd/us-east-1/base-tf-backendInfo
If the source layer was already initialized you should delete the previous OpenTofu setup using
sudo rm -rf .terraform*in the target layer's directory, e.g.rm -rf apps-prd/us-east-1/base-tf-backend/.terraform* -
Go to the
apps-prd/us-east-1/base-tf-backenddirectory, open theconfig.tffile and comment the S3 backend block. E.g.:We need to do this for the first apply of this layer.#backend "s3" { # key = "shared/tf-backend/terraform.tfstate" #} -
Now run the OpenTofu workflow to initialize and apply this layer. The flag
--skip-validationis needed here since the bucket does not yet exist.leverage tofu init --skip-validation leverage tofu apply - Open the
config.tffile again uncommenting the block commented before and replacingsharedwithapps-prd. E.g.:backend "s3" { key = "apps-prd/tf-backend/terraform.tfstate" } - To finish with the backend layer, re-init to move the
tfstateto the new location. Run:OpenTofu will detect that you are trying to move from a local to a remote state and will ask for confirmation.leverage tofu initEnterInitializing the backend... Acquiring state lock. This may take a few moments... Do you want to copy existing state to the new backend? Pre-existing state was found while migrating the previous "local" backend to the newly configured "s3" backend. No existing state was found in the newly configured "s3" backend. Do you want to copy this state to the new "s3" backend? Enter "yes" to copy and "no" to start with an empty state. Enter a value:yesand hit enter.
Create the security-base layer ¶
-
Copy the layer from an existing one: From the repository root run:
cp -r shared/us-east-1/security-base apps-prd/us-east-1/security-baseInfo
If the source layer was already initialized you should delete the previous OpenTofu setup using
sudo rm -rf .terraform*in the target layer's directory, e.g.rm -rf apps-prd/us-east-1/security-base/.terraform* -
Go to the
apps-prd/us-east-1/security-basedirectory and open theconfig.tffile replacing any occurrences ofsharedwithapps-prdE.g. this line should be:backend "s3" { key = "apps-prd/security-base/terraform.tfstate" } -
Init and apply the layer
leverage tf init leverage tf apply
Create the network layer ¶
-
Copy the layer from an existing one: From the root of the repository run this:
cp -r shared/us-east-1/base-network apps-prd/us-east-1/base-networkInfo
If the source layer was already initialized you should delete the previous OpenTofu setup using
sudo rm -rf .terraform*in the target layer's directory, e.g.rm -rf apps-prd/us-east-1/base-network/.terraform* -
Go to the
apps-prd/us-east-1/base-networkdirectory and open theconfig.tffile replacing any occurrences ofsharedwithapps-prd. E.g. this line should be:backend "s3" { key = "apps-prd/network/terraform.tfstate" } -
Open the file
locals.tfand set the new account's CIDRs.Note here only two AZs are enabled, if needed uncomment the other ones in the three structures.vpc_cidr_block = "172.19.0.0/20" azs = [ "${var.region}a", "${var.region}b", #"${var.region}c", #"${var.region}d", ] private_subnets_cidr = ["172.19.0.0/21"] private_subnets = [ "172.19.0.0/23", "172.19.2.0/23", #"172.19.4.0/23", #"172.19.6.0/23", ] public_subnets_cidr = ["172.19.8.0/21"] public_subnets = [ "172.19.8.0/23", "172.19.10.0/23", #"172.19.12.0/23", #"172.19.14.0/23", ]Do not overlap CIDRs!
Be careful when choosing CIDRs. Avoid overlapping CIDRs between accounts. If you need a reference on how to chose the right CIDRs, please see here.
Calculate CIDRs
To calculate CIDRs you can check this playbook.
-
Init and apply the layer
leverage tf init leverage tf apply -
Create the VPC Peering between the new account and the VPC of the Shared account. Edit file
shared/us-east-1/base-network/config.tfand add provider and remote state for the created account.Edit fileprovider "aws" { alias = "apps-prd" region = var.region profile = "${var.project}-apps-prd-devops" } data "terraform_remote_state" "apps-prd-vpcs" { for_each = { for k, v in local.apps-prd-vpcs : k => v if !v["tgw"] } backend = "s3" config = { region = lookup(each.value, "region") profile = lookup(each.value, "profile") bucket = lookup(each.value, "bucket") key = lookup(each.value, "key") } }shared/us-east-1/base-network/locals.tfand under...add the related structure:# # Data source definitions #Edit file# # Data source definitions # apps-prd-vpcs = { apps-prd-base = { region = var.region profile = "${var.project}-apps-prd-devops" bucket = "${var.project}-apps-prd-terraform-backend" key = "apps-prd/network/terraform.tfstate" tgw = false } }shared/us-east-1/base-network/vpc_peerings.tf(if this is your first added account the file won´t exist, please crate it) and add the peering definition:Apply the changes (be sure to CD into# # VPC Peering: AppsPrd VPC => Shared VPC # module "vpc_peering_apps_prd_to_shared" { source = "github.com/binbashar/terraform-aws-vpc-peering.git?ref=v6.0.0" for_each = { for k, v in local.apps-prd-vpcs : k => v if !v["tgw"] } providers = { aws.this = aws aws.peer = aws.apps-prd } this_vpc_id = module.vpc.vpc_id peer_vpc_id = data.terraform_remote_state.apps-prd-vpcs[each.key].outputs.vpc_id this_rts_ids = concat(module.vpc.private_route_table_ids, module.vpc.public_route_table_ids) peer_rts_ids = concat( data.terraform_remote_state.apps-prd-vpcs[each.key].outputs.public_route_table_ids, data.terraform_remote_state.apps-prd-vpcs[each.key].outputs.private_route_table_ids ) auto_accept_peering = true tags = merge(local.tags, { "Name" = "${each.key}-to-shared", "PeeringRequester" = each.key, "PeeringAccepter" = "shared" }) }shared/us-east-1/base-networklayer for doing this):leverage tofu init leverage tofu apply
Done! ¶
That should be it. At this point you should have the following:
- A brand new AWS account in your AWS organization.
- Working configuration files for both existing layers and any new layer you add in the future.
- A remote OpenTofu State Backend for this new account.
- Roles and policies (SSO) that are necessary to access the new account.
- The base networking resources ready to host your compute services.
- The VPC peerings between the new account and shared
Next steps ¶
Now you have a new account created, so what else?
To keep creating infra on top of this binbash Leverage Landing Zone with this new account added, please check:
-
Check common use cases in Playbooks
-
Review the binbash Leverage architecture
-
Go for EKS!