技術2課の多田です.
GuardDuty のマルチアカウント管理機能を紹介した記事を書きました.マルチアカウントで GuardDuty を運用するなら有効化すべき機能ですが,多数のアカウントを AWS マネジメントコンソールの操作で有効化するのは煩雑なため, CloudFormation と AWS CLI を使って省力化してみます.
省力化可能な部分の検討
今回,省力化できる箇所は以下のものと考えました.
- メンバーアカウントに対してマスターアカウントからアカウント管理機能の招待を送る処理
- メンバーアカウントでマスターアカウントからの招待を受ける処理
- GuardDuty の DetectorID を取得する処理
それぞれの処理ごとで省力化した箇所とコード例を記載していきます.
1. メンバーアカウントに対してマスターアカウントからアカウント管理機能の招待を送る処理
マスターアカウントがメンバーアカウントのイベントを管理するためには, メンバーアカウントへマスターアカウントに統合するための招待を送る必要があります.なお, AWS では利用可能なリージョン全てで GuardDuty を有効化することが推奨されておりますので本記事では,マスターアカウントの全リージョンからメンバーアカウントに招待通知を出す処理を CloudFormation で省力化するコードを紹介します.
GuardDuty は、サポートされているすべての AWS リージョンで有効にすることが強く推奨されています。このように設定することで、お客様が能動的に使用していないリージョンでも、許可されていないアクティビティや異常なアクティビティに関する検索結果を GuardDuty で生成できます。
関連ドキュメント
Amazon GuardDuty でサポートされているリージョン
CloudFormation テンプレート例
CloudFormation の StackSets 機能を使ってマスターアカウントの全リージョンに対して下記のテンプレートを実行することで指定のメンバーアカウントに対して招待通知を出せます.AWS::GuardDuty::Member
の Status: "Invited"
で設定するとメンバーアカウントに招待通知を出す処理まで一気に設定可能ですので,この設定は定義しておくと良いでしょう.
AWSTemplateFormatVersion: 2010-09-09 Description: Creates an AWS::GuardDuty::Detector resource and optionally an AWS::GuardDuty::Master resource in a set of accounts and regions. Mappings: GuardDutyMembers: us-east-1: DetectorId: xxxx us-east-2: DetectorId: xxxx us-west-1: DetectorId: xxxx us-west-2: DetectorId: xxxx ca-central-1: DetectorId: xxxx eu-central-1: DetectorId: xxxx eu-west-1: DetectorId: xxxx eu-west-2: DetectorId: xxxx eu-west-3: DetectorId: xxxx ap-northeast-1: DetectorId: xxxx ap-northeast-2: DetectorId: xxxx ap-southeast-1: DetectorId: xxxx ap-southeast-2: DetectorId: xxxx ap-south-1: DetectorId: xxxx sa-east-1: DetectorId: xxxx Parameters: MemberAccountId: Description: Type Member Account Number. Type: String MemberAccountEmail: Description: Type Member Account Email. Type: String Resources: Member: Type: AWS::GuardDuty::Member Properties: Status: "Invited" MemberId: !Ref MemberAccountId Email: !Ref MemberAccountEmail DetectorId: !FindInMap [GuardDutyMembers,!Ref "AWS::Region", DetectorId] DisableEmailNotification: True
なお,CloudFormation の StackSets 機能が使えないリージョンでは手動でメンバーアカウントの招待を行う必要があります.多数のアカウントに対して招待を出す場合,CSVファイルに次のようにメンバーアカウントの AWS アカウント番号とメールアドレスを記載したものを読み込ませるとスムーズです。
Account ID,Email
111111111111,user@example.com
CloudFormation ドキュメント
2. メンバーアカウントでマスターアカウントからの招待を受ける処理
マスターアカウントからメンバーアカウントへアカウント統合の招待を出した後は,メンバーアカウントでその招待を承認しなければなりません.その承認処理を CloudFormation で省力化します.マスターアカウントからの招待通知同様に全リージョンで承認処理を行うためのテンプレート例を紹介します.
CloudFormation テンプレート例
このテンプレートもメンバーアカウントで StackSets 機能を使って全リージョンの招待通知を一度に承認する処理を省力化しています.
AWSTemplateFormatVersion: 2010-09-09 Description: Approve Invitation From GuardDuty Master Account. Mappings: GuardDutyMasters: us-east-1: DetectorId: xxxx us-east-2: DetectorId: xxxx us-west-1: DetectorId: xxxx us-west-2: DetectorId: xxxx ca-central-1: DetectorId: xxxx eu-central-1: DetectorId: xxxx eu-west-1: DetectorId: xxxx eu-west-2: DetectorId: xxxx eu-west-3: DetectorId: xxxx ap-northeast-1: DetectorId: xxxx ap-northeast-2: DetectorId: xxxx ap-southeast-1: DetectorId: xxxx ap-southeast-2: DetectorId: xxxx ap-south-1: DetectorId: xxxx sa-east-1: DetectorId: xxxx Parameters: MasterAccountNumber: Type: String Resources: Master: Type: AWS::GuardDuty::Master Properties: DetectorId: !FindInMap [GuardDutyMasters,!Ref "AWS::Region", DetectorId] MasterId: !Ref MasterAccountNumber
CloudFormation ドキュメント
3. GuardDuty の DetectorID を取得する処理
最後に, 1,2 のCloudFormation テンプレートの定義で必ず必要な GuardDuty の DetectorID
取得を AWS CLI で全リージョン分取得する処理を紹介します.マスターアカウントでもメンバーアカウントでも必ず必要なため同様の処理を検討している方の参考になれば嬉しいです.
AWS CLI コード例
以下の2行で取得可能です.最初にリージョンのエンドポイントをソートして取得し,次に GuardDuty の DetectorID
をリージョンごとに取得しています.
# リージョン全取得して配列に格納(-r をつけるとダブルクオーテーションを削除可能) declare -a REGIONS=( $(aws ec2 describe-regions | jq -r '.Regions[] | .RegionName' | sort) ) # GuardDutyのDetectorIDをリージョンごとに表示する for i in ${REGIONS[@]}; do echo "$i = $( aws guardduty list-detectors --region $i | jq -r '.DetectorIds[]')";done
シェルスクリプト化してこんな感じに一気に取得することができます.
AWS CLI ドキュメント
まとめ
GuardDuty のマルチアカウント管理機能有効化を省力化するために行った CloudFormation と AWS CLI の意図とコードを紹介しました.他にもいろんな方法があるかと思いますが次はAWS CDK
でも同様のことを実現できないかをトライしてみたいと思います.