What?


Let’s say we already have an AWS root account set up and want to add an environment, for example, production.

Problem 1. After creating the root account, the other AWS accounts are also created manually.

AWS accounts hierarchy looks like this:

Draw.io Diagram


Initialization

There is a repository where infrastructure is managed, for example infrastructure. And we have separate folders for each layer:

1 infrstructure 2| 3|--- 0-accounts 4|--- 1-environments 5|--- 2-products

These are the commands to initialize at first:

  1. cd infrastructure

  2. meta auth

  3. meta exec project-name account-name , in our case the account is for prod, so it will be meta exec project-name prod

  4. meta init

  5. terraform init

  6. terraform apply

During the 1st terraform apply after meta init , new AWS access and secret keys are generated, which are temporary. Because of this, you will see these changes, which is fine, and these variables should be updated.


Account User Setup


Until this moment, nothing has been created manually except AWS prod account. To get access this account, we need to create an IAM user from root account, which will allow access to the prod account.

Before creating the user, SSO should be enabled from root for prod account, and at this step all users who should have access to prod can be invited to SSO.

Problem 2: SSO configuration is done manually.

After manually enabling SSO, we need to add yaml config file through which the IAM user will be created:

1infrstructure 2| 3|--- 0-accounts 4 | 5 |--- root 6 | 7 |--- iam-prod.yaml 8|--- 1-environments 9|--- 2-products

iam-prod.yaml

1source: terraform-aws-modules/iam/aws//modules/iam-user 2version: 5.30.0 3variables: 4 name: terraform 5 create_iam_user_login_profile: false 6 create_iam_access_key: true 7 policy_arns: 8 - arn:aws:iam::aws:policy/AdministratorAccess 9output: 10 sensitive: true 11providers: 12 - name: aws 13 version: ~> 4.0 14 variables: 15 default_tags: 16 tags: 17 Account: project-name-root 18 ManageLevel: account 19 blocks: 20 assume_role: 21 role_arn: "arn:aws:iam::33333333333333:role/OrganizationAccountAccessRole" 22 session_name: "AssumeRoleSession" 23 external_id: "33333333333333" 24

Each time we add a new yaml config file these commands are needed to execute:

  1. terraform apply

  2. git add .

  3. git commit

  4. git push

After just check that TFC correctly executes applying.



Environment Setup

Problem 3. We don’t have dependencies between workspaces, so we can’t integrate this configuration with the IAM user’s creation part.

We need to create a new subfolder in infrastructure/1-environments folder, for example prod-1:

1infrstructure 2| 3|--- 0-accounts 4|--- 1-environments 5 | 6 |--- prod-1 7|--- 2-products

Environment-specific resources are created in this layer. To do so, we need to add yaml config files to this subfolder. For example, resources like EKS, VPC and IAM users are specific to the environment, so we have:

1infrstructure 2| 3|--- 0-accounts 4|--- 1-environments 5 | 6 |--- prod-1 7 |--- eks.yaml 8 |--- iam.yaml 9 |--- vpc.yaml 10|--- 2-products

These new resources are applied by using the IAM user’s credentials in AWS provider that we created during the previous step. Therefore, we need to include the user’s credentials in the provider.

For example, vpc.yaml config should look like this:

vpc.yaml

1source: dasmeta/vpc/aws 2version: 1.0.1 3variables: 4 name: "prod-vpc" 5 availability_zones: 6 - "us-east-1a" 7 - "us-east-1b" 8 private_subnets: 9 - "10.17.1.0/24" 10 - "10.17.2.0/24" 11 public_subnets: 12 - "10.17.3.0/24" 13 - "10.17.4.0/24" 14 cidr: "10.17.0.0/16" 15 public_subnet_tags: 16 "kubernetes.io/cluster/eks-prod": "shared" 17 "kubernetes.io/role/elb": "1" 18 private_subnet_tags: 19 "kubernetes.io/cluster/eks-prod": "shared" 20 "kubernetes.io/role/internal-elb": "1" 21providers: 22 - name: aws 23 version: ~> 4.0 24 module_nested_provider: true 25 variables: 26 region: us-east-1 27 access_key: ${0-accounts/root/iam-prod.iam_access_key_id} ------ 1 28 secret_key: ${0-accounts/root/iam-prod.iam_access_key_secret} ------ 2 29 default_tags: 30 tags: 31 Account: project-name 32 ManageLevel: environment 33linked_workspaces: ------ 3 34 - 0-accounts/root/iam-prod ------ 4 35

1, 2 lines specify which credentials must be used in the provider.

3, 4 lines establish the link between this new configuration and the previously created IAM user’s configuration. In TFC these are 2 separate workspaces.

The execution is the same like before:

  1. terraform apply

  2. git add .

  3. git commit

  4. git push