Skip to content

Set Up your Leverage project

Up until now we have been taking care of all the prerequisites for a Leverage project, but is time to actually create the Reference Architecture definition for your project. Let's get to it.

Create the project directory

Each Leverage project must be in its own working directory.

Create the directory for your project.

mkdir myexample
cd myexample

Initialize the Leverage project

When setting up a Leverage project the directory where it will reside needs to be initialized

leverage project init
[09:30:54.027] INFO     No Leverage directory found in user's home. Creating.
[09:30:54.030] INFO     No project template found. Cloning template.
[09:30:54.978] INFO     Finished cloning template.
[09:30:54.981] INFO     Initializing git repository in project directory.
[09:30:54.990] INFO     No project configuration file found. Dropping configuration template project.yaml.
[09:30:55.007] INFO     Project initialization finished.

More information on project init

Initializing a project creates the global configurations directory for Leverage CLI and downloads the templates used to generate the project's files structure. It then initializes a git repository in the working directory, and creates a file called project.yaml. Leverage projects are by design repositories to leverage some of the capabilities of git and because it is assumed that the code in the project will be versioned.

Fill in the configuration file

Once the project is initialized you need to fill in the correct information for the project in the configuration file.

After filling in the data you will end up with a configuration file similar to the one below. Indicated by arrows are the fields that were modified.

You can see in the global values, the project name and a short version of it, in the organization section, the emails for each account, and further down, in the accounts section, the different groups and users for each group in the management and security accounts.

project.yaml for MyExample project
project_name: myexample # <--
short_name: me # <--

primary_region: us-east-1
secondary_region: us-west-2

organization:
  accounts:
  - name: management
    email: myexample-aws@example.com # <--
  - name: security
    email: myexample-aws+security@example.com # <--
  - name: shared
    email: myexample-aws+shared@example.com # <--
  organizational_units:
  - name: security
    policy:
    - aws_organizations_policy.default
    accounts:
    - security
  - name: shared
    policy:
    - aws_organizations_policy.standard
    accounts:
    - shared

accounts:
  management:
    groups:
    - name: admins # <--
      users:
      - kit.walker
      - natasha.romanoff
      policies:
      - '"arn:aws:iam::aws:policy/AdministratorAccess"'
  security:
    groups:
    - name: admins # <--
      users:
      - natasha.romanoff
    - name: auditors # <--
      users:
      - kit.walker
      policies:
      - aws_iam_policy.assume_auditor_role.arn
    - name: devops # <--
      users:
      - natasha.romanoff
      - edward.stark
      - john.wick
      policies:
      - aws_iam_policy.assume_devops_role.arn
  shared:
    networks:
    - cidr_block: "172.18.0.0/20"
      availability_zones: [a,b]
      private_subnets_cidr: "172.18.0.0/21"
      private_subnets:
      - "172.18.0.0/23"
      - "172.18.2.0/23"
      public_subnets_cidr: "172.18.8.0/21"
      public_subnets:
      - "172.18.8.0/23"
      - "172.18.10.0/23"

Set Up the bootstrap credentials

To be able to interact with your AWS environment you first need to configure the credentials to enable AWS CLI to do so. Provide the keys obtained in the previous account creation step to the command by any of the available means.

leverage credentials configure --type BOOTSTRAP
[09:37:17.530] INFO     Loading configuration file.
[09:37:18.477] INFO     Loading project environment configuration file.
[09:37:20.426] INFO     Configuring bootstrap credentials.
> Select the means by which you'll provide the programmatic keys: Manually
> Key: AKIAU1OF18IXH2EXAMPLE
> Secret: ****************************************
[09:37:51.638] INFO     Bootstrap credentials configured in: /home/user/.aws/me/credentials
[09:37:53.497] INFO     Fetching management account id.
[09:37:53.792] INFO     Updating project configuration file.
[09:37:55.344] INFO     Skipping assumable roles configuration.

