マルチアカウント環境で StackSets の失敗を検知し、通知する方法

記事タイトルとURLをコピーする

カスタマーサクセス部 岡部です。

AWS Organizations を利用したマルチアカウント環境にて AWS CloudFormation StackSets(以下 StackSets)が失敗したときに検知、通知をしたいと思い実装しましたが、いくつか躓くポイントがありました。
その躓いたポイントと実装方法を合わせてブログでご紹介します。

はじめに

初期構築時は別ですが、基本的に StackSets は新規アカウントが組織に発行されたタイミングなどに自動で動作するように実装すると思います。
StackSets 利用時の注意点として、StackSets の失敗は実際に対象アカウントの StackSets の画面を見にいかなければ気付けない、ということがあります。
もし StackSets が何らかの原因により失敗してしまった場合、StackSets の修正や再実行等の対応が必要となりますので、失敗時のみにその旨を検知し、Slack に通知するための実装方法を本ブログで具体的に記載していきます。

また、今回検証、実装していく中で躓いたポイントは以下の 2 つです。

  • 委任管理アカウントだけでは StackSets の失敗は検知できない
  • AWS Chatbot の通知内容がわかりにくい

StackSets は他のメンバーアカウントに委任しているため、委任管理アカウントのみで失敗の検知、通知を実装したかったのですが、それはできませんでした。
さらに、Slack への通知を実装した際に AWS Chatbot の通知内容がわかりにくいと感じ、修正方法も調査いたしましたので、それぞれご紹介いたします。

※ 実際の環境をイメージしやすいように、AWS Organizations の管理アカウントを Management Account、StackSets の委任管理アカウントを Security Account として記載していきます。

AWS 環境構成図

構成図は以下となります。 前半部分:
StackSets は Security Account に委任されていますが、実際には StackSets のリソースは Management Account に作成されます。そのため、そのイベントを Management Account 内の EventBridge で検知し、Security Account へ送信します。

後半部分:
Management Account のイベントを Security Account の EventBridge が受信したら、Input Transformer を利用して Slack に適した形式へ修正し、Amazon SNS、AWS Chatbot へと連携します。

設定方法

早速、設定方法について記載していきます。

a. Management Account にて EventBridge Rule を作成する

まずは Management Account にて StackSets の失敗を検知し、Security Account へ送信する Rule を作成する必要があります。

これは、StackSets のリソースは委任された Security Account に作成されるのではなく、Management Account に作成され、イベントも Management Account にて発生するためです。
StackSets は Security Account で実行していたので、リソースおよびイベントも Security Account に存在していると思っていました。ここが 1 つ目の躓きポイントです。
参考: AWS アカウント間での Amazon EventBridge イベントの送受信

次に、対象のイベントは AWS が発行するイベントなので Event bus は default を選択します。
Rule type は Rule with an event pattern を選択します。

Event source は Other を選択します。(デフォルト設定でも後述の Creation method の選択時に自動で Other が選択されます。)

Sample event はテスト用の項目となるので、今回はスキップします。
Method は Custom pattern (JSON editor) を選択して、Event pattern には下記を入力します。

{
  "source": ["aws.cloudformation"],
  "detail-type": ["CloudFormation StackSet Operation Status Change"],
  "detail": {
    "status-details": {
      "status": ["FAILED"]
    }
  }
}

Target では送信先の Event Bus を指定します。

Target types は EventBridge event bus、Target types は Event bus in a different account or Region、Event bus as target には送信先(Security Account)の Event Bus を入力します。

Execution role は Create a new role for this specific resource にて AWS 側で IAM ロールを作成してくれるので、こちらを利用します。
名前は環境に合わせて修正してください。

Tags は自由に設定し、確認画面にて問題がなければ「Create rule」を押下します

b. Security Account にて EventBridge Event Bus のリソースベースポリシーを記載する

EventBridge の送信先である Security Account の Event Bus (default) にて、他アカウントからの Event 受信を許可します。

今回は Organizations ID を指定して、Management Account だけでなく AWS Organizations に属するすべてのアカウントからの Event を許可することとします。

"Resource" には Security Account の default Event Bus の ARN を、"aws:PrincipalOrgID" にはアカウントが所属する Organizations ID を記載します。

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "AllowAllAccountsFromOrganizationToPutEvents",
    "Effect": "Allow",
    "Principal": "*",
    "Action": "events:PutEvents",
    "Resource": "arn:aws:events:ap-northeast-1:${Account ID}:event-bus/default",
    "Condition": {
      "StringEquals": {
        "aws:PrincipalOrgID": "${Organizations ID}"
      }
    }
  }]
}

