この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
ちゃだいん(@chazuke4649)です。
AWS Control Tower Account Factory for Terraform (AFT) を使って、AWSアカウントのカスタマイズをマルチリージョンに対して実施してみます。
AFTに関する過去の記事は以下ハッシュタグよりご確認ください。
経緯
Control Towerにてマルチアカウント管理を行う上で、セキュリティ・ガバナンス系サービスを利用する際に全リージョンに同じリソースを作成したいケースがあります。例えば、GuardDutyやSecurity Hubがそれに該当します。
これらをAFTで実現する場合どうするか調べました。
すると、すでにイシューにて「マルチリージョンのカスタマイズ方法」についてのやりとりを見つけました。
Customizations multiple regions · Issue #59 · aws-ia/terraform-aws-control_tower_account_factory
こういった要望を経て、現時点で最新バージョンの 1.3.3
では、Deploying customizations to multiple regions の Example が追加されました。
Release 1.3.3 · aws-ia/terraform-aws-control_tower_account_factory
実際のExampleはこちらです。
Terraformでやってみる
前提
前々回で既存AWSアカウントに対してカスタマイズを実行しましたが、この続きとして行いますので、ここまでの作業が完了している前提で進めます。
手順
Exampleを参考に行います。 以下手順となります。
- 1.aft-providers.jinjaにてproviderを追加する
- 2.Terraformコードにてリソースブロックを追加する
- 3.カスタマイズを実行する
「3.カスタマイズを実行する」については、前々回のカスタマイズと同じ作業になるので、こちらの記事の「3.手動でStep Functionsを実行」を参照ください。
1.aft-providers.jinjaにてproviderを追加する
そもそもJinjaとはPythonのテンプレートエンジンであり、Terraformコードを動的に生成するツールとのことです。AFTではterraformブロックとproviderブロックの生成にこのJinjaが使われているようです。
そのテンプレートである aft-providers.jijna`を以下ハイライト箇所を追加します。
aft-providers.jinja
## Auto generated providers.tf ##
## Updated on: {{ timestamp }} ##
provider "aws" {
region = "{{ provider_region }}"
assume_role {
role_arn = "{{ target_admin_role_arn }}"
}
default_tags {
tags = {
Project = "Example",
Terraform = true,
AFT = true
}
}
}
provider "aws" {
alias = "ap-se-1"
region = "ap-southeast-1"
assume_role {
role_arn = "{{ target_admin_role_arn }}"
}
default_tags {
tags = {
Project = "Example",
Terraform = true,
AFT = true
}
}
}
provider "aws" {
alias = "us-ea-1"
region = "us-east-1"
assume_role {
role_arn = "{{ target_admin_role_arn }}"
}
default_tags {
tags = {
Project = "Example",
Terraform = true,
AFT = true
}
}
}
今回は、ホームリージョンである東京以外に、バージニアとシンガポールリージョンのproviderを追加しています。
2. Terraformコードにてリソースブロックを追加する
続いて、上記により生成される各リージョンのプロバイダーを使用し、S3バケットを3つのリージョンに作成するよう定義します。
s3.tf
data "aws_caller_identity" "current" {}
resource "aws_s3_bucket" "ap-ne-1" {
bucket = "aft-test-${data.aws_caller_identity.current.account_id}-${local.regions.ap-ne-1}"
tags = { Name = "aft-test-${data.aws_caller_identity.current.account_id}-${local.regions.ap-ne-1}" }
}
resource "aws_s3_bucket" "ap-se-1" {
provider = aws.ap-se-1
bucket = "aft-test-${data.aws_caller_identity.current.account_id}-${local.regions.ap-se-1}"
tags = { Name = "aft-test-${data.aws_caller_identity.current.account_id}-${local.regions.ap-se-1}" }
}
resource "aws_s3_bucket" "us-ea-1" {
provider = aws.us-ea-1
bucket = "aft-test-${data.aws_caller_identity.current.account_id}-${local.regions.us-ea-1}"
tags = { Name = "aft-test-${data.aws_caller_identity.current.account_id}-${local.regions.us-ea-1}" }
}
ポイントとしては、ハイライト箇所にて、それぞれバージニアとシンガポールリージョンのプロバイダーを指定している点です。
また、ここは個人の好みですが、Resourceブロック内のリージョン表記を全て短い略称にするために、以下のようなローカル変数を設定し使用しています。
locals.tf
locals {
regions = {
"ap-ne-1" = "ap-northeast-1", ## Tokyo
"ap-se-1" = "ap-southeast-1", ## Singapore
"us-ea-1" = "us-east-1", ## Virginia
}
}
以上で、設定が完了しました。
実行結果
設定後にStep Functionsを実行してカスタマイズを行った結果、以下の通り3つのリージョンにS3バケットを作成することができました。
Shellでやってみる
AFTではTerraform以外にもPythonやShellスクリプトによってカスタマイズを行うことも可能です。実際、やりたい処理内容によってはTerraformよりも都合がいいものもあります。Shellスクリプトで上記同様に3つのリージョンに対して、何かコマンドを実行したい場合は、デフォルトで配置している api_helpers
ディレクトリ内の pre-api-helpers.sh
などで以下のように実行できます。
例として、3つのリージョンに対してSecurity HubのCISベンチマークのスタンダードを無効化するコマンドとなります。
pre-api-helpers.sh
#!/bin/bash
echo "Executing Pre-API Helpers"
## Security HubにてCISスタンダードを無効化
accountId=`aws sts get-caller-identity --query "Account" --output text`
for region in ap-northeast-1 ap-southeast-1 us-east-1;do
echo "##### disable CIS standard in ${region} for AccountID ${accountId}"
aws --region $region securityhub batch-disable-standards \
--standards-subscription-arns "arn:aws:securityhub:${region}:${accountId}:subscription/cis-aws-foundations-benchmark/v/1.2.0"
done
終わりに
AFTでのマルチリージョンのアカウントカスタマイズを行いました。AFTはスピーディに改良がなされていくので、超ありがたいですしワクワクします。「Control Tower x Terraform 環境では AFT が鉄板」と言える日も近いかと! ぜひ使ってみてください。
それではこの辺で。ちゃだいん(@chazuke4649)でした。