Skip to content

Commit

Permalink
⚠️ Move account_name from app config to network config (#673)
Browse files Browse the repository at this point in the history
- Add account_name to network configs
- Remove account_name from environment configs
- Remove account_names_by_environment from app-config
- Add ability for configure-aws-credentials custom action to log in by
account_name and network_name

---------

Co-authored-by: Rocket <[email protected]>
  • Loading branch information
lorenyu and rocketnova authored Jun 28, 2024
1 parent 525d3da commit 46949a5
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 57 deletions.
79 changes: 58 additions & 21 deletions .github/actions/configure-aws-credentials/action.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,59 @@
name: 'Configure AWS Credentials'
description: 'Configure AWS Credentials for a given application and |
environment so that the GitHub Actions workflow can access AWS resources. |
description: 'Configure AWS Credentials for an AWS account so that |
the GitHub Actions workflow can access AWS resources. |
This is a wrapper around https://github.com/aws-actions/configure-aws-credentials |
that first determines the account, role, and region based on the |
account_names_by_environment configuration in app-config'
that first determines the account, role, and region. |
Chose one of the following three authentication options: |
1. Authenticate by account_name |
2. Authenticate by network_name |
3. Authenticate by app_name and environment.'

inputs:
account_name:
description: 'Name of account, must match <ACCOUNT_NAME> in <ACCOUNT_NAME>.<ACCOUNT_ID>.s3.tfbackend file in /infra/accounts'
network_name:
description: 'Name of network, must match <NETWORK_NAME> in <NETWORK_NAME>.s3.tfbackend file in /infra/networks'
app_name:
description: 'Name of application folder under /infra'
required: true
environment:
description: 'Name of environment (dev, staging, prod) that AWS resources live in, or "shared" for resources that are shared across environments'
required: true
runs:
using: "composite"
steps:
- name: Get network name from app and environment
id: get-network-name
if: ${{ inputs.app_name && inputs.environment }}
run: |
echo "Get network name for app_name=${{ inputs.app_name }} and environment=${{ inputs.environment }}"
terraform -chdir=infra/${{ inputs.app_name }}/app-config init > /dev/null
terraform -chdir=infra/${{ inputs.app_name }}/app-config apply -auto-approve > /dev/null
if [[ "${{ inputs.environment }}" == "shared" ]]; then
network_name=$(terraform -chdir=infra/${{ inputs.app_name }}/app-config output -raw shared_network_name)
else
network_name=$(terraform -chdir=infra/${{ inputs.app_name }}/app-config output -json environment_configs | jq -r .${{ inputs.environment }}.network_name)
fi
echo "Network name retrieved: ${network_name}"
echo "network_name=${network_name}" >> "$GITHUB_OUTPUT"
shell: bash

- name: Get account name from network
id: get-account-name
if: ${{ inputs.network_name || steps.get-network-name.outputs.network_name }}
run: |
network_name="${{ inputs.network_name || steps.get-network-name.outputs.network_name }}"
echo "Get account name for network: ${network_name}"
terraform -chdir=infra/project-config init > /dev/null
terraform -chdir=infra/project-config apply -auto-approve > /dev/null
account_name=$(terraform -chdir=infra/project-config output -json network_configs | jq -r .${network_name}.account_name)
echo "Account name retrieved: ${account_name}"
echo "account_name=${account_name}" >> "$GITHUB_OUTPUT"
shell: bash

- name: Get AWS account authentication details (AWS account, IAM role, AWS region)
run: |
# Get AWS account authentication details (AWS account, IAM role, AWS region)
Expand All @@ -22,34 +62,31 @@ runs:
echo "::group::AWS account authentication details"
account_name="${{ inputs.account_name || steps.get-account-name.outputs.account_name }}"
terraform -chdir=infra/project-config init > /dev/null
terraform -chdir=infra/project-config apply -auto-approve > /dev/null
AWS_REGION=$(terraform -chdir=infra/project-config output -raw default_region)
echo "AWS_REGION=$AWS_REGION"
GITHUB_ACTIONS_ROLE_NAME=$(terraform -chdir=infra/project-config output -raw github_actions_role_name)
echo "GITHUB_ACTIONS_ROLE_NAME=$GITHUB_ACTIONS_ROLE_NAME"
terraform -chdir=infra/${{ inputs.app_name }}/app-config init > /dev/null
terraform -chdir=infra/${{ inputs.app_name }}/app-config apply -auto-approve > /dev/null
ACCOUNT_NAME=$(terraform -chdir=infra/${{ inputs.app_name }}/app-config output -json account_names_by_environment | jq -r .${{ inputs.environment }})
echo "ACCOUNT_NAME=$ACCOUNT_NAME"
aws_region=$(terraform -chdir=infra/project-config output -raw default_region)
echo "aws_region=${aws_region}"
github_actions_role_name=$(terraform -chdir=infra/project-config output -raw github_actions_role_name)
echo "github_actions_role_name=${github_actions_role_name}"
# Get the account id associated with the account name extracting the
# ACCOUNT_ID part of the tfbackend file name which looks like
# <ACCOUNT_NAME>.<ACCOUNT_ID>.s3.tfbackend.
# The cut command splits the string with period as the delimeter and
# extracts the second field.
ACCOUNT_ID=$(ls infra/accounts/$ACCOUNT_NAME.*.s3.tfbackend | cut -d. -f2)
echo "ACCOUNT_ID=$ACCOUNT_ID"
account_id=$(ls infra/accounts/${account_name}.*.s3.tfbackend | cut -d. -f2)
echo "account_id=${account_id}"
AWS_ROLE_TO_ASSUME=arn:aws:iam::$ACCOUNT_ID:role/$GITHUB_ACTIONS_ROLE_NAME
echo "AWS_ROLE_TO_ASSUME=$AWS_ROLE_TO_ASSUME"
aws_role_to_assume=arn:aws:iam::${account_id}:role/${github_actions_role_name}
echo "aws_role_to_assume=${aws_role_to_assume}"
echo "::endgroup::"
echo "Setting env vars AWS_ROLE_TO_ASSUME and AWS_REGION..."
echo "AWS_ROLE_TO_ASSUME=$AWS_ROLE_TO_ASSUME" >> "$GITHUB_ENV"
echo "AWS_REGION=$AWS_REGION" >> "$GITHUB_ENV"
echo "AWS_ROLE_TO_ASSUME=${aws_role_to_assume}" >> "$GITHUB_ENV"
echo "AWS_REGION=${aws_region}" >> "$GITHUB_ENV"
shell: bash
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
Expand Down
1 change: 0 additions & 1 deletion infra/app/app-config/dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ module "dev_config" {
app_name = local.app_name
default_region = module.project_config.default_region
environment = "dev"
account_name = "dev"
network_name = "dev"
domain_name = null
enable_https = false
Expand Down
5 changes: 0 additions & 5 deletions infra/app/app-config/env-config/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
output "account_name" {
value = var.account_name
description = "Name of the AWS account that contains the resources for the application environment."
}

output "database_config" {
value = local.database_config
}
Expand Down
11 changes: 0 additions & 11 deletions infra/app/app-config/env-config/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,6 @@ variable "environment" {
type = string
}

variable "account_name" {
description = <<EOT
Name of the AWS account that contains the resources for the application environment.
The list of configured AWS accounts is stored in /infra/account as
backend config files with the naming convention:
<ACCOUNT_NAME>.<ACCOUNT_ID>.s3.tfbackend
Provide the ACCOUNT_NAME for this variable.
EOT
type = string
}

variable "network_name" {
description = "Human readable identifier of the network / VPC"
type = string
Expand Down
8 changes: 4 additions & 4 deletions infra/app/app-config/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ locals {
region = module.project_config.default_region
}

# The name of the AWS account that contains the resources shared across all
# The name of the network that contains the resources shared across all
# application environments, such as the build repository.
# The list of configured AWS accounts can be found in /infra/account
# The list of networks can be found in /infra/networks
# by looking for the backend config files of the form:
# <ACCOUNT_NAME>.<ACCOUNT_ID>.s3.tfbackend
shared_account_name = "dev"
# <NETWORK_NAME>.s3.tfbackend
shared_network_name = "dev"
}

module "project_config" {
Expand Down
14 changes: 2 additions & 12 deletions infra/app/app-config/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@ output "app_name" {
value = local.app_name
}

output "account_names_by_environment" {
value = merge(
{
for environment, environment_config in local.environment_configs :
environment => environment_config.account_name
},
{ shared = local.shared_account_name },
)
}

output "environments" {
value = local.environments
}
Expand Down Expand Up @@ -44,6 +34,6 @@ output "environment_configs" {
value = local.environment_configs
}

output "shared_account_name" {
value = local.shared_account_name
output "shared_network_name" {
value = local.shared_network_name
}
1 change: 0 additions & 1 deletion infra/app/app-config/prod.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ module "prod_config" {
app_name = local.app_name
default_region = module.project_config.default_region
environment = "prod"
account_name = "prod"
network_name = "prod"
domain_name = null
enable_https = false
Expand Down
1 change: 0 additions & 1 deletion infra/app/app-config/staging.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ module "staging_config" {
app_name = local.app_name
default_region = module.project_config.default_region
environment = "staging"
account_name = "staging"
network_name = "staging"
domain_name = null
enable_https = false
Expand Down
3 changes: 2 additions & 1 deletion infra/app/build-repository/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ locals {

# Get list of AWS account ids for the application environments that
# will need access to the build repository
app_account_names = values(module.app_config.account_names_by_environment)
network_names = toset([for environment_config in values(module.app_config.environment_configs) : environment_config.network_name])
app_account_names = [for network_name in local.network_names : module.project_config.network_configs[network_name].account_name]
account_ids_by_name = data.external.account_ids_by_name.result
app_account_ids = [for account_name in local.app_account_names : local.account_ids_by_name[account_name] if contains(keys(local.account_ids_by_name), account_name)]
}
Expand Down
3 changes: 3 additions & 0 deletions infra/project-config/networks.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
locals {
network_configs = {
dev = {
account_name = "dev"
database_subnet_group_name = "dev"

domain_config = {
Expand Down Expand Up @@ -28,6 +29,7 @@ locals {
}

staging = {
account_name = "staging"
database_subnet_group_name = "staging"

domain_config = {
Expand All @@ -39,6 +41,7 @@ locals {
}

prod = {
account_name = "prod"
database_subnet_group_name = "prod"

domain_config = {
Expand Down

0 comments on commit 46949a5

Please sign in to comment.