S3イベント通知とは、バケットにオブジェクトが作成・削除されたときに、その内容をSQS・SNS・Lambda・EventBridgeへ自動で知らせる仕組みです。 設定は aws s3api put-bucket-notification-configuration にJSONを1つ渡すだけですが、宛先ごとにJSONのキー名が違い、宛先側にも「S3からの書き込みを許可する」ポリシーが必要です。

この記事では、宛先別のJSONと対になるポリシーJSONをコピペできる形でそろえ、設定の確認、既存設定を残したまま追加する手順、届いたメッセージの取り出し方までを順に示します。

確認環境:Ubuntu 24.04 / AWS CLI 1.46.1 / Python 3.11 / boto3 1.43。AWS の API をローカルで再現するツール(moto 5.2.3)で実行しました。掲載するコマンドは、実際の AWS でそのまま使える形(接続先の指定なし)で書いています。宛先の権限チェックなど AWS 側でだけ起きる動きは、AWS 公式ドキュメントの記載にもとづいて説明します。

S3イベント通知の早見表

宛先 JSONのキー ARNを書くキー 宛先側に必要な許可 フィルター
SQS(標準キュー) QueueConfigurations QueueArn キューポリシーで sqs:SendMessage prefix / suffix
SNS(標準トピック) TopicConfigurations TopicArn トピックポリシーで sns:Publish prefix / suffix
Lambda LambdaFunctionConfigurations LambdaFunctionArn 関数のリソースポリシーで lambda:InvokeFunction prefix / suffix
EventBridge EventBridgeConfiguration なし(空の {}) バケット側の設定のみ EventBridge のルール側で絞る
やりたいこと コマンド
設定する(全体を置き換える) aws s3api put-bucket-notification-configuration --bucket バケット名 --notification-configuration file://設定.json
いまの設定を見る aws s3api get-bucket-notification-configuration --bucket バケット名
通知をすべて止める --notification-configuration '{}' を put する
既存の設定に追加する get → JSONを編集 → put(後述)

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「S3イベント通知の設定|CLIのJSON例とSQS・SNS・Lambda連携」

全体の流れ

flowchart LR
  A[オブジェクトの作成・削除] --> B[S3バケットの通知設定]
  B -->|イベント種別とフィルターが一致| C{宛先}
  C --> D[SQSキュー]
  C --> E[SNSトピック]
  C --> F[Lambda関数]
  B -->|EventBridgeを有効化| G[EventBridgeのルール]

設定の順番は 「宛先を作る → 宛先側のポリシーでS3を許可する → バケットに通知設定を put する」 です。put のときに S3 は宛先の存在と権限を確かめるため、ポリシーを先に用意しておくと一度で通ります。

以降の例で使う名前は次のとおりです。

種類 名前
バケット demo-upload-bucket
SQSキュー s3-event-queue
SNSトピック s3-event-topic
Lambda関数 s3-event-handler
リージョン / アカウントID ap-northeast-1 / 123456789012
aws s3api create-bucket --bucket demo-upload-bucket \
  --create-bucket-configuration LocationConstraint=ap-northeast-1
aws sqs create-queue --queue-name s3-event-queue
aws sns create-topic --name s3-event-topic
{
    "Location": "/demo-upload-bucket"
}
{
    "TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:s3-event-topic"
}

キューのARNは次のコマンドで調べます。

QUEUE_URL=$(aws sqs get-queue-url --queue-name s3-event-queue --query QueueUrl --output text)
aws sqs get-queue-attributes --queue-url "$QUEUE_URL" --attribute-names QueueArn
{
    "Attributes": {
        "QueueArn": "arn:aws:sqs:ap-northeast-1:123456789012:s3-event-queue"
    }
}

SQSへ通知する(JSONとキューポリシー)

1. キューポリシーでS3を許可する

