API Gateway+Lambdaでsnsのunsuscribe linkを無効化する
===
[TOC]
## Lambda関数の作成
API Gateway経由でブラウザのurlから入力されたパラメータをパースしてunsubscribe無効化コマンドを実行
エラーハンドリングとレスポンス本文どこまでこだわるか
###
関数名:ConfirmSubscription
```python=
import boto3
import json
import logging
import re
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
# TODO implement
logger.info(json.dumps(event))
url = event['queryStringParameters']['url']
m = re.match(r'https://sns\.(.*?)\..*TopicArn=(.*)', url)
if m is None:
logger.info('url parameter is wrong. please copy and paste "Confirm subscription" Link URL.')
region = m.group(1)
topicarn = m.group(2)
token = event['queryStringParameters']['Token']
sns = boto3.client('sns', region_name=region)
r = sns.confirm_subscription(
TopicArn=topicarn,
Token=token,
AuthenticateOnUnsubscribe='true'
)
return {
'statusCode': 200,
'body': json.dumps(r)
}
```
## API Gatewayの作成
### 初期構築
#### API作成
- 「APIの作成」>「リソース」>「アクション」>「リソースの作成」
API名:DisableUnsubscribingSNSTopic
API名:ConfirmSubscription
API名:ExecLambda
⇒apiをたたく時のパスを作成
/sns/confirm-subscription?url=
- 「APIの作成」>「リソース」>「アクション」>「メソッドの作成」
⇒apiをたたいた時の処理内容を作成
- GETを選択
⇒ブラウザのURLバーからのリクエストを想定しているため
- メソッドリクエスト
統合タイプ:Lambda関数
Lambdaプロキシ統合の使用:チェックボックスにチェック
Lambdaリージョン:ap-northeast-1
Lambda関数:DisableUnsubscribingSNSTopic
デフォルトタイムアウトの使用:チェックボックスにチェック
リクエストの検証⇒クエリ文字列パラメータおよびヘッダーの検証
URLクエリ文字列パラメータ⇒名前:url、必須:チェックボックスにチェック
⇒GETパラメータ(?url="unsubscribeリンク")がないとエラーにする
ARNに表示されるrest-api-id(=lbq0kv0d85)をメモ
ARN: arn:aws:execute-api:ap-northeast-1:305017457084:lbq0kv0d85/*/GET/sns
- リソースポリシー作成
リクエスト元IP制限を定義
```json=
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:ap-northeast-1:"awsaccoundid":"rest-api-id"/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": ["111.89.79.227/32", "XXXX"]
}
}
}
]
}
```
- APIデプロイ
「APIの作成」>「リソース」>「アクション」>「APIのデプロイ」
デプロイされるステージ:新しいステージ
ステージ名:stage
ステージの説明:sgate
デプロイメントの説明:自由に
**※リソースの設定変更やリソースポリシー等の変更を行ったあと、このデプロイをしないと反映されないため注意!!!!!!!!!!!!**
- ステージ作成(必要に応じて)
商用環境:
prod
stage
⇒stageはAPI変更時の試験用
検証環境:
dev
⇒後段のlambdaがsnsのapiをたたく時に商用と検証それぞれ分けないといけないから、検証環境用にdevを作成しておく
※API(メソッドリクエストのAPIデプロイ)
#### 試験
- メソッドの動作確認
「リソース」>「GET」>「クライアント」のテストを押下
クエリ文字列:url=https://aaa?Topic=cccc&Token=bbbb&Endpoinst=dddd
を入力して「テスト」を押下する
⇒Lambda関数にリクエストがいくことを確認
- APIの動作確認
snsトピックを作成し、認証リンクを右クリック>コピー
任意のブラウザのURLバーで以下を入力
```
https://"rest-api-id".execute-api.ap-northeast-1.amazonaws.com/"stage"/sns/confirm-subscription?url="認証リンク"
```
⇒正常応答が返ってくることを確認
※APIの呼び出しURLは「ステージ」エディターの上部に記載されている
- エラー応答原因例
{"Message":"User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:*:lbq0kv0d85/v3/GET/sns with an explicit deny"}
⇒ポリシーのIP制限でdenyされている
{"message":"Missing Authentication Token"}
⇒URLが間違っている(ステージング名のあとにAPIリソース名をいれたらダメ)
⇒APIのデプロイができていない
※リソースポリシー修正後にデプロイした?
※APIに対して想定外のアクセスが来たときは大体このメッセージになる。クライアント証明書を使ってないからとかは関係ない
https://qiita.com/akatsukaha/items/08b524e20f7cc5cd8f2d
{"message": "Internal server error"}
⇒lambda関数で500エラー、confirm済みのtopicに対してリクエスト投げた時とか
### 維持
#### おれおれhtmlで簡易動作確認ページ作成
```htmlmixed=
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>takaishi tool v0</title>
</head>
<body>
<h1>検証環境用</h1>
<h2>sns email topicの認証&unsubscribeリンクの無効化</h2>
<form action="https://lbq0kv0d85.execute-api.ap-northeast-1.amazonaws.com/v1/sns" method="get">
<p>SNS Topinのsubscribeリンクをコピー&ペーストしてください<br>
<input type="text" name="url"></p>
<button>認証</button>
</form>
<h2>コンテンツ出し分け動作確認</h2>
<form action="https://dddd" method="POST">
<button>曜日別出し分け機能</button> <button>セグメント別出し分け機能</button>
<p>セグメント別出し分け機能</p>
</form>
<h1>商用環境</h1>
</body>
</html>
```