目次
鈴木です。久しぶりの投稿です。AWS SNSから別のSNSにメッセージを転送してみた記録です。
なぜ?
なぜそんな変なことをしたかったのかというと、AWS Backupの失敗通知を実現したかったからです。
2021/06/01追記:Backupの失敗通知については本記事の方法よりもシンプルな方法がありました。 → AWS Backupのジョブ失敗をメール通知する
AWS Backupの失敗通知は、以下の公式ドキュメントで解説されています。

上記ドキュメントでは、AWS Backupからの通知をSNSで受け取り、サブスクリプションのフィルターポリシーで、Backup成功を除外するよう案内されています。
これに従えばSNSからSNSへの送信なんて不要ですが、以下の状況で困りました。
- AWS Backup以外にもすでにさまざまな監視通知先として利用しているSNSトピックが存在する
- そのトピックには多くのメールアドレスがサブスクリプションとして登録済みで、通知先管理はそのトピックに集約したい
- 送信先メールアドレスは今後も追加・削除がありえる
AWS Backup以外の通知がフィルターポリシーに引っかかってしまったら困るうえ、すべてのサブスクリプションにフィルターポリシーを設定するのも運用上つらいです。

そこで、AWS Backup通知専用のSNSトピックを作成し、そこからAWS Backup用フィルターポリシーを経て、既存のSNSトピックに転送すればよいと考えました。フィルターポリシーの設定は1か所だけで済むうえに、AWS Backup以外には適用されません。メールアドレスの管理も既存のトピックだけで済みます。
AWS SNSのサブスクリプションは、現在以下が選択できます。
- Kinesis Data Firehose
- SQS
- Lambda
- Email-JSON
- HTTP
- HTTPS
- Platform application endpoint
- SMS
この中にはSNSは含まれません。しかしLambdaがあります。Lambdaに転送すればなんでもできちゃいます。今回の要件では、難しいことはせずに、ただ別のSNSにメッセージを転送するだけのLambdaを用意すればよいです。

SNSからSNSへの転送の設定手順
0. 前提
- 転送元と転送先のSNSトピックは作成済みとします。
- 転送先のSNSトピックには、メールアドレスなどのサブスクリプションが登録済みとします。
1. Lambda作成
SNSからSNSにそのまま転送するだけのLambdaを作成します。言語はなんでもよいのですが、今回はPythonで書きました。
コードの中で、転送先となるSNSトピックのARNを指定しています。
importboto3 def lambda_handler(event, context): try: # 転送元SNSからのメッセージを取得 message = event["Records"][0]["Sns"]["Message"] except: print("Invoked from anything but SNS") return client = boto3.client('sns') client.publish( TopicArn = "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:TOPIC2_NAME", # 転送先SNSトピック Message = message )2. 転送元SNSトピックの設定
転送元となるSNSトピックのサブスクリプションとして、さきほど作成したLambdaを設定します。

試してみる
以下のように、転送元SNSトピックにメッセージを送信してみると、転送先SNSトピックに登録済みのメールアドレスにメールが送信されるのが確認できます。これは公式ドキュメントの通りです
$ aws sns publish --topic-arn arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:TOPIC1_NAME --message "hello, world! from awscli"AWS Backup用フィルターポリシー設定
AWS Backup失敗通知にこの仕組みを利用したいのならば、1つ目のSNSトピックのサブスクリプションに、フィルターポリシーとして以下を設定します。
{ "State": [ { "anything-but": "COMPLETED" } ]}あとがき
AWS Backup失敗通知の方法があまりスマートでないなと思ったのが、本記事のきっかけです。
しかし、AWS各種サービスからの受信専用SNSトピックと、人への送信専用SNSトピックとを分けて、間にLambdaを置くという構成は、AWS Backup以外にも応用範囲があるかもしれません。たとえば以下の条件がそろっている状況です。
- Redshift、RDS、EC2インスタンスなどの死活監視をしている
- 一部インスタンスは毎日夜間停止している
- 毎日夜のアラートにより、アラートがオオカミ少年と化している
こんな場合は、Pythonコードで、時間と対象インスタンスを判定して、必要なアラートだけ転送するという方法が考えられます。インスタンスの判定が手間掛かりそうですけども、いつか試してみようと思います。
以上。