queue-policy.json として保存します。Principal は s3.amazonaws.com、Condition で送信元のバケットとアカウントを絞る形です。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3SendMessage",
      "Effect": "Allow",
      "Principal": {"Service": "s3.amazonaws.com"},
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:ap-northeast-1:123456789012:s3-event-queue",
      "Condition": {
        "ArnLike": {"aws:SourceArn": "arn:aws:s3:::demo-upload-bucket"},
        "StringEquals": {"aws:SourceAccount": "123456789012"}
      }
    }
  ]
}

set-queue-attributes の Policy は「JSONを文字列にしたもの」を値に取ります。手で引用符をエスケープする代わりに、Pythonで変換用のファイルを作ると確実です。

# attr.py
import json

p = json.load(open("queue-policy.json"))
json.dump({"Policy": json.dumps(p)}, open("queue-attr.json", "w"))
python3 attr.py
aws sqs set-queue-attributes --queue-url "$QUEUE_URL" --attributes file://queue-attr.json
aws sqs get-queue-attributes --queue-url "$QUEUE_URL" --attribute-names Policy
{
    "Attributes": {
        "Policy": "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Sid\": \"AllowS3SendMessage\", \"Effect\": \"Allow\", \"Principal\": {\"Service\": \"s3.amazonaws.com\"}, \"Action\": \"sqs:SendMessage\", …(省略)…}]}"
    }
}

2. 通知設定のJSON(prefix / suffix フィルターつき)

sqs.json として保存します。images/ で始まり .jpg で終わるキーが作成されたときだけ通知します。

{
  "QueueConfigurations": [
    {
      "Id": "images-to-sqs",
      "QueueArn": "arn:aws:sqs:ap-northeast-1:123456789012:s3-event-queue",
      "Events": ["s3:ObjectCreated:*"],
      "Filter": {
        "Key": {
          "FilterRules": [
            {"Name": "prefix", "Value": "images/"},
            {"Name": "suffix", "Value": ".jpg"}
          ]
        }
      }
    }
  ]
}
aws s3api put-bucket-notification-configuration \
  --bucket demo-upload-bucket --notification-configuration file://sqs.json
aws s3api get-bucket-notification-configuration --bucket demo-upload-bucket

put は成功時に何も表示しません。get の結果で確かめます。

{
    "QueueConfigurations": [
        {
            "Id": "images-to-sqs",
            "QueueArn": "arn:aws:sqs:ap-northeast-1:123456789012:s3-event-queue",
            "Events": [
                "s3:ObjectCreated:*"
            ],
            "Filter": {
                "Key": {
                    "FilterRules": [
                        {
                            "Name": "prefix",
                            "Value": "images/"
                        },
                        {
                            "Name": "suffix",
                            "Value": ".jpg"
                        }
                    ]
                }
            }
        }
    ]
}

Id は省略できますが、付けておくと届いたメッセージの configurationId でどの設定から来たかを見分けられ、後述の「get → 編集 → put」でも目印になります。

SNSへ通知する(JSONとトピックポリシー)

topic-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3Publish",
      "Effect": "Allow",
      "Principal": {"Service": "s3.amazonaws.com"},
      "Action": "sns:Publish",
      "Resource": "arn:aws:sns:ap-northeast-1:123456789012:s3-event-topic",
      "Condition": {
        "ArnLike": {"aws:SourceArn": "arn:aws:s3:::demo-upload-bucket"},
        "StringEquals": {"aws:SourceAccount": "123456789012"}
      }
    }
  ]
}

SNS はポリシーのファイルをそのまま渡せます。

aws sns set-topic-attributes \
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:s3-event-topic \
  --attribute-name Policy --attribute-value file://topic-policy.json

sns.json:logs/ 配下の「PUTでの作成」と「削除」を通知します。

{
  "TopicConfigurations": [
    {
      "Id": "logs-to-sns",
      "TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:s3-event-topic",
      "Events": ["s3:ObjectCreated:Put", "s3:ObjectRemoved:*"],
      "Filter": {"Key": {"FilterRules": [{"Name": "prefix", "Value": "logs/"}]}}
    }
  ]
}

SNSを挟むと、1つのイベントを複数のキューや関数へ配れます。宛先を後から増やす予定があるときに向いています。

Lambdaへ通知する(JSONと関数の許可)

