Control Towerカスタマイズソリューション(CfCT)で新規アカウント発行時にCloudFormationを自動展開してみた

Control Towerのカスタマイズソリューションを利用して、マニフェストファイルで定義したCloudFormationテンプレートを新規アカウント発行時に自動展開してみました。
2021.08.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

前回以下の記事でControl Towerのカスタマイズソリューションを展開して、CodeCommitへのPushからCloudFormationとガードレールを展開しました。

Control Towerカスタマイズソリューション(CfCT)を使ってガードレールとCloudFormationを自動展開してみた | DevelopersIO

このソリューションではCodeCommitやS3の変更だけでなく、アカウントファクトリーからの新規アカウントの発行時にもパイプラインを実行することが可能なのでやってみました。

前提

  • Control Tower有効化済(バージョン2.7)
  • ホームリージョンは東京
  • カスタマイズソリューション展開済

構成

今回試すのは、新規アカウントが発行された時に動くライフサイクルイベントワークフローの部分です。Control Towerカスタマイズソリューションを既に展開していれば、個別にリソースを作成する必要はありません。

各リソースについて簡単に説明します。

Control Tower ライフサイクルイベント

Control Towerではイベントが記録され、ライフサイクルイベントとして発行されます。今回利用するライフサイクルイベントは、アカウントファクトリーからAWSアカウントの作成が完了したときに発行されるCreateManagedAccountというライフサイクルイベントです。その他にいくつかライフサイクルイベントがあり、そこからEventBridgeを利用して自動化のフローを作成できます。

AWS Control Tower のライフサイクルイベント - AWS Control Tower

EventBridge

ライフサイクルイベントCreateManagedAccountを取得しSQSにイベントを送信します。イベントパターンは以下のように定義されています。

{
  "detail-type": ["AWS Service Event via CloudTrail"],
  "source": ["aws.controltower"],
  "detail": {
    "serviceEventDetails": {
      "createManagedAccountStatus": {
        "state": ["SUCCEEDED"]
      }
    },
    "eventName": ["CreateManagedAccount"]
  }
}

CreateManagedAccountのイベントを取得して、成功していればSQSに送るように設定されています。

SQS

EventBridgeからイベントを受け取ります。アカウント発行が連続で行われた時には順序性を保つためにキューのタイプはFIFOで作成されています。Lambdaトリガーが定義されており、イベントが格納される度にLambdaを動かす構成となっています。

ソリューションを展開すると、合わせてDLQ用のSQSキューも作成されます。

Lambda

SQSキューからキックされ起動するLambdaです。受け取ったイベントがControl Towerのものであれば後続に定義しているCodePipelineを実行するようになっています。最初はこのLambdaの中でイベントからアカウント番号を取得し実行しているのかと思いましたが、展開する先についてはソースのマニフェストファイルで全て定義しているようです。

構成としてはそこまで難しいものではないので分かりやすいですね。

やってみる

前回と事前準備はほぼ同じなので割愛します。まだソリューションを展開していない方は以下記事の「カスタマイズソリューションを展開する」まで進めてください。

Control Towerカスタマイズソリューション(CfCT)を使ってガードレールとCloudFormationを自動展開してみた | DevelopersIO

マニフェストファイルの修正

マニフェストファイルを新規発行するアカウントを配置するOUにも反映させるため、展開先のOUとして追加します。今回はSandBox OUに追加するため、マニフェストファイルに以下の様に追記します

---
#Default region for deploying Custom Control Tower: Code Pipeline, Step functions, Lambda, SSM parameters, and StackSets
region: ap-northeast-1 # Control Tower Home Region
version: 2021-03-15

resources:
# Control Tower Custom Service Control Policies - Additional Preventive Guardrails
  - name: test-preventive-guardrails
    description: To prevent from deleting or disabling resources in member accounts
    resource_file: s3://marketplace-sa-resources/ctlabs/preventive-guardrails.json
    deploy_method: scp
    #Apply to the following OU(s)
    deployment_targets:
      organizational_units:
          - Security

# Control Tower Custom CloudFormation Resources - Create Additional IAM Role
  - name: create-iam-role
    resource_file: template/describe-regions-iam-role.template
    deploy_method: stack_set
    deployment_targets:
      organizational_units:
          - Security
          - Sandbox
    regions:
    - ap-northeast-1

# Control Tower Config Rule - Additional Detective Guardrails
  - name: rotate-access-keys-guardrail
    resource_file: template/access_keys_rotated.template
    parameters:
    - parameter_key: maxAccessKeyAge
      parameter_value: '24'
    deploy_method: stack_set
    deployment_targets:
      organizational_units:
        - Security
    regions:
    - ap-northeast-1

create-iam-roleの定義ではSandbox OUが対象のためIAMロールをStackSetsで展開しますが、test-preventive-guardrailsrotate-access-keys-guardrailの定義では展開対象がSecurity OUのみのため展開されない動作となるはずです。

マニフェストファイルの書き方については開発者ガイドを参照してください。

AWS Control Towerのカスタマイズ開発者ガイド

ちなみに今回展開するCloudFormationテンプレートはIAMロールを1つ作成するだけです。

Resources:
  TestLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: DescribeRegions
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - ec2:DescribeRegions
                Resource: '*'

新規アカウントを発行

動作を確認するため、Control TowerのAccount Factoryからアカウントの登録を発行します。

アカウント発行に必要な情報を入力して発行します。今回はアカウントをSandboxに配置しました。

アカウントが利用可能になるまでしばらくかかります。アカウントが利用可能となったとき、Control Towerカスタマイズソリューションのアカウント発行フローが動き始めます。

ここからは前回実施したソースへPushしたときと同じパイプラインが実行されるので、中の動作は同じです。新規発行のアカウントなのか既存のアカウントなのかは関係なく、マニフェストファイルで定義されたターゲットに未展開のアカウントがあれば展開されます。

ソース(CodeCommit/S3)の更新とライフサイクルイベントの発行でパイプラインの動作が変わらないのはわかり易くていいですね。

作成されたリソースの確認

パイプラインが完了したら、StackSetsからスタックインスタンスが対象のアカウントに展開されていることを確認できます。新規発行したアカウントにログインしてIAMロールが展開されているか見てみます。

問題なくStackSet-CustomControlTower-create-TestLambdaRole-XXXXXXXXXXという名前で作成されていることが確認できました。

定義していないスタックの確認

マニフェストファイルではcreate-iam-roleのセクションだけSandboxを定義したので、他のリソースについては展開されていません。CloudFormationスタックを確認すると、IAMロールを展開しているStackSet-CustomControlTower-create-iam-role-XXXX以外はカスタマイズソリューションによって展開されていませんでした。

気をつけたいこと

注意したい点としてはマニフェストファイル側でアカウント単位の指定をしてしまうと、アカウントを発行だけしたとしても展開されないことです。パイプラインは起動されますが、マニフェストファイル側でアカウントが展開対象となっていないので、新規アカウントにはリソースが展開されずに正常終了します。

基本的にはOU単位で定義しておくと、アカウント発行時にも自動で展開されるのでこのソリューションを最大限活かせるのかなと思っています。どの範囲(OU単位、アカウント単位)まで自動で展開したいのかをよく考えた上でマニフェストファイルを作成するようにしましょう。

まとめ

Control Towerカスタマイズソリューションの新規アカウント発行の動作を確認してみました。コードで構成を管理でき、自動展開できるためいろいろと活用できそうなソリューションです。ぜひControl Towerを利用している環境で、リソースをマルチアカウントに自動展開したい場合は検討してみてはいかがでしょうか。

参考