CloudFormation StackSets でAWS Organization 管理下のアカウントのすべてのリージョンにAWS Config を設定して記録を単一バケットに集約するサンプル

AWS Organizations で複数のアカウントを管理してる場合、セキュリティ面からAWS CoudTrail やConfig、GouardDuty などを確実にすべてのアカウトのすべてのリージョンで有効化したいという場合のサンプルです。

このサンプルでは、Organizations のマスターアカウント内に、Config Recorderのログを集約するバケットを作成し、すべての子アカウントのConfig Recorder を作為し、マスターアカウントのバケットに記録を集約する設定をCloudFormation StackSets を利用して自動構成します。

CloudFormation StackSets の詳細は、以下のドキュメントを参照してください。

AWS CloudFormation StackSets の操作 – AWS CloudFormation

2020/02/13 追記 Organizations とStackSets の連携が強化されてOrganizations 配下のアカウントに対するStackSets の利用がより簡単にできるようになりました。以下記事を参照してください。

CFn StackSets の事前準備

StackSets を利用する場合は、CloudFormation が利用するIAM ロールを管理アカウント、対象アカウントの両方に設定する必要があります。なお、管理アカウントはどのアカウントでも良いのですが、このサンプルでは、Oraganizations のマスターアカウントを利用する想定で記述します。

ドキュメントは以下を参考にしてください。

前提条件: スタックセットオペレーションのアクセス権限の付与 – AWS CloudFormation

まずは、マスターアカウント内に、AWSCloudFormationStackSetAdministrationRole を作成します。このロールを作成するためのCFn テンプレートが上述のドキュメントに記載されていますので、それをそのまま利用します。

マスターアカウントの権限で以下を実行してください。

次に、対象アカウントにStackSetExecutionRole を作成します。Organizations 内で作成したAWS アカウントであれば、デフォルト名がOrganizationAccountAccessRole というロールが自動的に作成されていますので、それを利用して各対象アカウント内にStackSetExecutionRoleを作成します。対象アカウント分、TARGET_ACCOUNT_IDを切り替えて繰り返し実行してください。

マスターアカウント内にConfig 用のバケットを作成する

すべての小アカウントからマスターアカウントのバケットにログを集約するため、まず最初にマスターアカウント内にバケットを作成します。その際にバケットポリシーにて、Config からのアクセスを許可するように設定します。

CloudFormation のテンプレートファイルを作成してから、コマンドを実行してください。

StackSets を利用してターゲットアカウントのすべてのリージョンでConfig Recorder を設定する

以下の内容をyaml ファイルに保存してください。シンプル化するために、Config の設定としては最低限にしていますので、必要に応じて適宜編集してください。

マスターアカウントで、以下のコマンドを実行することで、Organizationsの特定OU に所属しているアカウント内のすべてのリージョン(※) にConfig Recorder が設定されます。
※ 2020/02/11 現在、eu-north-1 (ストックホルム) リージョンではStackSets がサポートされていないため、このリージョンだけ除外する必要があります。

実行する前に、ご自身のAWS OrganizationのID とConfig を適用するOU のIDをメモしておいてください。なお、OU ID はcreate-stack-instances で実行対象とするアカウントID を取得するために利用していますが、事前にアカウントID のリストがあればそれをそのままcreate-stack-instances にわたす方法でも問題ありません。ちなみに以下の実装はOU 配下のツリー構造のアカウントを再帰的に取得する実装にはなっていませんのでご注意ください。

Option: StackSets を削除する

作成したStackSets を削除する場合は、以下のコマンドを実行します。最後のdelete-stack-stets を実行する前に、delete-stack-instances 処理が完了するのを待つ必要があります。(Waiter は残念ながら提供されていないため、自動化する場合は、自分で実装してください。)

#!/bin/bash
CONFIG_BUCKET_NAME=<your_config_bucket>
ORGANIZATION_ID=<your_organization_id>
OU_ID=<your_ou_id>   # ou_id is such like ou-xxx-xxxxxx

STACK_SET_NAME=<your_stack_set_name>

OPERATION_REGION_ID=us-east-1

# Get target account ids
accounts=$(aws organizations list-children --parent-id $OU_ID --child-type=ACCOUNT --query "Children[].Id" --region $OPERATION_REGION_ID --output text)

# Get all regions does not work fine. eu-north-1 does not support stacksets
#regions=$(aws ec2 describe-regions --query "Regions[].RegionName" --region $OPERATION_REGION_ID --output text)
regions="ap-south-1 eu-west-3 eu-west-2 eu-west-1 ap-northeast-2 ap-northeast-1 sa-east-1 ca-central-1 ap-southeast-1 ap-southeast-2 eu-central-1 us-east-1 us-east-2 us-west-1 us-west-2"

# Delete Stack Instances
operationid=$(aws cloudformation  delete-stack-instances \
    --stack-set-name $STACK_SET_NAME \
    --accounts $accounts \
    --regions $regions \
    --no-retain-stacks \
    --operation-preferences MaxConcurrentCount=10 \
    --region $OPERATION_REGION_ID \
    --query "OperationId" \
    --output text)

# Wait until status is completed
aws cloudformation describe-stack-set-operation --stack-set-name $STACK_SET_NAME --operation-id $operationid --region $OPERATION_REGION_ID

# Delete stack set
aws cloudformation delete-stack-set --stack-set-name $STACK_SET_NAME \
    --region $OPERATION_REGION_ID

以上です。