EventBridge で注文イベントをルーティングする

AWSBeginner
オンラインで実践に進む

はじめに

出荷処理には新しく発注された注文が必要ですが、請求やキャンセルのイベントは別の場所で扱います。一致するイベントをキューへルーティングし、実際にどのメッセージが到着するかを確認します。

先に SQS でジョブを送信して消費する と リソースポリシーでバケットを保護する を完了してください。この独立した VM は、独自の CLI アクセスと参照データを提供します。以前のキューや認証情報は再利用しません。

認定試験との関連

このラボでは、次の試験トピックに関連する実践的な演習を行います。

バスと移動先キューを準備する

このステップでは、イベントが入る場所と、一致する作業がコンシューマーを待つ場所を、独立して作成します。

Terminal の隣で AWS View を使い、CLI クエリをこのラボの実際のリソースと結果と比較します。提供された参照データを保持してください。

Amazon EventBridge は、発生したことを表すイベントをルーティングします。バスはイベントを受け取り、ルールはフィールドを照合し、ターゲットは一致するイベントを受け取ります。カスタムバスは、このアプリケーションのイベントをデフォルトバスから分離します。SQS キューは、コンシューマーが処理するまで配信を保持します。プロジェクトディレクトリから始めます。シェルの代入は、CLI が返した識別子を保存します。--query は必要なフィールドを選択し、--output text は次のコマンドで使える形式にします。

cd /home/labex/project
BUS_NAME=labex-ev01-bus
RULE_NAME=labex-ev01-orders
aws events create-event-bus --name "$BUS_NAME"
QUEUE_URL=$(aws sqs create-queue \
  --queue-name labex-ev01-jobs \
  --query QueueUrl \
  --output text)
QUEUE_ARN=$(aws sqs get-queue-attributes \
  --queue-url "$QUEUE_URL" \
  --attribute-names QueueArn \
  --query Attributes.QueueArn \
  --output text)

バスのレスポンスには ARN が含まれ、QUEUE_URL はメッセージ操作の対象キューを識別します。キュー ARN は、ターゲットや権限ポリシー内でキューを識別します。これらの識別子の用途は異なります。

両方の空のリソースを確認します。

aws events list-rules --event-bus-name "$BUS_NAME"
aws sqs get-queue-attributes \
  --queue-url "$QUEUE_URL" \
  --attribute-names ApproximateNumberOfMessages ApproximateNumberOfMessagesNotVisible

ルールはまだなく、キューには利用可能なメッセージも処理中のメッセージもありません。AWS View には、カスタムバスと空のキューが表示されます。準備の検証を実行してください。

注文を照合して 1 つのルールを認可する

このステップでは、照合ルールをキューに接続し、そのルールの配信だけを認可します。

プロデューサー、バス、ルール、キュー

照合ルールがイベントを選択し、キューの送信元ルールへの権限付与が、別途その配信を許可します。

イベントパターンは、イベントフィールドに対するフィルターです。source はプロデューサーを指定し、detail-type はイベントのカテゴリを指定します。以下の各配列は、受け入れる値を列挙します。ヒアドキュメントは、JSON マーカーの間の JSON をそのまま書き込みます。マーカーを引用符で囲むことで、シェル展開を防ぎます。file:// は CLI にそのファイルを読み取るよう指示します。

cat > order-pattern.json <<'JSON'
{"source":["labex.orders"],"detail-type":["OrderPlaced"]}
JSON
RULE_ARN=$(aws events put-rule \
  --name "$RULE_NAME" \
  --event-bus-name "$BUS_NAME" \
  --event-pattern file://order-pattern.json \
  --state ENABLED \
  --query RuleArn \
  --output text)

ルールは有効ですが、一致だけでは配信は認可されません。キューのリソースポリシーは、EventBridge サービスによる送信を許可し、aws:SourceArn でこのルールに限定する必要があります。通常の JSON ポリシーを書き込みます。シェルは、自分のキュー ARN とルール ARN を挿入します。