c. Security Account にて EventBridge Rule を作成する

Security Account では Management Account から送信される Event を検知し、AWS Chatbot へ連携するための EventBridge Rule を作成します。

Event pattern までは Management Account で設定した内容と同様です。

Target は SNS topic を選択します。
この SNS Topic には Slack Channel への通知を登録している AWS Chatbot を設定しています。

AWS Chatbot の設定について下記をご参照ください。
blog.serverworks.co.jp

Tags は自由に設定し、確認画面にて問題がなければ「Create rule」を押下します。

ここまでで、対象の Slack Channel へ失敗通知が来るように設定できました。

d. Security Account にて AWS Chatbot へ送信する際の体裁を整える

まずは失敗するような StackSets をデプロイして、テストをしてみましょう。
サンプルとして通知内容を記載します。

ただ、この内容だと StackSets の ARN しかわからないので、設定内容を知らない人は StackSets で何が起きているかわかりにくいのではないでしょうか。
ここが 2 つ目の躓きポイントでした。

それでは、通知内容を修正していきます。
修正方法ですが、AWS Chatbot の通知内容を直接修正することはできないため、EventBridge 側の送信データを修正して、間接的に Slack への通知内容を修正します。
(※ただし、AWS Chatbot の通知内容については AWS から詳細が公開されておらず、今後のアップデートにより意図しない内容での通知となる可能性がございます。)

EventBridge Rules の Targets 設定で Input transformer という機能があるので、これを使って出力内容を修正します。

詳しくは、以下の AWS 公式ドキュメントに記載のあるチュートリアルもご確認ください。

docs.aws.amazon.com

Security Account の Rule を修正します。

Sample event はテスト用の項目となるので、今回はスキップします。
記載するのは Target input transformer の Input pathInput template です。

Input path では変数を定義して Input template では出力形式を記載しています。

Input path

{
  "stack-set-operation-id": "$.detail.stack-set-operation-id",
  "detail-type": "$.detail-type",
  "resources": "$.resources",
  "status-details": "$.detail.status-details.status",
  "source": "$.source",
  "id": "$.id",
  "time": "$.time",
  "region": "$.region",
  "arn": "$.detail.stack-set-arn",
  "version": "$.version",
  "account": "$.account"
}

Input template

{
  "version": <version>,
  "id": <id>,
  "detail-type": <detail-type>,
  "source": <source>,
  "account": <account>,
  "time": <time>,
  "region": <region>,
  "resources": [
    "Status: <status-details>",
    "StackSet Arn: <arn>",
    "StackSet Operation ID: <stack-set-operation-id>"
  ]
}

それぞれ記載できたら confirm を押下して、Rule の設定を更新します。

再度テストして意図した出力内容となっているか確認します。
設定後のサンプルは以下です。

見やすくなったでしょうか?
StackSets Operation の Status を出力することで、StackSets Operation が失敗していることがわかります。
また、StackSets Operation ID も出力しているので、調査もしやすくなりました。

Input template をさらに修正することで、今回の形式以外にも出力形式を変更することは可能となっています。
しかし、見かけ上はわかりませんが "version" や "id" など AWS Chatbot 側で必須項目としている要素があり、要素が足りない場合は AWS Chatbot から Slack に通知されませんので、ご注意ください。
Slack に届かない場合は AWS Chatbot 側のメトリクス等も確認してみてください。

おわりに

AWS Organizations において Management Account ではできるだけリソースを作ることや操作をしないことがベストプラクティスとされていますが、まだ委任できないサービスや今回のように Management Account 側でのリソースの作成や操作が必要なパターンがありますので、ご注意いただけたらと思います。

また、私は今回 AWS Organizations の委任について、「委任されたアカウントが管理者として任命される」のではなく、あくまで「AWS Organizations の機能の操作権限を委任(権限を譲渡)される」ということを改めて理解できました。
参考:委任された管理者の登録

例えば AWS CloudTrail の場合も "組織の証跡" はあくまで Management Account のリソースであり、委任されているアカウントは組織の証跡(Management Account のリソース)の操作権限を持っているだけに過ぎない、ということもあります。

本ブログが AWS Organizations、AWS CloudFormation StackSets をより使いやすくなるためのヒントになれば幸いです。

それでは、またお会いしましょう。

岡部 純 (記事一覧)

カスタマーサクセス部所属
AWS資格全冠取得