Lambda は、関数のリソースポリシーに「S3からの呼び出しを許可する」ステートメントを add-permission で足します。

aws lambda add-permission \
  --function-name s3-event-handler \
  --statement-id s3-invoke \
  --action lambda:InvokeFunction \
  --principal s3.amazonaws.com \
  --source-arn arn:aws:s3:::demo-upload-bucket \
  --source-account 123456789012
{
    "Statement": "{\"Action\": \"lambda:InvokeFunction\", \"Principal\": {\"Service\": \"s3.amazonaws.com\"}, \"Effect\": \"Allow\", \"Resource\": \"arn:aws:lambda:ap-northeast-1:123456789012:function:s3-event-handler\", \"Sid\": \"s3-invoke\", \"Condition\": {\"ArnLike\": {\"AWS:SourceArn\": \"arn:aws:s3:::demo-upload-bucket\"}, \"StringEquals\": {\"AWS:SourceAccount\": \"123456789012\"}}}"
}

lambda.json:import/ 配下の .csv が作成されたら関数を呼びます。

{
  "LambdaFunctionConfigurations": [
    {
      "Id": "csv-to-lambda",
      "LambdaFunctionArn": "arn:aws:lambda:ap-northeast-1:123456789012:function:s3-event-handler",
      "Events": ["s3:ObjectCreated:*"],
      "Filter": {
        "Key": {
          "FilterRules": [
            {"Name": "prefix", "Value": "import/"},
            {"Name": "suffix", "Value": ".csv"}
          ]
        }
      }
    }
  ]
}

受け取る側のハンドラーは次の形です。

# handler.py
import json
from urllib.parse import unquote_plus

def lambda_handler(event, context):
    for r in event["Records"]:
        bucket = r["s3"]["bucket"]["name"]
        key = unquote_plus(r["s3"]["object"]["key"])
        print(r["eventName"], bucket, key)
    return {"count": len(event["Records"])}

SQSで受け取ったイベントを event として、この関数を手元のPythonで直接呼んだ結果です。

ObjectCreated:Put demo-upload-bucket images/cat.jpg
{'count': 1}

関数が同じバケットへ書き戻す構成では、prefix を分けて通知が繰り返し起きないようにします(入力は import/、出力は done/ など)。AWS公式ドキュメントも、同じバケットへ書き込むトリガーは呼び出しが循環しうると注意しています。

EventBridgeへ送る(JSON)

EventBridge はキーを1つ置くだけです。

{
  "EventBridgeConfiguration": {}
}
aws s3api put-bucket-notification-configuration \
  --bucket demo-upload-bucket --notification-configuration file://eb.json

AWS公式ドキュメントによると、EventBridge を有効にするとイベント種別を選ぶ必要はなく、対象のイベントがすべて EventBridge に送られ、絞り込みと振り分けは EventBridge のルール側で行います。有効化から反映までは5分ほどかかると案内されています。FIFOのキューやトピックへ流したいときも、EventBridge 経由にします(S3イベント通知の直接の宛先は、SQS・SNSとも標準タイプのみ)。

複数の宛先を1つのJSONにまとめる

1つのバケットに持てる通知設定は1つだけで、その中に宛先を並べます。

{
  "QueueConfigurations": [
    {
      "Id": "images-to-sqs",
      "QueueArn": "arn:aws:sqs:ap-northeast-1:123456789012:s3-event-queue",
      "Events": ["s3:ObjectCreated:*"],
      "Filter": {"Key": {"FilterRules": [
        {"Name": "prefix", "Value": "images/"},
        {"Name": "suffix", "Value": ".jpg"}
      ]}}
    }
  ],
  "TopicConfigurations": [
    {
      "Id": "logs-to-sns",
      "TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:s3-event-topic",
      "Events": ["s3:ObjectCreated:Put", "s3:ObjectRemoved:*"],
      "Filter": {"Key": {"FilterRules": [{"Name": "prefix", "Value": "logs/"}]}}
    }
  ],
  "EventBridgeConfiguration": {}
}

