Adding Account Factory to a new repository
To configure Gruntwork Account Factory in a new GitHub/GitLab repository, the following steps are required (and will be explained in detail below):
- Create your infrastructure-live root, access-control and catalog repositories.
- Configure the authentication for the repositories to ensure that required access tokens are available.
- GitHub
- GitLab
Creating the infrastructure-live-root repository
Gruntwork provides a pre-configured git repository template that incorporates best practices while allowing for customization.
infrastructure-live-root-template
This template generates an infrastructure-live-root repository with a bootstrap workflow designed to scaffold a best-practices Terragrunt configuration. It includes patterns for module defaults, global variables, and account baselines. Additionally, it integrates Gruntwork Pipelines, which can be removed if not required.
The workflow can optionally scaffold the infrastructure-live-access-control and infrastructure-catalog repositories.
Navigate to the template repository and select Use this template -> Create a new Repository. Choose your organization as the owner, add a description if desired, set the repository to private, and click Create repository.
Configuring Gruntwork app settings
Use the Gruntwork.io GitHub App to add the repository as an Infra Root repository.
If using the machine user model, ensure the INFRA_ROOT_WRITE_TOKEN (and ORG_REPO_ADMIN_TOKEN for enterprise customers) is added to the repository as a secret or configured as an organization secret.
Updating the Bootstrap Workflow
Return to your infrastructure-live-root repository and follow the README instructions to update the bootstrap workflow for IaC Foundations. Provide details about your AWS organization, accounts, and default values for new account provisioning.
Running the workflow
Follow the instructions in your infrastructure-live-root repository to execute the Bootstrap Workflow. Gruntwork support is available to address any questions that arise. During the workflow execution, you can choose to create the infrastructure-live-access-control and infrastructure-catalog repositories. These repositories will be created in your GitHub organization using values defined in the workflow configuration.
Infrastructure live access control
This repository is primarily for Enterprise customers but is recommended for all users. When running the Bootstrap Workflow in your infrastructure-live-root repository, select the option to "Bootstrap the infrastructure-access-control repository."
Infrastructure catalog
The Bootstrap Workflow also creates an empty infrastructure-catalog repository. This repository is used to store Terraform/OpenTofu modules authored by your organization for internal use. During the Bootstrap Workflow execution in your infrastructure-live-root repository, select the option to "Bootstrap the infrastructure-catalog repository."
Completing instructions in Bootstrap Pull Requests
Each of your repositories will contain a Bootstrap Pull Request. Follow the instructions in these Pull Requests to finalize the setup of your IaC repositories.
The bootstrapping pull requests include pre-configured files, such as a .mise.toml file that specifies versions of OpenTofu and Terragrunt. Ensure you review and update these configurations to align with your organization's requirements.
This guide walks you through the process of setting up a new GitLab Project with the Gruntwork Platform. By the end, you'll have a fully configured GitLab CI/CD pipeline that can create new AWS accounts and deploy infrastructure changes automatically.
To use Gruntwork Pipelines in an existing GitLab repository, see this guide.
Prerequisites
Before you begin, make sure you have:
- Basic familiarity with Git, GitLab, and infrastructure as code concepts
- Completed the AWS Landing Zone setup
- Have programmatic access to the AWS accounts created in the AWS Landing Zone setup
- Completed the Pipelines Auth setup for GitLab and setup a machine user with appropriate PAT tokens
- Local access to Gruntwork's GitHub repositories, specifically the architecture catalog
Additional setup for custom GitLab instances only
Fork the Pipelines workflow project
You must fork Gruntwork's public Pipelines workflow project into your own GitLab instance. This is necessary because Gruntwork Pipelines uses GitLab CI/CD components, and GitLab requires components to reside within the same GitLab instance as the project referencing them.
When creating the fork, we recommend configuring it as a public mirror of the original Gruntwork project and ensuring that tags are included.
Ensure OIDC configuration and JWKS are publicly accessible
This step only applies if you are using a self-hosted GitLab instance that is not accessible from the public internet. If you are using GitLab.com or a self-hosted instance that is publicly accessible, you can skip this step.
- Follow GitLab's instructions for hosting your OIDC configuration and JWKS in a public location (e.g. S3 Bucket). This is necessary for both Gruntwork and the AWS OIDC provider to access the GitLab OIDC configuration and JWKS when authenticating JWT's generated by your custom instance.
- Note the <ISSUER_URL> (stored as
ci_id_tokens_issuer_urlin yourgitlab.rbfile per GitLab's instructions) generated above for reuse in the next steps.
- Create a new GitLab project for your
infrastructure-live-rootrepository. - Install dependencies.
- Configure the variables required to run the infrastructure-live-root boilerplate template.
- Create your
infrastructure-live-rootrepository contents using Gruntwork's architecture-catalog template. - Apply the account baselines to your AWS accounts.
Create a new infrastructure-live-root
Authorize Your GitLab Group with Gruntwork
To use Gruntwork Pipelines with GitLab, your group needs authorization from Gruntwork. Email your Gruntwork account manager or support@gruntwork.io with:
GitLab group name(s): <GITLAB_GROUP_NAME> (e.g. acme-io)
GitLab Issuer URL: <ISSUER_URL> (For most users this is the URL of your GitLab instance e.g. https://gitlab.acme.io, if your instance is not publicly accessible, this should be a separate URL that is publicly accessible per step 0, e.g. https://s3.amazonaws.com/YOUR_BUCKET_NAME/)
Organization name: <ORGANIZATION_NAME> (e.g. Acme, Inc.)
Continue with the rest of the guide while you await confirmation when your group has been authorized.
Create a new GitLab project
- Navigate to the <GITLAB_GROUP_NAME> group.
- Click the New Project button.
- Enter a name for the project. e.g. infrastructure-live-root
- Click Create Project.
- Clone the project to your local machine.
- Navigate to the project directory.
- Create a new branch
bootstrap-repository.
Install dependencies
-
Install mise on your machine.
-
Activate mise in your shell:
# For Bash
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
# For Zsh
echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc
# For Fish
echo 'mise activate fish | source' >> ~/.config/fish/config.fish -
Add the following to a .mise.toml file in the root of your project:
.mise.toml[tools]
boilerplate = "0.8.1"
opentofu = "1.10.0"
terragrunt = "0.81.6"
awscli = "latest" -
Run
mise install.
Bootstrap the repository
Gruntwork provides a boilerplate template that incorporates best practices while allowing for customization. The template is designed to scaffold a best-practices Terragrunt configurations. It includes patterns for module defaults, global variables, and account baselines. Additionally, it integrates Gruntwork Pipelines.
Configure the variables required to run the boilerplate template
Copy the content below to a vars.yaml file in the root of your project and update the <REPLACE> values with your own.
SCMProvider: GitLab
# The GitLab group to use for the infrastructure repositories. This should include any additional sub-groups in the name
# Example: acme/prod
SCMProviderGroup: <GITLAB_GROUP_NAME>
# The GitLab project to use for the infrastructure-live repository.
SCMProviderRepo: infrastructure-live-root
# The name of the project to use for the infrastructure-live-access-control repository.
AccessControlRepoName: infrastructure-live-access-control
# The name of the project to use for the infrastructure-catalog repository.
InfraModulesRepoName: infrastructure-catalog
# The base URL of your GitLab group repos. E.g., gitlab.com/<group>
RepoBaseUrl: <GITLAB_GROUP_REPO_BASE_URL>
# The name of the branch to deploy to.
# Example: main
DeployBranchName: <DEPLOY_BRANCH_NAME>
# The AWS account ID for the management account
# Example: "123456789012"
AwsManagementAccountId: <AWS_MANAGEMENT_ACCOUNT_ID>
# The AWS account ID for the security account
# Example: "123456789013"
AwsSecurityAccountId: <AWS_SECURITY_ACCOUNT_ID>
# The AWS account ID for the logs account
# Example: "123456789014"
AwsLogsAccountId: <AWS_LOGS_ACCOUNT_ID>
# The AWS account ID for the shared account
# Example: "123456789015"
AwsSharedAccountId: <AWS_SHARED_ACCOUNT_ID>
# The AWS account Email for the logs account
# Example: logs@acme.com
AwsLogsAccountEmail: <AWS_LOGS_ACCOUNT_EMAIL>
# The AWS account Email for the management account
# Example: management@acme.com
AwsManagementAccountEmail: <AWS_MANAGEMENT_ACCOUNT_EMAIL>
# The AWS account Email for the security account
# Example: security@acme.com
AwsSecurityAccountEmail: <AWS_SECURITY_ACCOUNT_EMAIL>
# The AWS account Email for the shared account
# Example: shared@acme.com
AwsSharedAccountEmail: <AWS_SHARED_ACCOUNT_EMAIL>
# The name prefix to use for creating resources e.g S3 bucket for OpenTofu state files
# Example: acme
OrgNamePrefix: <ORG_NAME_PREFIX>
# The default region for AWS Resources
# Example: us-east-1
DefaultRegion: <DEFAULT_REGION>
################################################################################
# OPTIONAL VARIABLES WITH THEIR DEFAULT VALUES. UNCOMMENT AND MODIFY IF NEEDED.
################################################################################
# If you are an enterprise customer, set this to true.
# IsEnterprise: true
# List of the git repositories to populate for the catalog
# CatalogRepositories:
# - github.com/gruntwork-io/terraform-aws-service-catalog
# The AWS partition to use. Options: aws, aws-us-gov, aws-cn
# AWSPartition: aws
# The name of the IAM role to use for the plan job.
# PlanIAMRoleName: root-pipelines-plan
# The name of the IAM role to use for the apply job.
# ApplyIAMRoleName: root-pipelines-apply
# The default tags to apply to all resources.
# DefaultTags:
# "{{ .OrgNamePrefix }}:Team": "DevOps"
# The version for terraform-aws-security module to use for OIDC provider and roles provisioning
# SecurityModulesVersion: v0.75.18
# The URL of the custom SCM provider instance. Set this if you are using a custom instance of GitLab.
# CustomSCMProviderInstanceURL: https://gitlab.example.io
# The relative path from the host server to the custom pipelines workflow repository. Set this if you are using a custom/forked instance of the pipelines workflow.
# CustomWorkflowHostRelativePath: pipelines-workflows
Generate the repository contents
-
Run the following command, from the root of your project, to generate the
infrastructure-live-rootrepository contents:boilerplate --template-url "git@github.com:gruntwork-io/terraform-aws-architecture-catalog.git//templates/devops-foundations-infrastructure-live-root/?ref=4.0.1" --output-folder . --var-file vars.yaml --non-interactiveThis command adds all code required to set up your
infrastructure-live-rootrepository. -
Remove the boilerplate dependency from the
mise.tomlfile. It is no longer needed. -
Commit your local changes and push them to the
bootstrap-repositorybranch.git add .
git commit -m "Bootstrap infrastructure-live-root repository initial commit [skip ci]"
git push origin bootstrap-repositorySkipping the CI/CD process for now; you will manually apply the infrastructure baselines to your AWS accounts in a later step.
-
Create a new merge request for the
bootstrap-repositorybranch. Review the changes to understand what will be applied to your AWS accounts. The generated files fall under the following categories:- GitLab Pipelines workflow file
- Gruntwork Pipelines configuration files
- Module defaults files for infrastructure code
- Account baselines and GitLab OIDC module scaffolding files for your core AWS accounts: management, security, logs and shared.
Apply the account baselines to your AWS accounts
You will manually terragrunt apply the generated infrastructure baselines to get your accounts bootstrapped before merging this content into your main branch.
You can utilize the AWS SSO Portal to obtain temporary AWS credentials necessary for subsequent steps:
- Sign in to the Portal page and select your preferred account to unveil the roles accessible to your SSO user.
- Navigate to the "Access keys" tab adjacent to the "AWSAdministratorAccess" role.
- Copy the "AWS environment variables" provided and paste them into your terminal for usage.
-
Apply infrastructure changes in the management account
-
- Obtain AWS CLI Administrator credentials for the management account
-
-
Navigate to the management account folder
cd management/
-
-
-
Using your credentials, run
terragrunt plan.terragrunt run --all --non-interactive --backend-bootstrap plan
-
-
-
After the plan succeeds, apply the changes:
terragrunt run --all --non-interactive apply
-
-
-
After applying the changes, make sure to lock providers in your
.terraform.lock.hclfiles. The lock files will be committed in the final step of the setup. e.g.terragrunt run --all providers -- lock -platform=darwin_amd64 -platform=linux_amd64
-
-
-
Update Permissions for Account Factory Portfolio
The account factory pipeline will fail until you grant the pipelines roles (
root-pipelines-planandroot-pipelines-apply) access to the portfolio. This step must be done after you provision the pipelines roles in the management account (where control tower is set up).Access to the portfolio is separate from IAM access, it must be granted in the Service Catalog console.
Steps to grant access
To grant access to the Account Factory Portfolio, you must be an individual with Service Catalog administrative permissions.
- Log into the management AWS account
- Go into the Service Catalog console
- Ensure you are in your default region(control-tower region)
- Select the Portfolios option in Administration from the left side navigation panel
- Click on the portfolio named AWS Control Tower Account Factory Portfolio
- Select the Access tab
- Click the Grant access button
- In the Access type section, leave the default value of IAM Principal
- Select the Roles tab in the lower section
- Enter
root-pipelinesinto the search bar, there should be two results (root-pipelines-planandroot-pipelines-apply). Click the checkbox to the left of each role name. - Click the Grant access button in the lower right hand corner
-
-
- Increase Account Quota Limit (OPTIONAL)
Note that DevOps Foundations makes it very convenient, and therefore likely, that you will encounter one of the soft limits imposed by AWS on the number of accounts you can create.
You may need to request a limit increase for the number of accounts you can create in the management account, as the default is currently 10 accounts.
To request an increase to this limit, search for "Organizations" in the AWS management console here and request a limit increase to a value that makes sense for your organization.
-
-
-
Apply infrastructure changes in the logs account
-
- Obtain AWS CLI Administrator credentials for the logs account
-
-
Navigate to the logs account folder
cd ../logs/
-
-
-
Using your credentials, run
terragrunt plan.terragrunt run --all --non-interactive --backend-bootstrap plan
-
-
-
After the plan succeeds, apply the changes:
terragrunt run --all --non-interactive apply
-
-
-
After applying the changes, make sure to lock providers in your
.terraform.lock.hclfiles. e.g.terragrunt run --all providers lock -platform=darwin_amd64 -platform=linux_amd64
-
-
-
-
Apply infrastructure changes in the security account
-
- Obtain AWS CLI Administrator credentials for the security account
-
-
Navigate to the security account folder
cd ../security/
-
-
-
Using your credentials, run
terragrunt plan.terragrunt run --all --non-interactive --backend-bootstrap plan
-
-
-
After the plan succeeds, apply the changes:
terragrunt run --all --non-interactive apply
-
-
-
After applying the changes, make sure to lock providers in your
.terraform.lock.hclfiles. e.g.terragrunt run --all providers lock -platform=darwin_amd64 -platform=linux_amd64
-
-
-
-
Apply infrastructure changes in the shared account
-
- Obtain AWS CLI Administrator credentials for the shared account. You may need to grant your user access to the
AWSAdministratorAccesspermission set in the shared account from the management account's Identity Center Admin console.
- Obtain AWS CLI Administrator credentials for the shared account. You may need to grant your user access to the
-
-
Using your credentials, create a service role
aws iam create-service-linked-role --aws-service-name autoscaling.amazonaws.com
-
-
-
Navigate to the shared account folder
cd ../shared/
-
-
-
Using your credentials, run
terragrunt plan.terragrunt run --all --non-interactive --backend-bootstrap plan
-
-
-
After the plan succeeds, apply the changes:
terragrunt run --all --non-interactive apply
-
-
-
After applying the changes, make sure to lock providers in your
.terraform.lock.hclfiles. e.g.terragrunt run --all providers lock -platform=darwin_amd64 -platform=linux_amd64
-
-
-
-
Commit your local changes and push them to the
bootstrap-repositorybranch.cd ..
git add .
git commit -m "Bootstrap infrastructure-live-root repository final commit [skip ci]"
git push origin bootstrap-repository
-
-
- Merge the open merge request. Ensure [skip ci] is present in the commit message.
Create a new infrastructure-live-access-control (optional, required for enterprise customers)
Create a new GitLab project
- Navigate to the <GITLAB_GROUP_NAME> group.
- Click the New Project button.
- Enter the name for the project as
infrastructure-live-access-control. - Click Create Project.
- Clone the project to your local machine.
- Navigate to the project directory.
- Create a new branch
bootstrap-repository.
Install dependencies
Run mise install boilerplate@0.8.1 to install the boilerplate tool.
Bootstrap the repository
Configure the variables required to run the boilerplate template
Copy the content below to a vars.yaml file in the root of your project and update the customizable values as needed.
SCMProvider: GitLab
# The GitLab group to use for the infrastructure repositories. This should include any additional sub-groups in the name
# Example: acme/prod
SCMProviderGroup: <GITLAB_GROUP_NAME>
# The GitLab project to use for the infrastructure-live-access-control repository.
InfraLiveAccessControlRepoName: infrastructure-live-access-control
# The name of the branch to deploy to.
# Example: main
DeployBranchName: <DEPLOY_BRANCH_NAME>
# The name prefix to use for creating resources e.g S3 bucket for OpenTofu state files
# Example: acme
OrgNamePrefix: <ORG_NAME_PREFIX>
# The default region for AWS Resources
# Example: us-east-1
DefaultRegion: <DEFAULT_REGION>
################################################################################
# OPTIONAL VARIABLES WITH THEIR DEFAULT VALUES. UNCOMMENT AND MODIFY IF NEEDED.
################################################################################
# The AWS partition to use.
# AWSPartition: aws
Generate the repository contents
-
Run the following command, from the root of your project, to generate the
infrastructure-live-access-controlrepository contents:boilerplate --template-url "git@github.com:gruntwork-io/terraform-aws-architecture-catalog.git//templates/devops-foundations-infrastructure-live-access-control/?ref=4.0.1" --output-folder . --var-file vars.yaml --non-interactiveThis command adds all code required to set up your
infrastructure-live-access-controlrepository. The generated files fall under the following categories:- GitLab Pipelines workflow file
- Gruntwork Pipelines configuration files
- Module defaults files for GitLab OIDC roles and policies
-
Commit your local changes and push them to the
bootstrap-repositorybranch.git add .
git commit -m "Bootstrap infrastructure-live-access-control repository [skip ci]"
git push origin bootstrap-repositorySkipping the CI/CD process now because there is no infrastructure to apply; repository simply contains the GitLab OIDC role module defaults to enable GitLab OIDC authentication from repositories other than
infrastructure-live-root. -
Create a new merge request for the
bootstrap-repositorybranch. Review the changes to understand the GitLab OIDC role module defaults. -
Merge the open merge request. Ensure [skip ci] is present in the commit message.
Create a new infrastructure-catalog (optional)
The infrastructure-catalog repository is a collection of modules that can be used to build your infrastructure. It is a great way to share modules with your team and across your organization. Learn more about the Developer Self-Service concept.
Create a new GitLab project
- Navigate to the <GITLAB_GROUP_NAME> group.
- Click the New Project button.
- Enter the name for the project as
infrastructure-catalog. - Click Create Project.
- Clone the project to your local machine.
- Navigate to the project directory.
- Create a new branch
bootstrap-repository.
Install dependencies
Run mise install boilerplate@0.8.1 to install the boilerplate tool.
Bootstrap the repository
Configure the variables required to run the boilerplate template
Copy the content below to a vars.yaml file in the root of your project and update the customizable values as needed.
# The name of the repository to use for the catalog.
InfraModulesRepoName: infrastructure-catalog
# The version of the Gruntwork Service Catalog to use. https://github.com/gruntwork-io/terraform-aws-service-catalog
ServiceCatalogVersion: v0.111.2
# The version of the Gruntwork VPC module to use. https://github.com/gruntwork-io/terraform-aws-vpc
VpcVersion: v0.26.22
# The default region for AWS Resources
# Example: us-east-1
DefaultRegion: <DEFAULT_REGION>
################################################################################
# OPTIONAL VARIABLES WITH THEIR DEFAULT VALUES. UNCOMMENT AND MODIFY IF NEEDED.
################################################################################
# The base URL of the Organization to use for the catalog.
# If you are using Gruntwork's RepoCopier tool, this should be the base URL of the repository you are copying from.
# RepoBaseUrl: github.com/gruntwork-io
# The name prefix to use for the Gruntwork RepoCopier copied repositories.
# Example: gruntwork-io-
# GWCopiedReposNamePrefix:
Generate the repository contents
-
Run the following command, from the root of your project, to generate the
infrastructure-catalogrepository contents:boilerplate --template-url "git@github.com:gruntwork-io/terraform-aws-architecture-catalog.git//templates/devops-foundations-infrastructure-modules/?ref=4.0.1" --output-folder . --var-file vars.yaml --non-interactiveThis command adds some code required to set up your
infrastructure-catalogrepository. The generated files are some usable modules for your infrastructure. -
Commit your local changes and push them to the
bootstrap-repositorybranch.git add .
git commit -m "Bootstrap infrastructure-catalog repository"
git push origin bootstrap-repository -
Create a new merge request for the
bootstrap-repositorybranch. Review the changes to understand the example Service Catalog modules. -
Merge the open merge request.