AWSアカウント間でAmazon EventBridgeイベントを送受信してみた

2020.03.28

Amazon EventBridge のイベントバスから別AWSアカウントのターゲットを呼び出したいことがあります。

EventBridge は Amazon SNS トピックのように別アカウントのターゲットを直接呼び出せないため

  • 送信側アカウントのイベントバスから受信側アカウントのイベントバスへのPub/Sub
  • 受信側アカウントのイベントバスからお目当てのターゲットへのPub/Sub

という多段の Pub/Sub 構成で実現します。

やってみた

AWSアカウント間のAmazon EventBridgeイベント送受信を実際にやってみます。

まず単一アカウントで動作させ、その後、クロスアカウントで動作させます。

ポイントを先にお伝えします

  • 別アカウントのターゲットを直接呼び出せないので、別アカウントのイベントバスを経由
  • イベントバス間では双方向の信頼関係が必要
  • アクセス制限はターゲットの種類によって異なる。呼び出し元のルールにポリシーを付与するケース(アイデンティティベース)と呼び出し先のターゲットにポリシーを付与するケース(リソースベース)がある

単一アカウントで EventBridge を動作

まずはシンプルにイベント受信側のアカウントだけで EventBridge を動作させます。

EC2 の任意のインベントをイベントソースとし、 EventBridge のイベントバスを経由して Lambda 関数を呼び出します。

Lambda 関数の作成

Lambda 関数を適当に作成します。

exports.handler = async (event) => {
    console.log(event)
};

トリガーの設定は後で行います。

EventBridge ルールの追加

default イベントバスに対して新規ルールを追加します。

パターンを定義

イベントバスに送信されたメッセージのうち、ルーティングするメッセージパターンを定義します。

今回は、任意の Amazon EC2 イベントをルーティングします。

項目
パターン イベントパターン
イベント一致パターン サービスごとの事前定義パターン
サービスプロバイダー AWS
サービス名 EC2
イベントタイプ すべてのイベント

生成されるイベントパターンは以下の通りです。

{
  "source": [
    "aws.ec2"
  ]
}

イベントバスを選択

「AWS のデフォルトのイベントバス」を選択します。

ターゲット

項目
ターゲット Lambda 関数
機能 作成した関数名

を選択します。

Lambda 関数のアクセス権限

イベントバスがLambda関数を呼び出せるように Lambda 関数に対してリソースベースの IAM ポリシーを設定します。

Lambda関数のトリガー追加画面から設定します。

項目
AWSサービス CloudWatch Events/EventBridge
ルール 作成したルール

を選択します。

Lambda 関数に次のような IAM ポリシーが設定されます。

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "lambda-56354727-6162-40cf-a8f8-63d58b809ded",
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:ap-northeast-1:12345:function:dummy",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:events:ap-northeast-1:12345:rule/Test"
        }
      }
    }
  ]
}

Lambda 関数のトリガー追加画面から新規ルールの作成とポリシー設定を同時に行うことも可能ですが、ルールに設定できるイベントパターンが限定的なため、今回のウォークスルーのように、予め EventBridge のルールを定義することをおすすめします。

動作確認

EC2 インスタンスを起動し、CloudWatch Logs などからこの Lambda 関数が呼び出されることを確認してください。

2020-03-27T11:33:45.765Z	XXX	INFO	{
  version: '0',
  id: 'YYY',
  'detail-type': 'EC2 Instance State-change Notification',
  source: 'aws.ec2',
  account: '受信側AWSアカウント',
  time: '2020-03-27T11:33:45Z',
  region: 'ap-northeast-1',
  resources: [
    'arn:aws:ec2:ap-northeast-1:受信側AWSアカウント:instance/i-12345'
  ],
  detail: { 'instance-id': 'i-12345', state: 'pending' }
}

クロスアカウントで EventBridge を動作

次に、イベント送信側 AWS アカウントで発生したイベントが、先程設定した受信側 AWS アカウントのターゲットを呼び出すようにします。

追加の作業は、送信側アカウントの EventBridge ルールのターゲットに受信側アカウントのイベントバスを指定し、相互に信頼させるだけです。

送信側・受信側それぞれの AWS アカウントで作業が発生します。

受信側アカウントの作業

default イベントバスのアクセス許可の設定画面で送信側アカウントIDを入力します。

設定画面からわかるように、組織の親アカウントからすべての子アカウントに一括送信することもできます。

このデフォルトバスの ARN を控えます。

送信側アカウントの作業

送信側アカウントの default イベントバスに、受信側アカウントのイベントバスをターゲットとするルールを追加します。

パターンを定義

先程と同じパターンを設定します。

ターゲット

項目
ターゲット 別のAWSアカウントのイベントバス
イベントバス 受信側イベントバスの ARN(先程控えたもの)

を設定します。

アクセス許可

このルールが受信側アカウントのイベントバスにメッセージ送信できるように、アイデンティティベースのアクセス設定をします。

オンデマンドで作成しても良いですし、予め以下のような IAM ロールを作成して割り当てても問題ありません。

信頼関係

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

アクセス権限

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "events:PutEvents"
            ],
            "Resource": [
                "arn:aws:events:ap-northeast-1:受信側アカウントID:event-bus/default"
            ]
        }
    ]
}

動作確認

イベント送信側アカウントで EC2 インスタンスを起動し、受信側アカウントの CloudWatch Logs などから Lambda 関数が呼び出されることを確認してください。

2020-03-27T11:58:20.560Z	XXX	INFO	{
  version: '0',
  id: 'XXX',
  'detail-type': 'EC2 Instance State-change Notification',
  source: 'aws.ec2',
  account: '送信側AWSアカウント',
  time: '2020-03-27T11:58:19Z',
  region: 'ap-northeast-1',
  resources: [
    'arn:aws:ec2:ap-northeast-1:送信側AWSアカウント:instance/i-12345'
  ],
  detail: { 'instance-id': 'i-12345', state: 'pending' }
}

注意:ルールとターゲット間のアクセス許可方法

ターゲットの種類によってアクセス許可方法が異なります。

S3 はクライアント側(IAM ユーザーなど)とサーバー側(バケットポリシー)の両サイドからアクセス制限をかけられるように、ルールとターゲット間のアクセス許可は

  • ターゲットにリソースベースで設定(ターゲットがAWS Lambda, Amazon SNS, Amazon SQS, Amazon CloudWatch Logsの場合)
  • ルールにアイデンティティベースで設定(上記以外)

の2種類があります。

本ブログのウォークスルーでは

  • Lambda へのメッセージ送信はリソースベース
  • 別AWSアカウントのイベントバスへのメッセージ送信はアイデンティティベース

です。

ターゲットに応じて正しくアクセス許可してください。

参考 : Amazon EventBridge に対する認証とアクセスコントロール - Amazon EventBridge

最後に

Amazon EventBridgeはイベント駆動型アーキテクチャを構築するための理想的なサービスです。

クロスアカウントなメッセージ配信も、今回紹介したように多段Pub/Subすることで簡単に実現できます。

Amazon EventBridge をフル活用してイベント駆動型アプリケーションをがんがん構築しましょう!

参考