put は全体の置き換え:get → 編集 → put の手順

put-bucket-notification-configuration は「追加」ではなく「全体の置き換え」です。 AWSのAPIリファレンスにも「既存の通知設定を、リクエストに含めた設定で置き換える」と書かれています。

Lambda 向けの設定が入っているバケットに、sqs.json だけを put してみます。

aws s3api put-bucket-notification-configuration \
  --bucket demo-upload-bucket --notification-configuration file://lambda.json
aws s3api put-bucket-notification-configuration \
  --bucket demo-upload-bucket --notification-configuration file://sqs.json
aws s3api get-bucket-notification-configuration \
  --bucket demo-upload-bucket --query 'keys(@)'
[
    "QueueConfigurations"
]

LambdaFunctionConfigurations がなくなり、SQS の設定だけが残りました。既存の設定を残したまま足すには、次の3ステップにします。

# 1) いまの設定を保存(これがバックアップにもなる)
aws s3api get-bucket-notification-configuration --bucket demo-upload-bucket > current.json

# 2) 足したい設定(ここでは sns.json)を合成
python3 merge.py

# 3) 合成した全体を put
aws s3api put-bucket-notification-configuration \
  --bucket demo-upload-bucket --notification-configuration file://merged.json
# merge.py
import json

cur = json.load(open("current.json"))          # いまの設定(getの結果)
add = json.load(open("sns.json"))              # 足したい設定

for kind, items in add.items():
    ids = {c["Id"] for c in items}
    kept = [c for c in cur.get(kind, []) if c.get("Id") not in ids]
    cur[kind] = kept + items                   # 同じIdは入れ替え、ほかは残す

cur.pop("ResponseMetadata", None)
json.dump(cur, open("merged.json", "w"), indent=2)
print({k: [c["Id"] for c in v] for k, v in cur.items() if isinstance(v, list)})
{'QueueConfigurations': ['images-to-sqs'], 'TopicConfigurations': ['logs-to-sns']}

put 後に確認すると、両方が入っています。

aws s3api get-bucket-notification-configuration --bucket demo-upload-bucket \
  --query '{Queue:QueueConfigurations[].Id,Topic:TopicConfigurations[].Id}'
{
    "Queue": [
        "images-to-sqs"
    ],
    "Topic": [
        "logs-to-sns"
    ]
}

通知が1つも設定されていないバケットでは、get は何も表示しません。その場合は current.json が空になるので、{} を書いてから合成します。通知をすべて止めたいときは --notification-configuration '{}' を put します。

イベント種別の一覧

Events に書ける主な値です(AWS公式ドキュメントのイベント種別一覧より)。

イベント種別 通知されるタイミング
s3:ObjectCreated:* 作成すべて(Put・Post・Copy・マルチパート完了)
s3:ObjectCreated:Put PUT での作成
s3:ObjectCreated:Post POST(フォームからのアップロード)での作成
s3:ObjectCreated:Copy コピーでの作成
s3:ObjectCreated:CompleteMultipartUpload マルチパートアップロードの完了
s3:ObjectRemoved:* 削除すべて
s3:ObjectRemoved:Delete 削除(バージョンを指定した完全な削除を含む)
s3:ObjectRemoved:DeleteMarkerCreated バージョニング有効時の削除マーカー作成
s3:ObjectRestore:* 復元に関するすべて
s3:ObjectRestore:Post 復元の開始
s3:ObjectRestore:Completed 復元の完了
s3:ObjectRestore:Delete 復元したコピーの期限切れ
s3:LifecycleExpiration:* ライフサイクルによる期限切れすべて
s3:LifecycleExpiration:Delete ライフサイクルによる削除
s3:LifecycleExpiration:DeleteMarkerCreated ライフサイクルによる削除マーカー作成
s3:LifecycleTransition ライフサイクルによるストレージクラスの移行
s3:IntelligentTiering Intelligent-Tiering でアーカイブ層へ移動
s3:ObjectTagging:* タグ操作すべて
s3:ObjectTagging:Put タグの追加・更新
s3:ObjectTagging:Delete タグの削除
s3:ObjectAcl:Put オブジェクトACLの設定・変更
s3:Replication:* レプリケーションに関するすべて(メトリクスまたはRTCの有効化が前提)
s3:ReducedRedundancyLostObject 低冗長化ストレージのオブジェクト消失の検知
s3:TestEvent 通知を設定したときにS3が送るテストメッセージ(Events には書かない)

