SNS トピックには同じエンドポイントを持つ SNS サブスクリプションを複数関連づけられない

属性の切り替え作業のため、同一エンドポイントに対する SNS サブスクリプションを複数持ちたいことがありました。残念ながら仕様上できないようでした。

コンバンハ、千葉(幸)です。

SNS トピックには複数の SNS サブスクリプションを関連づけられます。

SNS サブスクリプションはプロトコル、エンドポイントといったパラメータを持ちます。例えば SNS トピックを通じた Eメール配信を行いたければ、プロトコルに「Eメール」、エンドポイントに送信先メールアドレスを設定します。

ここで、同じ SNS トピックに同じエンドポイントを持つ SNS サブスクリプションを複数関連づけたいことがありました。

sns topic mutipule sns subscriptions

結果から言うとこの構成は実現できませんでした。試した内容をまとめておきます。

なぜ同じエンドポイントを持つ SNS サブスクリプションを複数設定したいのか

先に、なぜやりたかったのかを説明しておきます。「SNS サブスクリプションの空白期間を設けずConfirmationWasAuthenticated属性を変更したかったから」です。

SNS サブスクリプションにはConfirmationWasAuthenticatedという属性があり、true / false のいずれかを持ちます。これは SNS サブスクリプションの確認(初回登録)が認証有りで行われたかどうかを表す属性であり、これが false の場合、IAM 認証なしでサブスクリプション解除できてしまう状態です。

以下エントリのように「いつの間にかサブスクリプションが削除されていた」という事態になりかねません。

既存の SNS サブスクリプションのConfirmationWasAuthenticated属性が false であったため、これを true に切り替えたいと考えました。

SNS サブスクリプション属性の変更はできないため、既存のサブスクリプションの削除→新規サブスクリプションの作成というステップを踏む必要があります。

ここで、サブスクリプションが存在しない期間をなるべく設けたくなく、以下のプロセスで実現できないか考えました。

  • 新規の SNS サブスクリプション(true)を追加する
  • 既存の SNS サブスクリプション(false)を削除する

sns topic mutipule sns subscriptions 2

このプロセスを踏む場合、同じエンドポイントを持つサブスクリプションが一時的に同居することになります。が、冒頭で述べた通り、これは実現できません。

SNS トピックに重複するエンドポイントを持つ SNS サブスクリプションを追加してみる

同じエンドポイントを複数設定できるのか?について AWS ドキュメント上ではそれらしき記述が確認できなかったので、実際に手を動かして確認してみます。

作業前の状態は以下です。

SNS_topic_test_topic

SNS トピックtest-topicに、ひとつのサブスクリプションが関連づいています。プロトコルは Eメールで、エンドポイントはchiba.yukihiro@example.comです。(実際のアドレスではなく例示用のものです。)

サブスクリプションに払い出された ID はfa87649c-2fe6-47e0-937a-a4e4830330b3です。

この状態からさらにサブスクリプションを追加してみます。画像内の「サブスクリプションの作成」を押下し作成画面に遷移し、以下のように設定します。

Sns_subscription_create

正常に作成が完了したように表示されました。

SNS_New_subscription

しかし、払い出された ID を確認すると既存のものと同じfa87649c-2fe6-47e0-937a-a4e4830330b3です。ステータスもすでに「確認済み」となっています。

SNS トピックの画面に戻って確認しても、新規の SNS サブスクリプションは確認できません。

SNS_topic_sus_subscriptions

ちなみに、Confirm 用のメールは改めて送信されています。特にこれは意味を持ちません。メール内の Confirm 用のリンクを押下しても特にステータスは変わりません。

AWS_Notification_-_Subscription_Confirmation_-_mail

AWS CLI でも確認してみる

マネジメントコンソール上での操作だけでなく、AWS CLI でも確認してみます。aws sns subscribeコマンドを使用します。

# 変数の格納
TOPIC_ARN=arn:aws:sns:ap-northeast-1:000000000000:test-topic
ENDPOINT=chiba.yukihiro@example.com

# コマンドの実行
% aws sns subscribe \
    --topic-arn $TOPIC_ARN \
    --protocol email \
    --notification-endpoint $ENDPOINT
{
    "SubscriptionArn": "pending confirmation"
}

pending confirmationという出力が返ってきましたが、「保留中の確認」ステータスのサブスクリプションが作成されたわけではありません。

マネジメントコンソールと同じ以下の状態です。

  • Confirm 用のメールは届く
  • メール内の Confirm 用リンクを押下した際に確認できるサブスクリプション ID はfa87649c-2fe6-47e0-937a-a4e4830330b3(既存のものと同じ)
  • 新規のサブスクリプションは確認できない

操作の手法によらず、同じエンドポイントを持つ SNS サブスクリプションを単一トピックに同居させられないことがわかりました。

ConfirmationWasAuthenticated 属性を切り替えたい際にどうしたらいいのか

冒頭で述べた「SNS サブスクリプションの空白期間を設けずConfirmationWasAuthenticated属性を変更」は実現できないことが分かりました。

代替策としては以下のあたりがあるでしょう。

  • 既存 SNS サブスクリプションの削除→新規 SNS サブスクリプションの作成をなるべく間を置かずに実施する
  • 別のエンドポイントの SNS サブスクリプションを一時的に追加し、「削除→新規」の作業中の通知をそちらで受ける
    • Webメールによってはエイリアス機能を持つものがあるのでそちらの活用もあり

新規の SNS トピックを作成してそちらに切り替える、という手法もありますが、手間が大きい気もします。許容できる空白期間と作業ボリュームを鑑みて、よき案を採用してください。

終わりに

SNS トピックに同じエンドポイントを持つ SNS サブスクリプションを複数関連づけられない、という話でした。

試してみた挙動からすると、SNS トピックとプロトコル・エンドポイントの組み合わせごとに一意の ID が払い出され、複数回「作成」や「Subscribe」を実行しても別物として扱われない、ということだと捉えました。

今回のような背景がない限り「複数持ちたい」というケースはあまり無いと思いますが、参考になれば幸いです。

以上、 チバユキ (@batchicchi) がお送りしました。

参考