
Amazon SNS でプライベートエンドポイントに メッセージを送信してみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
アノテーション株式会社の hato です。
Amazon SNS から HTTP または HTTPS エンドポイントに送信されるメッセージは、パブリック IP アドレスが送信元となるため、プライベートエンドポイント(プライベートサブネット内のエンドポイント)にメッセージを送信したい場合は、 Lambda 関数などを経由する必要があります。
Lambda 関数を利用する方法は AWS ナレッジセンターにて公開されていますが、実際に構築したことはなかったのと、お問い合わせ頂いた際に備えて画面キャプチャを取得するため、やってみました。
なお、プライベートサブネット内から Amazon SNS にメッセージを送信する方法は次のブログとなります。
やってみた
前提
- SNS トピックは作成済
- メッセージ受信用にプライベートサブネットに EC2 を作成、受信アプリ配置済み
構成イメージ

手順
- セキュリティグループの作成
- IAM ロールの作成
- Lambda 関数のコード作成
- Lambda 関数の作成
- SNS トピックの作成
- テスト
セキュリティグループの作成
Lambda 関数に設定するセキュリティグループを作成します。
Amazon VPC コンソール のナビゲーションペインから「セキュリティグループ」を選択して、「セキュリティグループを作成」を選択します。

次の値を指定して「セキュリティグループを作成」を選択します。
- セキュリティグループ名:任意の名前(例:
LambdaSG) - VPC:プライベートエンドポイントの VPC

セキュリティグループが正常に作成されたことを確認します。

IAM ロールの作成
Lambda に設定する IAM ロールを作成します。
VPC に接続する Lambda は通常の Lambda 関数の権限に加えて、追加の権限が必要となります。
今回は必要な権限をまとめた AWS 管理ポリシーAWSLambdaVPCAccessExecutionRoleを使用します。
IAM コンソール を開き、ロールから「ロールを作成」をクリックします。

信頼されたエンティティタイプに「AWS のサービス」、ユースケースに「Lambda」を選択して、「次へ」をクリックします。

許可ポリシーからAWSLambdaVPCAccessExecutionRoleを選択して、「次へ」をクリックします。

ロール名に任意の名前(例:lambda_vpc_basic_execution)を指定して、「ロールを作成」をクリックします。

IAM ロールが正常に作成されたことを確認します。

Lambda 関数のコード作成
Amazon SNS をトリガーに Lambda 関数が実行された場合に、プライベートエンドポイントにリクエストを送信するサンプルコードを作成します。
作業用のディレクトリを作成します。
$ mkdir my-sourcecode-function $ cd my-sourcecode-function
エディタで次のサンプルコードを作成します。
※5行目はプライベートエンドポイントの URL に修正してください。
import json
import requests
def lambda_handler(event, context):
url = "<PRIVATE_HTTP/S_ENDPOINT_URL>"
sns_message_payload = event["Records"][0]["Sns"]
sns_message_headers = {
"x-amz-sns-message-id": sns_message_payload['MessageId'],
"x-amz-sns-message-type": sns_message_payload["Type"],
"x-amz-sns-subscription-arn" : event["Records"][0]["EventSubscriptionArn"],
"x-amz-sns-topic-arn" : sns_message_payload["TopicArn"]
}
try:
r = requests.post(url = url, data = json.dumps(sns_message_payload), headers = sns_message_headers)
except Exceptions as e:
print(e)
print(r.content)
return {
'statusCode': 200,
'body': json.dumps(r.content)
}
pipで周辺モジュールをインストールして、ZIP圧縮します。
$ pip install --target ./package requests ...(中略)... Successfully installed certifi-2022.12.7 charset-normalizer-2.1.1 idna-3.4 requests-2.28.1 urllib3-1.26.13 $ cd package $ zip -r ../my-deployment-package.zip . ...(中略)... adding: urllib3/poolmanager.py (deflated 71%) adding: urllib3/_collections.py (deflated 69%) $ cd .. $ zip -g my-deployment-package.zip lambda_function.py adding: lambda_function.py (deflated 75%)
Lambda 関数の作成
プライベートエンドポイントにリクエストを送信する Lambda 関数を作成します。
Lambda コンソールを開き、関数から「関数の作成」をクリックします。

次の値を指定し、「▼詳細設定」を選択します。
- 関数名:任意の名前(例:
Private-endpoint-Amazon-SNS-topic-subscription) - ランタイム:Python 3.8
- デフォルトの実行ロールの変更:
既存のロールを使用する- 作成した IAM ロールを指定(例:
lambda_vpc_basic_execution)
- 作成した IAM ロールを指定(例:

次の値を指定して「関数の作成」を選択します。
- VPC を有効化:有効
- VPC:プライベートエンドポイントの VPC
- サブネット:プライベートサブネットを指定
- セキュリティグループ:作成したセキュリティグループを指定(例:
LambdaSG)

Lambda 関数の作成中は設定変更ができないためしばらく待ちます。

Lambda 関数が正常に作成されたことを確認します。

作成したサンプルコードを設定します。 「アップロード元」から「.zipファイル」を選択

手順3で作成したサンプルコード(ZIP)を選択します。

コード変更の警告です。「OK」を選択します。

次の手順で必要になるため Lambda 関数の ARN をメモします。

エンドポイントのサブスクライブ
Amazon SNS コンソール のナビゲーションペインから「サブスクリプションの作成」を選択します。

次の値を指定して「サブスクリプションの作成」を選択します。
- トピック ARN:関連付けを行う SNS トピックを選択
- プロトコル:
AWS Lambda - エンドポイント:Lambda 関数の ARN を指定

サブスクリプションが正常に作成されたことを確認します。

メッセージの通知確認
「メッセージの発行」を選択します。

テストメッセージを入力して「メッセージの発行」を選択します。

エンドポイントにメッセージが配信されました。
{
"Type": "Notification",
"MessageId" : "22b80b92-fdea-4c2c-8f9d-bdfb0c7bf324",
"TopicArn" : "arn:aws:sns:ap-northeast-1:123456789012:hato-sns-topic",
"Subject": "hato-test-title",
"Message": "hato-test-Message",
"Timestamp" : "2012-05-02T00:54:06.655Z",
"SignatureVersion": "1",
"Signature" : "EXAMPLEw6JRN...",
"SigningCertURL" : "https://sns.ap-northeast-1.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem",
"UnsubscribeURL" : "https://sns.ap-northeast-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:ap-northeast-1:123456789012:hato-sns-topic:d6a4f408-4021-4e66-82e3-920cb71bb5fe"
"MessageAttributes": {}
}
最後に
この記事が誰かのお役にたてば幸いです。
参考資料
- プライベートエンドポイントを Amazon SNS トピックにサブスクライブする
- Amazon SNS の IP アドレス範囲を取得する
- Deploy Python Lambda functions with .zip file archives - AWS Lambda
- 同じアカウントで Lambda 関数を Amazon SNS のトピックにサブスクライブする
アノテーション株式会社について
アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。