cat > queue-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com"
      },
      "Action": "sqs:SendMessage",
      "Resource": "$QUEUE_ARN",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "$RULE_ARN"
        }
      }
    }
  ]
}
EOF
jq -n --rawfile policy queue-policy.json '{Policy:$policy}' > queue-attributes.json
aws sqs set-queue-attributes \
  --queue-url "$QUEUE_URL" \
  --attributes file://queue-attributes.json

属性 API はポリシーを JSON 文字列として保存するため、--rawfile がそのドキュメントを Policy 属性に読み込みます。権限付与の対象は、1 つのキューと 1 つの送信元ルールです。

ターゲットは、ルールの移動先です。その ID を使って、後でこの接続を更新または削除できます。

cat > targets.json <<EOF
[
  {
    "Id": "order-queue",
    "Arn": "$QUEUE_ARN"
  }
]
EOF
aws events put-targets \
  --rule "$RULE_NAME" \
  --event-bus-name "$BUS_NAME" \
  --targets file://targets.json
aws events describe-rule --name "$RULE_NAME" --event-bus-name "$BUS_NAME"
aws events list-targets-by-rule --rule "$RULE_NAME" --event-bus-name "$BUS_NAME"

ターゲット設定の FailedEntryCount は 0、取得したルールには意図するパターンがあり、ターゲット ARN は自分のキューと一致します。AWS View には、ルールとその移動先キューが表示されます。配信するイベントはまだありません。接続の検証を実行してください。

照合と配信の境界を確認する

このステップでは、一致するイベントと無関係なイベントを発行し、その後、新しいキューメッセージを追加せずに送信元権限の失敗をテストします。

EventBridge イベントには、ルーティングフィールドと detail ペイロードがあります。PutEvents API は、JSON エンコードされた文字列として Detail を受け付けます。発注された注文、請求イベント、キャンセルの 3 つの読みやすいエントリを書き込みます。jq は、各 Detail オブジェクトを API が要求する文字列に変換します。

cat > event-inputs.json <<EOF
[
  {
    "EventBusName": "$BUS_NAME",
    "Source": "labex.orders",
    "DetailType": "OrderPlaced",
    "Detail": {
      "id": "route-order",
      "quantity": 2
    }
  },
  {
    "EventBusName": "$BUS_NAME",
    "Source": "labex.billing",
    "DetailType": "OrderPlaced",
    "Detail": {
      "id": "billing-event",
      "quantity": 9
    }
  },
  {
    "EventBusName": "$BUS_NAME",
    "Source": "labex.orders",
    "DetailType": "OrderCancelled",
    "Detail": {
      "id": "cancelled-event",
      "quantity": 1
    }
  }
]
EOF
jq 'map(.Detail |= tojson)' event-inputs.json > events.json
aws events put-events --entries file://events.json
aws sqs get-queue-attributes \
  --queue-url "$QUEUE_URL" \
  --attribute-names ApproximateNumberOfMessages ApproximateNumberOfMessagesNotVisible

発行レスポンスは、失敗エントリ 0 件と、受け付けた各エントリのイベント ID を報告します。両方のフィールドに一致するのは route-order だけなので、キューには利用可能なメッセージが 1 件含まれます。AWS View は、source、detail type、account、region、detail を含む完全なイベントエンベロープを表示します。

コンシューマーが実際に受け取る本文を読み取ります。通常の受信は、可視性タイムアウトの間メッセージを非表示にします。--visibility-timeout 0 は、この確認後すぐに再び見えるようにします。クエリは ID と本文だけを表示し、レシートハンドルを表示しません。この確認は、業務処理の完了や、メッセージの処理済み確認ではありません。

fromjson は、SQS メッセージ ID を保持しながら、各 JSON 本文を読みやすくします。変更されるのは表示出力だけです。

aws sqs receive-message \
  --queue-url "$QUEUE_URL" \
  --max-number-of-messages 10 \
  --visibility-timeout 0 \
  --output json | jq '[.Messages[] | {MessageId, Body: (.Body | fromjson)}]'

本文の detail.id は route-order、detail.quantity は 2 です。請求とキャンセルのエントリは、このキューに到達しませんでした。

以下の例は、有効な照合ルール、そのキューターゲット、アカウントとリージョンを含む実際の完全な注文イベントを示します。