覚えておくと役立つ点が3つあります。

  • マルチパートアップロードで作られたオブジェクトは、s3:ObjectCreated:Put ではなく CompleteMultipartUpload で届きます。 作成を漏れなく拾うなら s3:ObjectCreated:* を選びます。
  • s3:ObjectRemoved:* は、ライフサイクルによる自動削除を含みません。 そちらは s3:LifecycleExpiration:* を使います。
  • 通知は「少なくとも1回」届き、順番は保証されません。同じイベントが重ねて届いても結果が変わらない処理にしておくと安心です。

prefix / suffix フィルターの決まり

決まり 内容
書ける条件 prefix(前方一致)と suffix(後方一致)。ワイルドカード(*)は使えない
対象 オブジェクトのキー全体(images/2026/cat.jpg など)
空白を含む値 空白は + に置き換えて書く。そのほかの特殊文字はURLエンコードして書く
重なり 同じイベント種別で、フィルターが重なる設定を2つ置くと保存時にエラーになる
重なってよい場合 イベント種別が違う、または prefix が重なっても suffix が重ならない

フィルターが効いているかを、4つのファイルをアップロードして確かめます(images-to-sqs は images/ かつ .jpg)。

aws s3 cp a.jpg s3://demo-upload-bucket/images/cat.jpg
aws s3 cp a.jpg s3://demo-upload-bucket/images/memo.txt
aws s3 cp a.jpg "s3://demo-upload-bucket/images/夏 2026.jpg"
aws s3 cp a.jpg s3://demo-upload-bucket/other/dog.jpg

次の節の read_direct.py でキューを読んだ結果は2件でした。memo.txt(suffix が不一致)と other/dog.jpg(prefix が不一致)は届いていません。

ObjectCreated:Put demo-upload-bucket images/cat.jpg 2
ObjectCreated:Put demo-upload-bucket images/夏 2026.jpg 2

届くメッセージの中身と取り出し方

メッセージの構造

S3が送る本文はJSONで、Records 配列の中にイベントが入ります。AWS公式ドキュメントに載っている構造から、よく使うキーを抜き出すと次のとおりです。

{
  "Records": [
    {
      "eventVersion": "2.x",
      "eventSource": "aws:s3",
      "awsRegion": "リージョン",
      "eventTime": "処理が終わった時刻(ISO-8601)",
      "eventName": "イベント種別(例:ObjectCreated:Put)",
      "userIdentity": {"principalId": "操作した利用者のID"},
      "requestParameters": {"sourceIPAddress": "リクエスト元のIPアドレス"},
      "responseElements": {"x-amz-request-id": "…", "x-amz-id-2": "…"},
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "通知設定の Id",
        "bucket": {"name": "バケット名", "arn": "バケットのARN"},
        "object": {
          "key": "オブジェクトのキー(URLエンコード済み)",
          "size": "バイト数(数値)",
          "eTag": "ETag",
          "versionId": "バージョンID(バージョニング有効時)",
          "sequencer": "同じキーのイベントの前後を比べるための16進文字列"
        }
      }
    }
  ]
}
キー 使いどころ
eventName s3: を除いた形で入る(ObjectCreated:Put)。作成か削除かの分岐に使う
s3.configurationId 通知設定の Id。どの設定から届いたかを見分ける
s3.object.key URLエンコードされている。空白は + になるため unquote_plus で戻す
s3.object.sequencer 同じキーに対するイベントの順序を比べる。大きいほうが後

SQSで直接受け取る場合

receive-message の結果を保存して読みます。

aws sqs receive-message --queue-url "$QUEUE_URL" --max-number-of-messages 10 > recv.json
python3 read_direct.py
# read_direct.py
import json
from urllib.parse import unquote_plus

