はじめに

こんにちは!エンタープライズクラウド事業部の名和です。
今回はControl Towerで特定OU配下にMemberAccountが作成された際に、自動でIAM Identity Centerの権限グループへ許可セットを付与するアーキテクチャを構築したのでご紹介します。

現在Control Towerを利用してマルチアカウント環境を構築しています。
その中で、特定OUにMemberAccountを作成した際、特定の権限グループに対して新規MemberAccountの許可セットの付与を手動で行うといった作業をしていました。
ですが、今後本運用に入った際に手作業で許可セット付与を行うのは現実的でないため、許可セット自動付与を行えるアーキテクチャを構築しました。

概要

全体の構成図は下記の通りです。
本構成はPayer AccountとID-Manage Accountの2つのAWSアカウントにまたがるクロスアカウント構成です。
イベント駆動のサーバーレスアーキテクチャにより、アカウント作成から権限付与までを実現します。

Account 主なサービス
Payer Account Control Tower / CloudTrail / EventBridge
ID-Manage Account EventBridge / Lambda / IAM Identity Center / SNS

処理の全体フローは以下のとおりです。

  1. Control Towerが特定OU(Hoge OU)配下へMemberAccountを作成
  2. CloudTrailがAPIコールを記録し、Payer AccountのEvent Busへ送信
  3. EventBridgeルールが「特定OU配下へのMemberAccount作成」イベントを検知
  4. イベントをクロスアカウントでID-Manage AccountのEvent Busへ転送
  5. LambdaがIAM Identity Center APIを呼び出し、権限グループへ許可セットを自動付与
  6. エラー発生時はSNS経由でSlackへ通知

実装のポイント

① クロスアカウントEventBridge転送の設定

Payer AccountからID-Manage AccountへEventBridgeイベントを転送するには、ID-Manage AccountのEvent Busリソースポリシー でPayer AccountからのPutEventsを許可する必要があります。

{
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam:::root"
  },
  "Action": "events:PutEvents",
  "Resource": "arn:aws:events:ap-northeast-1::event-bus/default"
}

② EventBridgeイベントパターン

Payer Account側のEventBridgeルールでは、Control Towerの CreateManagedAccount イベントを対象OUのIDでフィルタリングします。

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

③ LambdaによるIAM Identity Center操作

LambdaはIAM Identity Center(SSO)APIの create_account_assignment を使用して、権限グループと許可セットを新規MemberAccountに関連付けます。

import boto3

sso_admin = boto3.client('sso-admin', region_name='ap-northeast-1')

def lambda_handler(event, context):
    account_id = event['detail']['serviceEventDetails']['createManagedAccountStatus']['account']['accountId']

    response = sso_admin.create_account_assignment(
        InstanceArn='arn:aws:sso:::instance/ssoins-xxxxxxxxxx',
        TargetId=account_id,
        TargetType='AWS_ACCOUNT',
        PermissionSetArn='arn:aws:sso:::permissionSet/ssoins-xxxxxxxxxx/ps-xxxxxxxxxx',
        PrincipalType='GROUP',
        PrincipalId='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'  # 権限グループID
    )
    return response

LambdaのIAMロールには sso:CreateAccountAssignment 権限が必要です。最小権限の原則に従って付与してください。

④ エラー通知(SNS → Slack)

Lambda処理中に例外が発生した場合、SNSトピックへパブリッシュしてSlackへ通知します。
今回はエラー検知さえできればよかったためLambdaの送信先設定を利用して、非同期呼び出しで例外発生時にSNSトピックへ送信する方法を採用しました。
通知メッセージをより分かりやすい形に加工したい等あれば、下記のtry/exceptでエラーをcatchしてSNSへパブリッシュする方法等ご活用ください。

import json

sns = boto3.client('sns')

try:
    # IAM Identity Center API呼び出し
    ...
except Exception as e:
    sns.publish(
        TopicArn='arn:aws:sns:ap-northeast-1::error-notification',
        Message=json.dumps({'error': str(e), 'account_id': account_id}),
        Subject='[ERROR] PermissionSet付与に失敗しました'
    )
    raise

注意点

リージョンの統一 EventBridgeのクロスアカウント転送は同一リージョン間のみサポートされます。Payer AccountとID-Manage Accountで同じリージョンを使用するよう設計してください。

OUのID指定 「② EventBridgeイベントパターンにてOUを指定する際に、指定されたOUしか検知しません。親OUのIDを指定してもその配下の子OUの検知は行えないので検知したいOUのIDは全て個別に指定するようご注意ください。

まとめ

今回はMemberAccount作成から許可セット付与までを完全自動化するアーキテクチャをご紹介しました。

  • ゼロタッチで自動化:アカウント作成直後に権限が付与され、対応漏れが発生しない
  • フルサーバーレス:管理コストが低く、スケーラビリティも自動確保
  • エラーの即時通知:Slackへのアラートで障害対応の遅延を防止

マルチアカウント環境のガバナンス強化とオペレーション効率化を同時に実現したいチームの参考になれば幸いです。


※本記事で使用しているコードはサンプルです。実際の環境に合わせてARNやIDを書き換えてご利用ください。