AWS View に移動先キューの一致する注文イベントが表示される

次に、ルールとターゲットを有効なまま保持し、キューポリシーを別の送信元 ARN に変更します。

jq --arg wrong "${RULE_ARN}-other" '.Statement[0].Condition.ArnEquals["aws:SourceArn"]=$wrong' queue-policy.json > wrong-source-policy.json
jq -n --rawfile policy wrong-source-policy.json '{Policy:$policy}' > wrong-source-attributes.json
aws sqs set-queue-attributes \
  --queue-url "$QUEUE_URL" \
  --attributes file://wrong-source-attributes.json
cat > event-inputs.json <<EOF
[
  {
    "EventBusName": "$BUS_NAME",
    "Source": "labex.orders",
    "DetailType": "OrderPlaced",
    "Detail": {
      "id": "denied-order",
      "quantity": 4
    }
  }
]
EOF
jq 'map(.Detail |= tojson)' event-inputs.json > denied-event.json
aws events put-events --entries file://denied-event.json
aws sqs get-queue-attributes \
  --queue-url "$QUEUE_URL" \
  --attribute-names ApproximateNumberOfMessages ApproximateNumberOfMessagesNotVisible

EventBridge はこのイベントを受け付けますが、ルールには必要なキュー権限付与がありません。元のメッセージだけがキューに残り、denied-order は存在しません。パイプラインを診断するときは、イベントの受け付けとターゲットへの配信を区別してください。この演習は配信の再試行を扱いません。

意図する権限付与を復元し、もう一度確認します。

aws sqs set-queue-attributes \
  --queue-url "$QUEUE_URL" \
  --attributes file://queue-attributes.json
aws sqs receive-message \
  --queue-url "$QUEUE_URL" \
  --max-number-of-messages 10 \
  --visibility-timeout 0 \
  --output json | jq '[.Messages[] | {MessageId, Body: (.Body | fromjson)}]'

元の route-order だけが存在します。修正されたポリシーは、今後の配信を認可します。このラボは、以前に拒否されたイベントが再試行されることには依存しません。ルーティングの検証を実行してください。

イベントパイプラインを削除する

このステップでは、無関係なリソースを保持しながら、自分のターゲット、ルール、カスタムバス、使い捨てキューを削除します。

ルールを削除する前に、ターゲットを削除します。その後、カスタムバスとキューを削除します。キューの削除は、ルーティング確認のために保持された合成イベントを破棄します。そのイベントについて業務結果を生成したとは主張していません。

aws events remove-targets \
  --rule "$RULE_NAME" \
  --event-bus-name "$BUS_NAME" \
  --ids order-queue
aws events delete-rule --name "$RULE_NAME" --event-bus-name "$BUS_NAME"
aws events delete-event-bus --name "$BUS_NAME"
aws sqs delete-queue --queue-url "$QUEUE_URL"

成功した読み取り専用クエリで、残るものを確認します。

aws events list-event-buses
aws events list-rules --event-bus-name default
aws sqs list-queues
aws dynamodb scan --table-name labex-ev01-reference --query Items

デフォルトバスだけが残り、そのルール一覧は空で、キュー URL は存在せず、参照アイテムには keep unchanged があります。認証エラーやネットワークエラーは削除の証拠になりません。AWS View には、空のカスタムリソース一覧と保持された参照リソースが表示されます。

作成した通常のファイルを削除します。

rm -f event-inputs.json order-pattern.json queue-policy.json queue-attributes.json targets.json events.json wrong-source-policy.json wrong-source-attributes.json denied-event.json

VM を終了する前に、後片付けの検証を実行してください。

まとめ

カスタム EventBridge バスを作成し、発注イベントを照合して、正確な送信元ルールへの権限付与でキューターゲットを接続しました。実際のキュー本文で、どのイベントがコンシューマーへ到達したかを確認し、送信元拒否のテストで、イベントの受け付けと配信を区別しました。デフォルトバスと参照データを保持しながら、所有リソースを削除しました。

次のユニットでは、イベントエンベロープを、キューコンシューマーが必要とする小さなペイロードへ変換します。