messages = json.load(open("recv.json")).get("Messages", [])
for m in messages:
    body = json.loads(m["Body"])               # 1回の json.loads で S3 イベントになる
    if body.get("Event") == "s3:TestEvent":    # 設定直後に届くテストメッセージは読み飛ばす
        print("test event")
        continue
    for r in body["Records"]:
        key = unquote_plus(r["s3"]["object"]["key"])
        print(r["eventName"], r["s3"]["bucket"]["name"], key, r["s3"]["object"]["size"])
ObjectCreated:Put demo-upload-bucket images/cat.jpg 2
ObjectCreated:Put demo-upload-bucket images/夏 2026.jpg 2

通知を設定した直後には、S3 からテストメッセージが1通届きます。こちらは Records を持たない形なので、上のコードのように先に見分けます(AWS公式ドキュメントの例)。

{
   "Service":"Amazon S3",
   "Event":"s3:TestEvent",
   "Time":"2014-10-13T15:57:02.089Z",
   "Bucket":"amzn-s3-demo-bucket",
   "RequestId":"5582815E1AEA5ADF",
   "HostId":"8cLeGAmw098X5cv4Zkwcmo8vvZa3eH3eKxsPzbB9wrR+YstdA6Knx4Ip8EXAMPLE"
}

SNS経由でSQSに届く場合

トピックにキューを購読させ、logs/ にファイルを置いて消します。

aws sqs create-queue --queue-name sns-fanout-queue
aws sns subscribe \
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:s3-event-topic \
  --protocol sqs \
  --notification-endpoint arn:aws:sqs:ap-northeast-1:123456789012:sns-fanout-queue
aws s3 cp a.jpg s3://demo-upload-bucket/logs/app.log
aws s3 rm s3://demo-upload-bucket/logs/app.log

SNS経由では、S3のイベントが SNSの封筒(Type・TopicArn・Message など)に包まれ、Message に文字列として入ります。 受信した本文は次の形でした。

{
  "Message": "{\"Records\": [{\"eventVersion\": \"2.1\", \"eventSource\": \"aws:s3\", …(省略)…}]}",
  "MessageId": "725afd42-a141-4909-a9c5-a74b4710bec9",
  "Timestamp": "2026-10-05T06:34:28.648Z",
  "TopicArn": "arn:aws:sns:ap-northeast-1:123456789012:s3-event-topic",
  "Type": "Notification",
  …(署名などのキーは省略)…
}

そのため、取り出しは json.loads を2回に分けます。

# read_sns.py
import json
from urllib.parse import unquote_plus

messages = json.load(open("recv_sns.json")).get("Messages", [])
for m in messages:
    envelope = json.loads(m["Body"])           # 1回目:SNS の封筒
    body = json.loads(envelope["Message"])     # 2回目:中の S3 イベント
    if body.get("Event") == "s3:TestEvent":
        print("test event")
        continue
    for r in body["Records"]:
        key = unquote_plus(r["s3"]["object"]["key"])
        print(envelope["Type"], r["eventName"], key)
Notification ObjectCreated:Put logs/app.log
Notification ObjectRemoved:Delete logs/app.log
受け取り方 json.loads の回数 S3イベントの場所
SQSで直接 1回 Body
SNS → SQS 2回 Body の中の Message
Lambdaで直接 0回(辞書で渡される) event["Records"]

エラーと対処

Unable to validate the following destination configurations

AWSのAPIリファレンスによると、put を受け取った S3 は、SNS・SQS の宛先が存在するか、発行する権限があるかをテスト通知を送って確かめます。 この確認が通らないと put 全体が取り消され、設定は1つも保存されません。そのときのメッセージが次の文です(AWS ナレッジセンターの記載)。

Unable to validate the following destination configurations

ナレッジセンターが挙げている原因と、対になる直し方です。

