Skip to content

Create a Leverage project

A Leverage project starts with a simple project definition file that you modify to suit your needs. That file is then used to render the initial directory layout which, at the end of this guide, will be your reference architecture. Follow the sections below to begin with that.

The account's name will be given by your project's name followed by -management, since Leverage uses a suffix naming system to differentiate between the multiple accounts of a project. For this guide we'll stick to calling the project MyExample and so, the account name will be myexample-management.

Along the same line, we'll use the example.com domain for the email address used to register the account. Adding a -aws suffix to the project's name to indicate that this email address is related to the project's AWS account, we end up with a registration email that looks like myexample-aws@example.com.

Email addresses for AWS accounts.

Each AWS account requires having a unique email address associated to it. The Leverage Reference Architecture for AWS makes use of multiple accounts to better manage the infrastructure, as such, you will need different addresses for each one. Creating a new email account for each AWS is not a really viable solution to this problem, a better approach is to take advantage of mail services that support aliases. For information regarding how this works: 📚 Email setup for your AWS account.

Create the project directory

Each Leverage project lives in its own working directory. Create a directory for your project as follows:

mkdir myexample
cd myexample

Initialize the project

Create the project definition file by running the following command:

$ leverage project init
[18:53:24.407] INFO     Project template found. Updating.                                                                                              
[18:53:25.105] INFO     Finished updating template.                                                                                                    
[18:53:25.107] INFO     Initializing git repository in project directory.                                                                              
[18:53:25.139] INFO     No project configuration file found. Dropping configuration template project.yaml.                                             
[18:53:25.143] INFO     Project initialization finished.

The command above should create the project definition file (project.yaml) and should initialize a git repository in the current working directory. This is important because Leverage projects by-design rely on specific git conventions and also because it is assumed that you will want to keep your infrastructure code versioned.

Modify the project definition file

Open the project.yaml file and fill in the required information.

Typically the placeholder values between < and > symbols are the ones you would want to edit however you are welcome to adjust any other values to suit your needs.

For instance, the following is a snippet of the project.yaml file in which the values for project_name and short_name have been set to example and ex respectively:

project_name: example
short_name: ex
primary_region: us-east-1
secondary_region: us-west-2
...

The project_name field only accepts lowercase alphanumeric characters and allows hyphens('-'). For instance, valid names could be 'example' or 'leveragedemo' or 'example-demo'

The short_name field only accepts 2 to 4 lowercase alpha characters. For instance, valid names could be 'exam or 'leve or 'ex

We typically use as 1ry us-east-1 and 2ry us-west-2 as our default regions for the majority of our projects. However, please note that these regions may not be the most fitting choice for your specific use case. For detailed guidance, we recommend following these provided guidelines.

Another example is below. Note that the management, security, and shared accounts have been updated with slightly different email addresses (actually aws+security@example.com and aws+shared@example.com are email aliases of aws@example.com which is a convenient trick in some cases):

...
organization:
  accounts:
  - name: management
    email: aws@example.com
  - name: security
    email: aws+security@example.com
  - name: shared
    email: aws+shared@example.com
...

Finally, here's another example snippet that shows how you can define users and assign them to groups:

...
users:
- first_name: Jane
  last_name: Doe
  email: jane.doe@example.com
  groups:
  - administrators
  - devops
- first_name: Foo
  last_name: Bar
  email: foo.bar@example.com
  groups:
  - devops
...

Note these users will be the ones used later for SSO access.

The project definition file includes other entries but the ones shown above are the most frequently updated.

Configure "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 the first and main account of the project, the management account.