AWSアカウントごとに通知先を分ける EventBridge アーキテクチャ案

2022.04.26

AWSアカウントごとに通知先を分けたい

今回の話の前提は マルチアカウントサービス です。 AWS Organizations や AWS Security Hub、Amazon GuardDuty などがそれに当たります。 これらのサービスは、代表1アカウント上で複数AWSアカウントを集中的に操作・管理できます。 例えば AWS Security Hub では 代表1アカウント上で 他アカウントの セキュリティ検出結果を集約、集中管理できます。

img

図: AWS Security Hub のマルチアカウント利用イメージ

これらマルチアカウントサービスを使っていると AWSアカウントごとに異なる通知先へ振り分けたい ケースが出てきます。 「このプロジェクトに関連するAWSアカウント通知はここに」、 「あのプロジェクトに関連するAWSアカウント通知はあそこに」といったイメージです。 その際の「良いアーキテクチャ」を設計したいです。

もともとは下図のようなアーキテクチャで対応していました。 振り分けの単位で 「EventBridgeルール、SNSトピック」を作成するアーキテクチャです。

img

AWS CloudFormation など IaC ツールを使うことで容易に複製できるので、 このアーキテクチャでも悪くはないです。 しかし、例えば 「AWS Security Hub で通知する検出結果の重要度を変えたい」 といった変更作業が出てきたときに、全ての EventBridgeルールを変更する必要があります。 少し面倒に感じてしまいます。

イベントバス間連携を活用できそう

同一リージョン・同一アカウント内のイベントバス間連携 で (前述の) 課題を解決できそう」と考えました。 下図のような構成です。

img

  • EventBride イベントバスを 2つ利用
    • default : AWSサービスからイベントを受信
    • custom security : 新規作成するカスタムイベントバス。Security Hub のイベントを受信するように構成する
  • EventBride ルールによるフィルタリングを 2段階に分離
    • Security Hub rule : Security Hub の イベントを検知 → custom security イベントバスへ送信
    • Accounts rule : 特定アカウントのイベントを検知 → SNSトピックへ送信

フィルタリングを 2段階に分離することで、通知するしきい値の変更作業を簡素化できます。 つまり 「AWS Security Hub で通知する検出結果の重要度を変えたい」 といったケースの場合、 Security Hub rule の変更のみで済みます。

次章で実際に構築してみます。

※1: 「同一リージョン・同一アカウント内のイベントバス間連携」は比較的新しい(2021年)機能アップデートです。 以下記事を参照ください。

※2: 今回は試していませんが、他にも良いアーキテクチャはありそうです。 例えば SNSトピックの サブスクリプションフィルター を活用する方法です(下図参照)。

img

作ってみる

1. カスタムイベントバスへ送信するところまで

img

  • カスタムイベントバス
  • カスタムイベントバスに送信する EventBridgeルール

これらリソースを作っていきます。

カスタムイベントバス

[EventBridge > イベントバス > イベントバスを作成] からイベントバスを作成します。

名前のみ指定 ( custom-securityhub-bus )、それ以外はデフォルトでOKです。

img

カスタムイベントバスに送信する EventBridgeルール

[EventBridge > ルール > ルールを作成] からルールを作成します。

ルール名を適当に記載 ( capture-securityhub-findings など )、イベントバスは default です

img

イベントパターンは下記のようにしています。 (参考: Security Hub 検出結果のフィルタリング例 | DevelopersIO )

{
  "detail": {
    "findings": {
      "Compliance": {
        "Status": [{
          "anything-but": "PASSED"
        }]
      },
      "ProductName": ["Security Hub"],
      "RecordState": ["ACTIVE"],
      "Severity": {
        "Label": ["CRITICAL", "HIGH"]
      },
      "Workflow": {
        "Status": ["NEW"]
      }
    }
  },
  "detail-type": ["Security Hub Findings - Imported"],
  "source": ["aws.securityhub"]
}

ターゲットは「先程作成したカスタムイベントバス」です。

img

※ターゲットをカスタムイベントバスにする際に IAMロール を作成する必要があります。 以下のような設定値の IAMロールを事前に作成しておきましょう。

  • 信頼関係ポリシー: EventBridgeサービス ( "events.amazonaws.com" ) からの "sts:AssumeRole" を許可
  • ロールポリシー: 該当カスタムイベントバスへの "events:PutEvents" を許可

2. メッセージ送信するところまで

img

  • SNSトピック
  • EventBridgeルール ( from カスタムイベントバス )

これらリソースを作っていきます。 ( 今回は 1プロジェクト分、つまり 図の AAA 関連リソース のみ構築してみます)

SNSトピック

SNSトピックを作成しておきます。サブスクリプション設定も済ませておきましょう。

img

EventBridgeルール ( from カスタムイベントバス )

[EventBridge > イベントバス > イベントバスを作成] からイベントバスを作成します。

名前を適当に記入して ( account-selector-aaa など)、 イベントバスは 先程作成したカスタムイベントバス とします。

img

イベントパターンは下記のようにします。 "AwsAccountId" キー値であるリスト内に 「通知させたい AWSアカウントID」を入力していきます。

{
  "detail": {
    "findings": {
      "AwsAccountId": ["1234567890XX", "1234567890YY", "1234567890ZZ"]
    }
  }
}

ターゲットは 先程作成した SNSトピックとしましょう。

img

以上で リソース作成は完了です。 追加で別に通知させたいプロジェクト(AWSアカウント)がある場合は 「2. メッセージ送信するところまで」 節の手順を同じように実行します。

確認

作成した EventBridgeルール、およびメール通知を確認します。

img

① EventBridge Security Hub rule のメトリクス

TriggerdRulesInvocations が一致していて FailedInvocations はありません。 正常にカスタムイベントバスへ送信できていること確認しました。

img

② EventBridge Accounts rule (AAA) のメトリクス

TriggerdRulesInvocations が一致していて FailedInvocations はありません。 また 「① EventBridge Security Hub rule のメトリクス」と同じグラフとなっています。 正常に ① からイベントを受け取り、SNSトピックへ送信できていること確認しました。

img

③ メール通知

サブスクリプション先のアドレスへメール通知ができていること確認しました。

img

※今回はメッセージの整形までは行っていないです。行い場合は以下ブログを参照ください。

おわりに

以上、マルチアカウントサービスの(柔軟な)通知アーキテクチャ例を考えてみました。

この要件が出てきたときに、始めは Step Functions など活用したほうが良いかなと思っていました。 ある程度シンプルな振り分けであれば、EventBridgeのイベント連携のみで、なんとかなることを確かめられて良かったです。

補足: 今回作成に使った Terraform コード(サンプル)を下記に置いています。

参考