原因 直し方
宛先のリソースポリシーが S3 を許可していない この記事のキューポリシー / トピックポリシー / add-permission を先に設定する
宛先がすでに存在しない(削除済みのキューや関数が設定に残っている) get した設定から、その宛先の設定を取り除いて put する
宛先が KMS で暗号化されていて、キーポリシーが S3 を許可していない カスタマー管理キーのキーポリシーで s3.amazonaws.com に kms:GenerateDataKey と kms:Decrypt を許可する(AWS管理キーは対象外)
バケットに通知を設定したあとで、宛先のポリシーを書き換えた ポリシーを直してから、通知設定を put し直す

「get → 編集 → put」で設定を足すときにも、以前からある宛先のどれか1つが無効になっていると、全体がこのエラーで止まります。 足した設定に心当たりがないときは、既存の宛先を1つずつ確かめます。

JSONの形が違うとき(AWS CLIが送信前に知らせる)

キー名の s が抜けた例です。

aws s3api put-bucket-notification-configuration --bucket demo-upload-bucket \
  --notification-configuration '{"QueueConfiguration":[]}'
Parameter validation failed:
Unknown parameter in NotificationConfiguration: "QueueConfiguration", must be one of: TopicConfigurations, QueueConfigurations, LambdaFunctionConfigurations, EventBridgeConfiguration

Events を書き忘れた例です。

Parameter validation failed:
Missing required parameter in NotificationConfiguration.QueueConfigurations[0]: "Events"

そのほかの確認ポイント

症状 見るところ
NoSuchBucket バケット名とリージョン
put は通ったのに通知が届かない get で表示される prefix・suffix・イベント種別と、実際のキーや操作を見比べる
マルチパートでアップロードしたものだけ届かない s3:ObjectCreated:Put だけを指定していないか(s3:ObjectCreated:* にする)
キー名が文字化けして見える unquote_plus でURLデコードする
設定を足したら以前の通知が止まった put が全体の置き換えになっていないか。get の結果から合成し直す

よくある質問

Q. 1つのバケットに通知はいくつ設定できますか? A. 通知設定そのものはバケットに1つで、その中に QueueConfigurations などの配列として複数の設定を並べます。同じイベント種別でフィルターが重なる設定は置けないので、prefix か suffix で分けます。

Q. 同じイベントを複数の宛先に送れますか? A. 1つの設定に書ける宛先は1つです。複数へ配りたいときは、SNSトピックに送って購読先を増やすか、EventBridge を有効にしてルールで振り分けます。

Q. FIFOキューに直接送れますか? A. S3イベント通知の直接の宛先は標準キュー・標準トピックです。FIFOへ流したいときは EventBridge を経由します。

Q. 設定を元に戻したいときは? A. put の前に get-bucket-notification-configuration の結果をファイルに保存しておけば、そのファイルを put するだけで戻せます。

まとめ

  • 設定は put-bucket-notification-configuration にJSONを1つ渡す。 キーは宛先別に QueueConfigurations・TopicConfigurations・LambdaFunctionConfigurations・EventBridgeConfiguration。
  • 宛先側の許可を先に用意する。 SQSはキューポリシー、SNSはトピックポリシー、Lambdaは add-permission。Principal は s3.amazonaws.com。
  • put は全体の置き換え。 追加するときは get → 編集 → put。get の結果はバックアップにもなる。
  • フィルターは prefix と suffix。 作成を漏れなく拾うなら s3:ObjectCreated:*。
  • Unable to validate the following destination configurations は、宛先の存在・ポリシー・KMS を順に確かめる。
  • 取り出し方は経路で変わる。 SQS直接は json.loads 1回、SNS経由は2回。キーは unquote_plus で戻す。

参考・出典

  • AWS公式ドキュメント「Amazon S3 Event Notifications」各ページ(Event notification types and destinations / Configuring event notifications using object key name filtering / Granting permissions to publish event notification messages to a destination / Event message structure / Using EventBridge / Enabling Amazon EventBridge)
  • Amazon S3 API Reference「PutBucketNotificationConfiguration」
  • AWS ナレッジセンター「Unable to validate the following destination configurations」の解決方法

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「S3イベント通知の設定|CLIのJSON例とSQS・SNS・Lambda連携」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?