Terraform module providing an AWS Account Vending Machine (AVM). This module provisions an AWS account using the "AWS Control Tower Account Factory" product in Service Catalog with one or more Terraform Cloud/Enterprise (TFE) workspaces backed by a VCS project.
Using the default values, this module will create an IAM user per workspace in the provisioned AWS account. If using self-hosted Terraform Cloud agents then it is recommended to rather use an IAM role to authenticate with the AWS account. This is in line with authentication best practices to use IAM roles over IAM users with long-lived tokens.
To use IAM roles for authentication:
- Set
var.tfe_workspace.agent_pool_id
or (agent_pool_id
if specifying additional workspaces) to the Terraform Cloud agent pool ID - Set
var.tfe_workspace.auth_method
or (auth_method
if specifying additional workspaces) toiam_role
- Set
var.tfe_workspace.agent_role_arn
or (agent_role_arn
if specifying additional workspaces) to the IAM role assumed by the Terraform Cloud agents in the specified agent pool
This will create an IAM role in the provisioned AWS account with a randomly generated external ID which can only be assumed by the Terraform Cloud agent role. The created role and external ID value are stored in the new workspace as Terraform variables which can be used to configure your AWS provider. Using the default workspace the created role will be called TPEPipelineRole
, role names for additional workspaces will be calculated for you based on the workspace name but you can always set your own via the role_name
variable (similarly you can set your own role name in the default workspace via var.tfe_workspace.role_name
); but please be aware that each IAM role must have a unique name.
To use the created IAM role, use the following when configuring your AWS provider:
provider "aws" {
assume_role {
role_arn = var.aws_assume_role
external_id = var.aws_assume_role_external_id
session_name = "tfe-agent"
}
}
Team access can be configured per workspace using the team_access
variable.
As the state is considered sensitive, we recommend the following custom role permissions which is similar to the pre-existing "write" permission but blocks read access to the state (viewing outputs is still allowed):
team_access = {
"MyTeamName" = {
permissions = {
run_tasks = false
runs = "apply"
sentinel_mocks = "read"
state_versions = "read-outputs"
variables = "write"
workspace_locking = true
}
}
}
More complete usage information can be found in the underlying terraform-aws-mcaf-workspace module README.
Note: the team should already exist, this module will not create it for you.
In the account
variable, the SSO attributes (sso_email
, sso_firstname
and sso_lastname
) will be used by AWS Service Catalog to provide initial access to the newly created account.
You should use the details from the AWS Control Tower Admin user.
module "aws_account" {
source = "github.com/schubergphilis/terraform-aws-mcaf-avm?ref=VERSION"
name = "my-aws-account"
tags = { Terraform = true }
account = {
email = "[email protected]"
environment = "prod"
organizational_unit = "Production"
sso_email = "[email protected]"
}
tfe_workspace = {
default_region = "eu-west-1"
repository_identifier = "schubergphilis/terraform-aws-mcaf-avm"
organization = "schubergphilis"
vcs_oauth_token_id = var.oauth_token_id
}
}
module "aws_account" {
source = "github.com/schubergphilis/terraform-aws-mcaf-avm?ref=VERSION"
name = "my-aws-account"
tags = { Terraform = true }
account = {
email = "[email protected]"
environment = "prod"
organizational_unit = "Production"
sso_email = "[email protected]"
}
tfe_workspace = {
default_region = "eu-west-1"
repository_identifier = "schubergphilis/terraform-aws-mcaf-avm"
organization = "schubergphilis"
vcs_oauth_token_id = var.oauth_token_id
}
additional_tfe_workspaces = {
baseline-my-aws-account = {
auto_apply = true
repository_identifier = "schubergphilis/terraform-aws-mcaf-account-baseline"
}
}
}
module "aws_account" {
source = "github.com/schubergphilis/terraform-aws-mcaf-avm?ref=VERSION"
create_default_workspace = false
name = "my-aws-account"
tags = { Terraform = true }
account = {
email = "[email protected]"
environment = "prod"
organizational_unit = "Production"
sso_email = "[email protected]"
}
tfe_workspace = {
default_region = "eu-west-1"
repository_identifier = "schubergphilis/terraform-aws-mcaf-avm"
organization = "schubergphilis"
vcs_oauth_token_id = var.oauth_token_id
}
additional_tfe_workspaces = {
my-aws-account-subsystem1 = {
working_directory = "terraform/subsystem1"
}
my-aws-account-subsystem2 = {
working_directory = "terraform/subsystem2"
}
}
}
The module supports setting a Permission Boundary on the workspace iam_user
or iam_role
by passing down permissions_boundaries.workspace_boundary
, which needs to be referencing the path where the permissions boundary is stored in git and the name: permissions_boundaries.workspace_boundary_name
.
In case you want to reference a permission boundary that needs to be attached to every IAM role/user that will be created by the workspace role/user then you can create this permission boundary by specifying permissions_boundaries.workload_boundary
which needs to be referencing the path where the permissions boundary is stored in git and the name: permissions_boundaries.workload_boundary_name
.
module "aws_account" {
source = "github.com/schubergphilis/terraform-aws-mcaf-avm?ref=VERSION"
...
permissions_boundaries = {
workspace_boundary = "${path.module}/workspace_boundary.json"
workspace_boundary_name = "workspace_boundary"
workload_boundary = "${path.module}/workload_boundary.json"
workload_boundary_name = "workload_boundary"
}
...
}
Note: the workspace_boundary
and workload_boundary
can be templated files, account_id
will be replaced by AVM by the account ID of the AWS account created.
Name | Version |
---|---|
terraform | >= 1.3.0 |
aws | >= 4.9.0 |
github | >= 4.0.0 |
mcaf | >= 0.4.2 |
tfe | >= 0.25.0 |
Name | Version |
---|---|
aws.account | >= 4.9.0 |
Name | Description | Type | Default | Required |
---|---|---|---|---|
account | AWS account settings | object({ |
n/a | yes |
name | Name of the account and default TFE workspace | string |
n/a | yes |
tags | A map of tags to assign to all resources | map(string) |
n/a | yes |
tfe_workspace | TFE workspace settings | object({ |
n/a | yes |
additional_tfe_workspaces | Additional TFE workspaces | map(object({ |
{} |
no |
create_default_workspace | Set to false to skip creating default workspace | bool |
true |
no |
permissions_boundaries | n/a | object({ |
{} |
no |
Name | Description |
---|---|
additional_tfe_workspace | Map of additional TFE workspaces containing name and workspace ID |
id | The AWS account ID |
tfe_workspace_id | The TFE workspace ID |
workload_permissions_boundary_arn | The ARN of the workload permissions boundary |