leverage credentials configure --type BOOTSTRAP
[09:37:17.530] INFO     Loading configuration file.
[09:37:18.477] INFO     Loading project environment configuration file.
[09:37:20.426] INFO     Configuring bootstrap credentials.
> Select the means by which you'll provide the programmatic keys: Path to an access keys file obtained from AWS
> Path to access keys file: ../bootstrap_accessKeys.csv
[09:37:51.638] INFO     Bootstrap credentials configured in: /home/user/.aws/me/credentials
[09:37:53.497] INFO     Fetching management account id.
[09:37:53.792] INFO     Updating project configuration file.
[09:37:55.344] INFO     Skipping assumable roles configuration.

leverage credentials configure --type BOOTSTRAP --credentials-file ../bootstrap_accessKeys.csv
[09:37:17.530] INFO     Loading configuration file.
[09:37:18.477] INFO     Loading project environment configuration file.
[09:37:20.426] INFO     Configuring bootstrap credentials.
[09:37:51.638] INFO     Bootstrap credentials configured in: /home/user/.aws/me/credentials
[09:37:53.497] INFO     Fetching management account id.
[09:37:53.792] INFO     Updating project configuration file.
[09:37:55.344] INFO     Skipping assumable roles configuration.

More information on credentials configure

During the credentials setup, the AWS account id is filled in for us in the project configuration file.

...
organization:
  accounts:
    - name: management
      email: myexample-aws@example.com
      id: '000123456789'
...

Create the configured project

Now you will finally create all the infrastructure definition in the project.

leverage project create
[09:40:54.934] INFO     Loading configuration file.
[09:40:54.950] INFO     Creating project directory structure.
[09:40:54.957] INFO     Finished creating directory structure.
[09:40:54.958] INFO     Setting up common base files.
[09:40:54.964] INFO     Account: Setting up management.
[09:40:54.965] INFO             Layer: Setting up config.
[09:40:54.968] INFO             Layer: Setting up base-tf-backend.
[09:40:54.969] INFO             Layer: Setting up base-identities.
[09:40:54.984] INFO             Layer: Setting up organizations.
[09:40:54.989] INFO             Layer: Setting up security-base.
[09:40:54.990] INFO     Account: Setting up security.
[09:40:54.991] INFO             Layer: Setting up config.
[09:40:54.994] INFO             Layer: Setting up base-tf-backend.
[09:40:54.995] INFO             Layer: Setting up base-identities.
[09:40:55.001] INFO             Layer: Setting up security-base.
[09:40:55.002] INFO     Account: Setting up shared.
[09:40:55.003] INFO             Layer: Setting up config.
[09:40:55.006] INFO             Layer: Setting up base-tf-backend.
[09:40:55.007] INFO             Layer: Setting up base-identities.
[09:40:55.008] INFO             Layer: Setting up security-base.
[09:40:55.009] INFO             Layer: Setting up base-network.
[09:40:55.013] INFO     Project configuration finished.
               INFO     Reformatting terraform configuration to the standard style.
[09:40:55.743] INFO     Finished setting up project.

More information on project create

In this step, the directory structure for the project and all definition files are created using the information from the project.yaml file and checked for correct formatting.

You will end up with something that looks like this:

MyExample project file structure

