こんにちは!Martimです!
今回は、Amazon EventBridge のイベントバスのログを Amazon CloudWatch Logs に配信するために必要な権限設定を、検証用アカウントで段階的に切り分けた結果を共有していきます!
目次
- はじめに
- 先に結論
- 前提:イベントバスのログと Vended log delivery
- 何が分かりにくかったか
- 何を確かめたか
- 検証環境と構成
- 結果1:正しく動いた構成と aws:SourceArn
- 結果2:実際に出たログ
- 結果3:デフォルトバスでも同じ方法で通った
- 結果4:ロググループ名のプレフィックスは関係なかった
- 注意点・ハマりどころ
- 検証コードと再現方法(GitHub)
- 未検証の範囲
- おわりに
- 参考
はじめに
皆さん、「公式ドキュメントを読んだのに、結局どこに何を設定すればいいのか分からない」という経験はありませんか?
「この設定、どのリソースに付けるのが正解なの?」
「サンプルに出てくる値が、自分の環境だと何に当たるのか分からない」
今回の私が、まさにそうでした。Amazon EventBridge のイベントバスのログを CloudWatch Logs に出したくて、公式ドキュメントを読み、re:Post も見ました。それでも、aws:SourceArn に何の ARN を入れればいいのかが、どこにも書かれていませんでした。
そこで、検証用アカウントで設定を段階的に足しながら、実機で確かめてみました!
先に射程を書いておきます。
- 個人の検証用 AWS アカウントでの検証です
- リージョンは
ap-northeast-1のみ、Terraform v1.8.5 / Terraform AWS Provider v6.44.0 での1ケースです - 検証した範囲と、していない範囲を分けて書きます(未検証は最後にまとめました)
検証に使ったコードと記録は、個人リポジトリに置いてあります。
先に結論
-
配信パイプラインの3部品を作った構成で、ログが出力されました。 イベントバスの
log_configに指定できるのはlevelとinclude_detailだけで、宛先を指定する欄がありません。宛先との紐付けは、CloudWatch Logs 側の delivery source / delivery destination / delivery で行います(3部品を省いた場合の挙動は、今回は未検証です) -
ログの書き込み許可は、宛先ロググループ側のリソースポリシーに書きました。 プリンシパルは
delivery.logs.amazonaws.comです - そのポリシーの
aws:SourceArnに delivery-source の ARN を入れた構成で、ログ出力が成立しました - イベントバス自身へのリソースベースポリシーは、無くても出力されました
- デフォルトイベントバスでも、同じ方法で出力されました
- ロググループ名は
/aws/vendedlogs/配下でなくても出力されました
→ つまり、「イベントバスに許可を付ける」ではなく、「配信パイプラインを作り、宛先のロググループに許可を付ける」が今回の構成でした。
ただし、「ロググループ ARN やアカウントワイルドカードを入れたら失敗する」という確認は、今回していません。 「delivery-source の ARN なら通る」ことは確認できましたが、「それ以外はダメ」とまでは言えません。あとで詳しく書きます。
前提:イベントバスのログと Vended log delivery
Vended log delivery とは
Vended log delivery とは、AWS サービスが生成するログを、Amazon CloudWatch Logs・Amazon S3・Amazon Data Firehose などの宛先へ配信するための仕組みで、delivery source・delivery destination・delivery の3部品を組み合わせて構成します。
| 部品 | 役割 |
|---|---|
| delivery source | ログの出どころ(今回はイベントバス)を表す論理オブジェクト |
| delivery destination | ログの宛先(今回は CloudWatch Logs のロググループ)を表す論理オブジェクト |
| delivery | source と destination を1対1でつなぐ |
イベントバスのログとして何が出るか
公式ドキュメントによると、イベントバスのログは次のようなイベントを対象に生成されます。
- バス上のルールに一致した AWS サービスのイベント
- PutEvents で送られたイベント、パートナーイベントソースからのイベント、アーカイブからリプレイされたイベント(ルールに一致したかどうかに関係なく対象)
PutEvents で送ったイベントは、ルールやターゲットが無くてもログの対象になります。今回の検証でルールやターゲットを作っていないのは、そのためです。
ログレベル
ログレベルは OFF(既定)、ERROR、INFO、TRACE の4段階で、上位のレベルは下位のレベルのステップを含みます。
| レベル | 出力される主なステップ |
|---|---|
| ERROR | 取り込み失敗、呼び出しの恒久失敗・リトライ可能な失敗・スロットリング、DLQ など、エラー系 |
| INFO | ERROR に加えて、Event Ingested、Rule Matched、No Rules Matched、Invocation Started / Succeeded など主要ステップ |
| TRACE | INFO に加えて、Event Received、Rule Matching Started、Invocation Attempt Started / Succeeded など全ステップ |
さらに include_detail で、イベント本体(event_detail)やターゲットへの入力などを含めるかを選べます。
配信はベストエフォート
公式ドキュメントには、イベントバスのログはベストエフォートで配信され、完全性やタイムリーさは保証されない、と書かれています。「ログが出ない」と思ったとき、設定ミスと配信遅延を見分ける必要があります。
何が分かりにくかったか
ここが今回の出発点です。調べた範囲の情報源ごとに、言っていることが少しずつ違いました。
| 情報源 | 書いてあること | 分からなかった点 |
|---|---|---|
| 公式ドキュメント(現在の英語版) |
events:AllowVendedLogDeliveryForResource を許可するアイデンティティベースポリシーを、ログ設定を行う IAM ユーザー/ロールに付ける |
配信パイプライン(delivery source など)の構成手順が、このページには無い |
| 公式ドキュメント(re:Post の質問者が引用していた文言) | 「イベントバスにこの権限を付与するポリシーを追加する」と読める書き方 | イベントバス側にポリシーを付けるのか、設定者に付けるのかが読み取りづらい |
| re:Post の質問(採用回答は質問者自身) |
PutPermission でこのアクションを付与しようとしても、ValidationException で失敗する。コンソールなら有効化できるが、それは操作者の権限で配信リソースが作られるから、という整理 |
aws:SourceArn の実値は出てこない |
| re:Post の AI 生成回答(専門家レビュー未実施) | イベントバスにリソースポリシーを付け、条件キーを加える案内 | 質問者自身が、役に立ったのはコンソールを開く手順だけで、残りは意味が通らないとコメントしている。aws:SourceArn の実値は無い |
| Terraform provider ベースのドキュメント(Pulumi Registry 経由) | 配信パイプライン3部品とロググループ側のリソースポリシーが必要リソース。サンプルの aws:SourceArn は delivery-source の ARN |
Pulumi のパッケージのバージョンは Terraform provider のものとは別体系で、検証に使った v6.44.0 での記述かどうかは未確認。HashiCorp 公式の Registry は読めていません |
(私が確認した時点の話で、公式ドキュメントの文言がいつ変わったのかは、私には確認できていません)
正直に言うと、ここまで読んで「結局、aws:SourceArn に何の ARN を入れて、どこにポリシーを付ければいいの?」となりました。そして Terraform 側のドキュメントを読んでようやく、配信パイプラインの存在に気づきます(遠回りでした)。
→ つまり、情報源ごとに「どのリソースに、どのポリシーを付けるか」の前提が違っていて、実際の値が載っているのは Terraform 側のサンプルだけでした。
何を確かめたか
事前調査をもとに、確かめたいことを優先順に5つ立てました。
| # | 確かめたいこと |
|---|---|
| 1 | ポリシーも配信パイプラインも無い状態で、ログは出力されるか |
| 2 | 設定者側のアイデンティティベースポリシー(events:AllowVendedLogDeliveryForResource)だけで出力されるか |
| 3 | リソースベースポリシーが要る場合、Condition 無しで出力されるか |
| 4 | Condition が必要なら、aws:SourceArn に入る実際の ARN 形式は何か |
| 5 | デフォルトイベントバスでも、同じ方法でログ出力できるか |
あわせて、「ロググループ名は /aws/vendedlogs/ 配下でないといけないのか」も追加で確認しました。
検証環境と構成
- リージョン:
ap-northeast-1 - Terraform v1.8.5 / Terraform AWS Provider v6.44.0(2026年10月8日に見た Terraform provider の公式リリース一覧では、v6.68.0 が最新として並んでいました)
- 検証用 AWS アカウントで実施
- 使用した IAM ロール:管理者権限ではなく、検証に必要な操作だけを許可した専用のポリシー(下記)。デフォルトバスの AWS CloudShell での確認も、同じロールで行いました
使用したロールのポリシーのうち、今回の論点に関わる部分を抜粋します(アカウント ID の部分は * のままです)。
{
"Sid": "EventBridgeVendedLogDelivery",
"Effect": "Allow",
"Action": ["events:AllowVendedLogDeliveryForResource"],
"Resource": [
"arn:aws:events:ap-northeast-1:*:event-bus/verify-vendedlog-bus",
"arn:aws:events:ap-northeast-1:*:event-bus/default"
]
}
{
"Sid": "CloudWatchLogsDeliveryManage",
"Effect": "Allow",
"Action": [
"logs:PutDeliverySource", "logs:GetDeliverySource", "logs:DeleteDeliverySource",
"logs:PutDeliveryDestination", "logs:GetDeliveryDestination", "logs:DeleteDeliveryDestination",
"logs:CreateDelivery", "logs:GetDelivery", "logs:DeleteDelivery"
],
"Resource": "*"
}
ほかに、イベントバスの作成・更新・削除、ロググループの管理、ロググループのリソースポリシー(logs:PutResourcePolicy など)、AWS CloudTrail の LookupEvents を許可しています。上の2つは、読みやすいよう配信関連のアクションを一部省いた抜粋です。
作成したリソースは次のとおりです(アカウント ID は <ACCOUNT_ID> に置換しています)。
| リソース | 値 |
|---|---|
| カスタムイベントバス | arn:aws:events:ap-northeast-1:<ACCOUNT_ID>:event-bus/verify-vendedlog-bus |
| ロググループ | /aws/vendedlogs/events/event-bus/verify-vendedlog-bus |
| delivery source | arn:aws:logs:ap-northeast-1:<ACCOUNT_ID>:delivery-source:verify-vendedlog-bus-src-INFO |
| delivery destination | arn:aws:logs:ap-northeast-1:<ACCOUNT_ID>:delivery-destination:verify-vendedlog-bus-dst-cwl |
| ロググループ側のリソースポリシー | AWSLogDeliveryWrite-verify-vendedlog-bus |
ほかに delivery(source と destination の紐付け)も作成しています。ルール、ターゲット、外部連携は作っていません。
切り分けのために、Terraform の変数で構成を出し入れできるようにしました。
| 変数 | 役割 |
|---|---|
log_level / include_detail
|
イベントバスの log_config
|
enable_log_delivery |
配信パイプライン(source / destination / delivery)を作るか |
enable_log_group_resource_policy |
ロググループ側のリソースポリシーを作るか |
enable_resource_policy_condition |
そのポリシーに Condition を付けるか |
source_arn_pattern |
aws:SourceArn に入れる値(delivery-source の ARN か、ロググループの ARN か) |
今回実際に apply したのは、既定値(配信あり・ポリシーあり・Condition あり・SourceArn は delivery-source の ARN)の構成です。
結果1:正しく動いた構成と aws:SourceArn
ロググループ側のリソースポリシーは、次の形です(デフォルトバスで CLI から付けたものを匿名化して載せます)。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowVendedLogDelivery",
"Effect": "Allow",
"Principal": { "Service": "delivery.logs.amazonaws.com" },
"Action": ["logs:CreateLogStream", "logs:PutLogEvents"],
"Resource": "arn:aws:logs:ap-northeast-1:<ACCOUNT_ID>:log-group:<ロググループ名>:log-stream:*",
"Condition": {
"StringEquals": { "aws:SourceAccount": "<ACCOUNT_ID>" },
"ArnLike": {
"aws:SourceArn": "arn:aws:logs:ap-northeast-1:<ACCOUNT_ID>:delivery-source:<delivery-source名>"
}
}
}
]
}
terraform output で確認した、ポリシーに実際に入った aws:SourceArn は次の値でした。
arn:aws:logs:ap-northeast-1:<ACCOUNT_ID>:delivery-source:verify-vendedlog-bus-src-INFO
aws:SourceArn は「ログの出どころ」を示す条件キーなので、入るのは宛先(ロググループ)ではなく、出どころ側である delivery source の ARN でした。
補足です。CLI の put-resource-policy で付けたこのポリシーは、返ってきた policyScope が ACCOUNT でした。「ロググループ側のポリシー」と呼んでいますが、実体としてはアカウントスコープのポリシーで、Resource でログストリームを絞っています。CLI リファレンスでは、--resource-arn にロググループの ARN を指定する方法も用意されていて、その場合はロググループ単位のポリシーになる、と読めます。今回は指定していないので、この点は試していません。
結果2:実際に出たログ
カスタムバスに PutEvents でイベントを4件投入しました(FailedEntryCount: 0)。60〜90秒ほどで、ロググループに次のログストリームができました。
-
EventBridgeEventBusLogs(ログ本体) -
log_stream_created_by_aws_to_validate_log_delivery_subscriptions(AWS が配信検証用に自動生成)
ログの中身は、匿名化すると次のとおりです。
{
"resource_arn": "arn:aws:events:ap-northeast-1:<ACCOUNT_ID>:event-bus/verify-vendedlog-bus",
"event_bus_name": "verify-vendedlog-bus",
"message_type": "EVENT_INGEST_SUCCESS",
"log_level": "INFO",
"details": {
"source": "verify.test",
"detail_type": "VerifyEvent",
"event_detail": "{\"msg\":\"hello\"}"
}
}
投入した4件すべてが EVENT_INGEST_SUCCESS として記録されました!
気づいた点を2つ。
- 待ち時間:事前には「初回は数分、最大5〜10分程度」を見込んでいましたが、実測は60〜90秒でした(1回の観測です。ベストエフォート配信なので、常にこの速さとは限りません)
-
ログレベル:バスの
log_configは TRACE にしましたが、delivery source のlog_typeはINFO_LOGSで作っています。出力されたレコードのlog_levelはINFOでした。TRACE 相当のステップが出るのかは、今回確認していません(未検証です)
結果3:デフォルトバスでも同じ方法で通った
デフォルトバスは Terraform で新規作成できない既存リソースなので、AWS CloudShell から CLI で確認しました。
# 1. デフォルトバスのログ設定
aws events update-event-bus --name default --log-config IncludeDetail=FULL,Level=TRACE
# 2. delivery source(デフォルトバスの ARN を指定)
aws logs put-delivery-source --name default-bus-src-INFO \
--log-type INFO_LOGS \
--resource-arn arn:aws:events:ap-northeast-1:<ACCOUNT_ID>:event-bus/default
あとは、ロググループ作成、リソースポリシー(aws:SourceArn は delivery source の ARN)、delivery destination、delivery の順に、カスタムバスと同じ手順です。
確認できたことは次のとおりです。
-
update-event-bus --log-configは、デフォルトバスにも適用できた(カスタムバス固有の機能ではなかった) -
put-delivery-sourceのresource-arnに、デフォルトバスの ARN(event-bus/default)を指定できた -
verify.testのイベント5件が、すべてEVENT_INGEST_SUCCESSで出力された(各イベントの直後に、ルール未設定を示すNO_STANDARD_RULES_MATCHEDも記録された)
注意点は、デフォルトバスには AWS サービス由来のスケジュールイベントなども流れてくることです。ログには、検証と関係のないレコードが混ざります。検証後は、ログ設定を Level=OFF に戻しました(デフォルトバス自体は削除しません)。
結果4:ロググループ名のプレフィックスは関係なかった
「/aws/vendedlogs/ 配下でないとダメなのか」も試しました。/verify-non-vendedlogs-prefix-01 というロググループで検証し、4件が EVENT_INGEST_SUCCESS で出力されました。今回の構成では、プレフィックスは必須ではありませんでした。
ただし、公式ドキュメントには別の観点があります。ログ配信のリソースポリシーには 51,200 バイトの上限があり、上限に達すると AWS が新しい許可を追加できなくなります。そのため、/aws/vendedlogs/* のようなプレフィックスをワイルドカードで許可して使う運用が案内されています。「必須ではないが、将来のために使う価値がある」というのが、私の今の理解です。
注意点・ハマりどころ
-
設定者側の権限は、管理者権限だと気づきにくい。 re:Post の質問者の整理によれば、コンソールでは操作者自身の権限で配信リソースが作られるので、管理者権限だと通ってしまいます。今回は管理者権限ではなく、
events:AllowVendedLogDeliveryForResourceを明示して許可した専用ロールで検証しました。ただし、この権限を外して試してはいません。そのため「必須である」とは言えず、「付けた状態で通った」までが確認できたことです -
公式の自動作成ポリシーは、アカウント単位のワイルドカード。 公式ドキュメントのロググループのリソースポリシー例では、
aws:SourceArnがarn:aws:logs:region:account:*の形です。設定者に必要な権限(logs:PutResourcePolicyなど)があれば、AWS がこのポリシーを自動で作る、とも書かれています。自分でポリシーを書いて個別の delivery source ARN に絞る場合は、この形との違いを意識してください - 待ち時間と配信の保証。 ベストエフォートなので、すぐ出なくても数分待ってから判断するのが安全です
- 料金。 公式ドキュメントによると、Amazon S3 や Amazon Data Firehose に配信する場合でも、Amazon CloudWatch の配信料金がかかります。今回は料金の検証はしていないので、詳細は公式の料金ページを確認してください
- 後片付けの順番。 公式ドキュメントでは、ログを出すリソースを削除した後に、配信リソースを自分で削除する必要があるとされています。順番は Delivery、DeliverySource の順で、DeliveryDestination はそのソース専用の場合に消します(Terraform 管理外で作ったものは手動で消す必要があります)
検証コードと再現方法(GitHub)
検証に使った Terraform と実行記録は、個人リポジトリ(poc-lab)の eventbridge-vended-log-verify ディレクトリに置いています。
何が入っているか
| ファイル | 内容 |
|---|---|
README.md |
検証の目的、前提条件、構成、検証手順(Step 1〜5)、AWS CloudTrail での調査手順、後片付け |
RESULTS.md |
検証結果と、確かめたいこと1〜5への回答 |
consolelog.md |
デフォルトバスの AWS CloudShell での実行記録 |
| Terraform 一式 | 切り分け用の変数は variables.tf にあります |
再現するには
検証用の AWS アカウントで、次の順に実行します。Terraform を実行するロールに必要な権限は、README.md の前提条件に一覧があります。
export AWS_PROFILE=<your-profile>
terraform init
terraform plan
terraform apply
terraform output
apply したら、PutEvents でイベントを送ります。<BUS_NAME> は terraform output の値に読み替えてください。
aws events put-events --region ap-northeast-1 --entries 'file://event.json'
[{"Source":"verify.test","DetailType":"VerifyEvent","Detail":"{\"msg\":\"hello\"}","EventBusName":"<BUS_NAME>"}]
ログは、ロググループにログストリームができてから確認します。
aws logs describe-log-streams --region ap-northeast-1 \
--log-group-name "<LOG_GROUP_NAME>" --order-by LastEventTime --descending
aws logs filter-log-events --region ap-northeast-1 \
--log-group-name "<LOG_GROUP_NAME>" --limit 20
今回は60〜90秒ほどで出ましたが、ベストエフォート配信なので、数分待ってから判断するのが安全です。
変数を切り替えて、Step ごとに切り分ける
構成は1つで、変数を切り替えて terraform apply を繰り返すと、Step を順に試せる作りにしています。既定値のまま apply すると、今回確認した構成(Step 4-b-1)になります。
| Step | 試すこと | 切り替える変数 | 今回の実施 |
|---|---|---|---|
| 1 | 配信もポリシーも無い状態 |
enable_log_delivery=false など |
未実施 |
| 2 | 設定者側のアイデンティティベースポリシーのみ | enable_log_group_resource_policy=false |
未実施 (@要確認) |
| 3 | 配信あり・ロググループ側ポリシー無し | enable_log_group_resource_policy=false |
未実施 (@要確認) |
| 4-a | ポリシーあり・Condition 無し | enable_resource_policy_condition=false |
未実施 |
| 4-b-1 |
aws:SourceArn が delivery source の ARN(既定値) |
source_arn_pattern="delivery_source" |
実施(出力成立) |
| 4-b-2 |
aws:SourceArn がロググループの ARN |
source_arn_pattern="log_group" |
未実施 |
| 5 | デフォルトバス(Terraform 管理外) | CLI で実施 | 実施(出力成立) |
「未実施」の Step は、本記事の未検証の範囲にそのまま対応しています。試した方は、結果が違ったらぜひ教えてください!
試すときの注意
-
検証用のアカウントで実施してください。 デフォルトバスは既存の共有リソースなので、
Level=OFFに戻すだけにして、削除はしません -
後片付けは
terraform destroy。 ただし、デフォルトバス向けに CLI で作った delivery source / destination / delivery、リソースポリシーは Terraform の管理外なので、手動で削除します(手順はREADME.mdとconsolelog.mdにあります) - ロググループの保持期間は1日にしています。料金は今回検証していないので、気になる方は公式の料金ページを確認してください
未検証の範囲
正直に、今回確認していないことを並べます。
- 配信パイプラインも許可も無い状態での挙動(確かめたいこと1):配信なし構成の apply は、今回していません
- 配信パイプラインはあるが、ロググループ側のリソースポリシーが無い状態での挙動:公式ドキュメントには、必要な権限があれば AWS がこのポリシーを自動で作る、という記述があります。ポリシー無しで通るのか、自分で付けるのが必須なのかは、今回は確認していません (@要確認)
- Condition 無しのポリシーで出力されるか(確かめたいこと3)
-
aws:SourceArnにロググループの ARN やアカウントワイルドカードを入れた場合の結果:ここは「delivery-source の ARN で通った」までで、「それ以外はダメ」とは確認していません。公式例がワイルドカードである以上、通る可能性は十分あると思っています -
設定者側の
events:AllowVendedLogDeliveryForResourceが必要かどうか:付けた状態で通ったことは確認しましたが、外した場合の挙動は未確認です -
INFO_LOGS以外のlogTypeでの配信:INFO_LOGSのみ使用しました。ERROR_LOGSや、TRACE に当たるものを個別に配信できるかは試していません - ほかのリージョン、ほかの配信先(Amazon S3 / Amazon Data Firehose)、クロスアカウント配信
おわりに
今回の検証で、迷いの原因は「配信パイプラインの存在が、権限の説明の手前で抜けていた」ことだと分かりました。権限の話だけを追いかけても、ポリシーを付ける場所は決まりません。
要点をまとめます。
- イベントバスの
log_configには宛先を指定する欄が無く、delivery source / destination / delivery の3部品で配信をつなぐ - 書き込み許可は宛先ロググループ側で、
aws:SourceArnに delivery source の ARN を入れた構成で出力された - イベントバス自身へのリソースベースポリシーは、無くても出力された
- デフォルトバスでも、同じ方法で出力された
同じところで止まった方は、まず delivery source / destination / delivery の3部品を組んで、そのうえで宛先ロググループ側の許可を見直してみてください。私が確認できたのは1つのケースだけですが、切り分けの順番は参考になれば嬉しいです。遠回りしましたが、実機で確かめられてよかったです!
検証用のコードと記録は個人リポジトリに置いてあるので、気になった方は覗いてみてください!
それでは!よいAWSライフを!
参考
- Configuring logs for Amazon EventBridge event buses
- Logs sent to CloudWatch Logs(CloudWatch Logs ユーザーガイド)
- Enable logging from AWS services(CloudWatch Logs ユーザーガイド)
- AWS CLI: update-event-bus
- AWS re:Post: How do I configure an event bus to allow vended log delivery?
- Pulumi Registry: aws.cloudwatch.EventBus(AWS Terraform Provider ベース)
- AWS CLI: logs put-resource-policy
ーーー
以下確認をお願いします
- 未実施 (@要確認)(記事本文、「検証コードと再現方法(GitHub)」の Step 2 と Step 3 の行)
・RESULTS に、Step 2(設定者側のアイデンティティベースポリシーのみ)と Step 3(配信あり・ロググループ側ポリシー無し)を実行した記録が無く、未実施と読み取りました。実施していたら、結果を教えてください。 - ポリシー無しで通るのか、自分で付けるのが必須なのかは、今回は確認していません (@要確認)(記事本文、「未検証の範囲」)
・Step 3 を未実施とした場合に書いた内容です。1と同じ確認です。
ーーー