この記事は公開されてから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 に修正してください。
lambda_function.py
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サイトをご覧ください。