📂 myexample
├── 📄 build.env
├── 📄 project.yaml
├── 📂 config
│   └── 📄 common.tfvars
├── 📂 management
│   ├── 📂 config
│   │   ├── 📄 account.tfvars
│   │   └── 📄 backend.tfvars
|   ├── 📂 global
|   │   ├── 📂 organizations
|   │   │   ├── 📄 accounts.tf
|   │   │   ├── 📄 config.tf
|   │   │   ├── 📄 delegated_administrator.tf
|   │   │   ├── 📄 locals.tf
|   │   │   ├── 📄 organizational_units.tf
|   │   │   ├── 📄 organization.tf
|   │   │   ├── 📄 policies_scp.tf
|   │   │   ├── 📄 policy_scp_attachments.tf
|   │   │   ├── 📄 service_linked_roles.tf
|   │   │   └── 📄 variables.tf
|   │   └── 📂 base-identities
|   │       ├── 📄 account.tf
|   │       ├── 📄 config.tf
|   │       ├── 📄 groups.tf
|   │       ├── 📄 keys
|   │       ├── 📄 locals.tf
|   │       ├── 📄 outputs.tf
|   │       ├── 📄 roles.tf
|   │       ├── 📄 users.tf
|   │       └── 📄 variables.tf
|   └── 📂 us-east-1
|       ├── 📂 base-tf-backend
|       │   ├── 📄 config.tf
|       │   ├── 📄 locals.tf
|       │   ├── 📄 main.tf
|       │   └── 📄 variables.tf
|       └── 📂 security-base
|           ├── 📄 account.tf
|           ├── 📄 config.tf
|           └── 📄 variables.tf
├── 📂 security
│   ├── 📂 config
│   │   ├── 📄 account.tfvars
│   │   └── 📄 backend.tfvars
│   ├── 📂 global
|   |   └── 📂 base-identities
|   │       ├── 📄 account.tf
|   │       ├── 📄 config.tf
|   │       ├── 📄 groups_policies.tf
|   │       ├── 📄 groups.tf
|   │       ├── 📄 keys
|   │       ├── 📄 locals.tf
|   │       ├── 📄 outputs.tf
|   │       ├── 📄 role_policies.tf
|   │       ├── 📄 roles.tf
|   │       ├── 📄 users.tf
|   │       └── 📄 variables.tf
│   └── 📂 us-east-1
|       ├── 📂 base-tf-backend
|       │   ├── 📄 config.tf
|       │   ├── 📄 locals.tf
|       │   ├── 📄 main.tf
|       │   └── 📄 variables.tf
|       └── 📂 security-base
|           ├── 📄 account.tf
|           ├── 📄 config.tf
|           ├── 📄 iam_access_analyzer.tf
|           ├── 📄 locals.tf
│           └── 📄 variables.tf
└── 📂 shared
    ├── 📂 config
    │   ├── 📄 account.tfvars
    │   └── 📄 backend.tfvars
    ├── 📂 global
    |   └── 📂 base-identities
    |       ├── 📄 account.tf
    |       ├── 📄 config.tf
    |       ├── 📄 locals.tf
    |       ├── 📄 policies.tf
    |       ├── 📄 roles.tf
    |       ├── 📄 service_linked_roles.tf
    |       └── 📄 variables.tf
    └── 📂 us-east-1
        ├── 📂 base-network
        │   ├── 📄 account.tf
        │   ├── 📄 config.tf
        │   ├── 📄 locals.tf
        │   ├── 📄 network.tf
        │   ├── 📄 network_vpc_flow_logs.tf
        │   ├── 📄 outputs.tf
        │   └── 📄 variables.tf
        ├── 📂 base-tf-backend
        │   ├── 📄 config.tf
        │   ├── 📄 locals.tf
        │   ├── 📄 main.tf
        │   └── 📄 variables.tf
        └── 📂 security-base
            ├── 📄 account.tf
            ├── 📄 config.tf
            └── 📄 variables.tf

As you can see, it is a structure comprised of directories for each account containing all the definitions for each of the accounts respective layers.

The layers themselves are also grouped based on the region in which they are deployed. The regions are configured through the project.yaml file. In the case of the Leverage landing zone, most layers are deployed in the primary region, so you can see the definition of these layers in a us-east-1 directory, as per the example configuration.

Some layers are not bound to a region because their definition is mainly comprised of resources for services that are global in nature, like IAM or Organizations. These kind of layers are kept in a global directory.

Next steps

You have now created the definition of all the infrastructure for your project and configured the credentials need to deploy such infrastructure in the AWS environment.

Next, you will orchestrate de first and main account of the project, the management account.