<style>
.reveal div.head{
background-color:#fcf8e3;
position: absolute;
text-align: left;
font-size: 50%;
}
.reveal div.red{
color: red;
}
.reveal div.font50{
font-size: 50%;
text-align: left;
}
.reveal div.font75{
font-size: 75%;
text-align: left;
}
.left{
text-align: left;
}
.reveal section img{
border:0px;
box-shadow:none;
}
</style>
## AWS SAA対策<br>ハンズオン
:::warning
S3/SNS/Lambdaでサーバレスに作る
ファイルダウンロードURL発行処理
:::
2019.08.19 ©System Shared
t-kawa
---
### 目的・ゴール
* AWS認定ソリューションアーキテクトアソシエイト試験の対策
* 一つ一つのサービスだけでなく、組み合わせて使ってみる(今回はS3/Lambda/SNS)
* サーバレスってどんなものかちょっとだけでも知って欲しい
* やっぱり自分で触った方が覚えるよね
* AWSのことを今より少しでも好きになって欲しい
---
### 概要、作るもの
:::info
S3にファイルアップロードすると
そのファイルのダウンロードURLが
メール or SMS or Slack に通知される仕組みを構築
:::
---
<div class="head">概要、作るもの</div>
どんな時に使うの?
* 大容量のファイルを渡したい時を想定
* メールだと大きなサイズのファイルをそのまま送れない。GSも容量制限がある。
* 特定の人だけにファイルを渡したい。誰でもいつでもダウンロードできてしまうのはセキュリティ的にもよろしくない。
---
<div class="head">概要、作るもの</div>
こんな感じ

---
<div class="head">概要、作るもの</div>
詳しめにはこんな感じ

---
### 事前準備
---
<div class="head">事前準備</div>
<br>
1. Slackアカウント作成
2. アップロード用画像ダウンロード
---
<div class="head">事前準備</div>
#### Slackアカウント作成
<div class="left">
- 事前に本ハンズオン用のワークスペースを用意しています。
- [ここ](https://join.slack.com/t/sssawshandson20190819/shared_invite/enQtNzI0OTMxMjQxNTI3LTUyY2EwYTc1YTQxZDM2NjA3NjE4ZTJiY2RlMWZhOWFlMjZjOTEwOGMxNDRkZDVkMjVmNzI4YjRmNzA3NDRkOTc) にアクセスして自分のアカウントを作成してください。
- サインインしたら、オーナー権限を渡します。
※本ワークスペースはハンズオン終了後に削除予定です。
</div>
---
<div class="head">事前準備</div>
#### アップロード用画像ダウンロード
<div class="left">
- Slackの#generalに配置してある画像ファイルをダウンロードしてください。
- アップロード用のファイルなので、デスクトップ等に置いておいてください。
※大容量ファイルをアップロードすると費用がかかってしまうので、本ハンズオンでは画像ファイルで行います。
</div>
---
#### 🙇♂️(追記)お詫びと訂正🙇♂️
:::danger
<div class="left">
本ハンズオンではファイルをダウンロードするURLを**SMS**にも送信するようになっていますが、
URLは1000文字程度の長さとなるので、そもそも**SMS**に向いてませんでした。
※**SMS**は文字数制限があるので遅れない場合がある。
なので**SMS**と記載されている部分は読み飛ばしてください。
資料は直しません。~~めんどくさいので。~~
</div>
:::
---
### どこから作るか

---
### Amazon SNS -> Email

---
### Amazon SNS
---
<div class="head">Amazon SNS</div>
#### SNSとは
Simple Notification Serviceの略
<iframe src="//www.slideshare.net/slideshow/embed_code/key/ASHAKSlShWtFpx?startSlide=7" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe>
---
<div class="head">Amazon SNS</div>
##### SNSからメールを送ってみる
:::success
:bulb: まずはマネジメントコンソール上でSNSからメールを送ってみましょう。
:::
---
<div class="head">Amazon SNS</div>
SNSトピックの作成
<div class="font75">
1. AWSへログイン 「SNS」で検索
</div>

---
<div class="head">Amazon SNS</div>
SNSトピックの作成
<div class="font75">
2. 「トピックの作成」をクリック
3. 「S3PreSignedURLTOPIC」を入力
4. 画面下の「トピックの作成」をクリック
</div>

---
<div class="head">Amazon SNS</div>
サブスクリプションの作成
<div class="font75">
1. トピックが作成されたら「サブスクリプションの作成」をクリック
</div>

---
<div class="head">Amazon SNS</div>
サブスクリプションの作成
<div class="font75">
2. ARNはそのまま
3. プロトコルに「Eメール」を指定、エンドポイントに自分のメールアドレスを入力
4. 画面下の「サブスクリプションの作成」をクリック
</div>

---
<div class="head">Amazon SNS</div>
サブスクリプションの作成
<div class="font75">
5. 入力したメールアドレス宛にメールが来ているので、「Confirm subscription」をクリック
</div>

---
<div class="head">Amazon SNS</div>
サブスクリプションの作成
<div class="font75">
6. Subscription confirmed!が表示され、マネジメントコンソール上のステータスが「確認済み」となる。
</div>

---
<div class="head">Amazon SNS</div>
通知の発行テスト
:::success
:bulb: Eメールを通知するサブスクリプションが作成できたので、先ほど作成したトピックにパブリッシュ(メッセージの発行)を行ってみましょう。
:::
---
<div class="head">Amazon SNS</div>
通知の発行テスト
<div class="font75">
1. 先ほど作成したトピックを開き、「メッセージの発行」をクリック
</div>

---
<div class="head">Amazon SNS</div>
通知の発行テスト
<div class="font75">
2. 件名、本文を適当に入力して画面下の「メッセージの発行」をクリック
</div>

---
<div class="head">Amazon SNS</div>
通知の発行テスト
<div class="font75">
3. メールが届く。
※本文下のURLを開くと購読が解除される
</div>

---
<div class="head">Amazon SNS</div>
##### SNSからSMSを送ってみる
:::success
:bulb: 同様にSMSのサブスクリプションも作ってみましょう。
:::

---
<div class="head">Amazon SNS</div>
画面を見つつやってみましょう。
先ほど作成したトピックに新たにSMSのサブスクリプションを追加する形です。
:::danger
なお電話番号は
080 => 8180
090 => 8190
となるので注意してください。
:::
---
### Lambda -> SNS

---
### AWS Lambda
---
<div class="head">Lambda -> SNS</div>
#### AWS Lambdaとは
<iframe src="//www.slideshare.net/slideshow/embed_code/key/9xZFhWF1JBVU5N?startSlide=19" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe>
---
<div class="head">Lambda -> SNS</div>
#### LambdaからSNSへ<br>メッセージを発行してみる
:::success
:bulb: とりあえずLambda関数を作ってみましょう。
:::
* 言語はPython 3.7を使用
---
<div class="head">Lambda -> SNS</div>
関数の作成
<div class="font75">
1. マネジメントコンソールから「lambda」で検索
</div>

---
<div class="head">Lambda -> SNS</div>
関数の作成
<div class="font75">
2. 「関数の作成」をクリック
3. 関数名に「SNSPublishFunction」、ランタイムに「Python3.7」を選択。
4. 画面下の「関数の作成」をクリック
</div>

---
<div class="head">Lambda -> SNS</div>
関数の起動テスト
:::success
:bulb: ひとまず関数が作成で来たので、そのまま何も変えずに動かしてみましょう。
:::
---
<div class="head">Lambda -> SNS</div>
関数の起動テスト
<div class="font75">
1. 画面右上の「テスト」をクリック
2. 「イベント名」を適当に入力して「作成」をクリック
</div>

---
<div class="head">Lambda -> SNS</div>
関数の起動テスト
<div class="font75">
3. 作成したテストを選択し、画面右上の「テスト」を再度クリックすると関数が実行される。
4. 実行結果:「成功」と表示
</div>

---
<div class="head">Lambda -> SNS</div>
関数を変えてみる
:::success
:bulb: 現在記載されている関数はデフォルトのままなので、少しいじってみましょう。
:::
---
<div class="head">Lambda -> SNS</div>
関数を変えてみる
<div class="font75">テストで作成したjsonを引数に</div>
```json=
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
```
<div class="font75">デフォルトで作成されている関数を実行した</div>
```python=
import json
def lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
```
---
<div class="head">Lambda -> SNS</div>
関数を変えてみる
<div class="font75">引数を使用するように変更する</div>
<br>
<div class="font75">テスト値の変更</div>
```json=
{
"key": "Hello AWS!",
}
```
<div class="font75">コードの変更</div>
```python=
import json
def lambda_handler(event, context):
value = event["key"] # 引数の取得
print(value) # printでログに出力できる
return {
'statusCode': 200,
'body': json.dumps(value)
}
```
---
<div class="head">Lambda -> SNS</div>
関数を変えてみる
<div class="font75">保存して実行してみると引数が反映され、ログも出力されている。</div>

---
<div class="head">Lambda -> SNS</div>
SNSを呼び出してみる
:::success
:bulb: 次に先ほど作成したSNSトピックへ、Lambdaからメッセージを発行してみましょう。
:::
---
<div class="head">Lambda -> SNS</div>
SNSを呼び出してみる
<div class="font75">
1. 関数の変更
※ARNはSNSトピックのものをコピペする
</div>
```python=
import boto3
def lambda_handler(event, context):
print("start SNSPublishFunction")
## Publish to AWS SNS.
topic = 'arn:aws:sns:us-east-1:XXXXXXXXXXXXXXX:S3PreSignedURLTOPIC' # 作成したSNSトピックのARN
subject = 'Lambda to SNS' # 件名
message = event["key"] # 本文
sns = boto3.client('sns')
mail = {'TopicArn': topic ,'Message': message ,'Subject': subject}
sns.publish(**mail)
```
---
<div class="head">Lambda -> SNS</div>
SNSを呼び出してみる
<div class="font75">
2. 保存してテスト実行するとエラーとなってしまう
</div>

<div class="font50 red">SNSを呼び出す権限がない</div>
---
<div class="head">Lambda -> SNS</div>
SNSを呼び出してみる
<div class="font75">
3. IAMから権限を付与しに行く
</div>

---
<div class="head">Lambda -> SNS</div>
SNSを呼び出してみる
<div class="font75">
4. ロールより先ほど作成したLambda関数の名前で検索
</div>

---
<div class="head">Lambda -> SNS</div>
SNSを呼び出してみる
<div class="font75">
5. 「ポリシーをアタッチします」をクリック
</div>

---
<div class="head">Lambda -> SNS</div>
SNSを呼び出してみる
<div class="font75">
6. フィルターに「SNS」と入力する
7. 「AmazonSNSFullAccess」を選択する
8. 画面下の「ポリシーのアタッチ」をクリック
</div>

---
<div class="head">Lambda -> SNS</div>
SNSを呼び出してみる
<div class="font75">
9. 再度Lambdaをテスト実行すると「成功」となり、メールとSMSが送られてくる。
</div>

---
### ここまで完成。次は…

---
### S3 -> Lambda

---
### Amazon S3
---
<div class="head">S3 -> Lambda</div>
#### Amazon S3とは
Simple Storage Serviceの略
<iframe src="//www.slideshare.net/slideshow/embed_code/key/4zPD58GMemkCPF?startSlide=9" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe>
---
<div class="head">S3 -> Lambda</div>
#### S3にファイルアップロードすると<br>Lambdaが実行されるようにする
:::success
:bulb: アップロードするためのS3バケットを作成しましょう。
:::
---
<div class="head">S3 -> Lambda</div>
S3バケットの作成
<div class="font75">
1. マネジメントコンソールから「s3」で検索
</div>

---
<div class="head">S3 -> Lambda</div>
S3バケットの作成
<div class="font75">
2. 「バケットを作成」をクリック
3. 「バケット名」を入力(全世界でユニーク)
4. 「リージョン」は既に作成したLambdaとSNSと同じリージョンを選択
5. 「作成」をクリック
</div>

---
<div class="head">S3 -> Lambda</div>
S3バケットの作成
<div class="font75">
6. バケットの作成完了
</div>

---
<div class="head">S3 -> Lambda</div>
S3のアクセス権限
:::success
:bulb: S3のデフォルトのアクセス権の確認をし、ファイルを公開してみましょう。
:::
---
<div class="head">S3 -> Lambda</div>
S3のアクセス権限
<div class="font75">
1. 画像ファイルをドラッグ&ドロップ
2. アップロードをクリック
</div>

---
<div class="head">S3 -> Lambda</div>
S3のアクセス権限
<div class="font75">
3. アップロードしたファイルの詳細を表示
4. オブジェクトURLをクリックする
</div>

---
<div class="head">S3 -> Lambda</div>
S3のアクセス権限
<div class="font75">
5. 公開されていないため。アクセスできない。
6. 「公開する」が非活性なのは、ブロックパブリックアクセスがonになっているため
</div>

---
<div class="head">S3 -> Lambda</div>
S3のアクセス権限
<div class="font75">
7. バケットのアクセス権限より、ブロックパブリックアクセスを全てoffにする。
8. 「保存」をクリック
</div>

---
<div class="head">S3 -> Lambda</div>
S3のアクセス権限
<div class="font75">
9. 「確認」と入力して「確認」をクリック
</div>

---
<div class="head">S3 -> Lambda</div>
S3のアクセス権限
<div class="font75">
10. アップロードしたファイルの詳細を見ると「公開する」が活性化されている。
11. 「公開する」をクリック
12. オブジェクトURLをクリック
</div>

---
<div class="head">S3 -> Lambda</div>
S3のアクセス権限
<div class="font75">
13. 画像が表示される。
</div>

---
<div class="head">S3 -> Lambda</div>
S3のアクセス権限
<div class="font75">
外部に公開されたままだと危険。
なので、ブロックパブリックアクセスをonに戻しておく。
</div>

---
<div class="head">S3 -> Lambda</div>
署名付きURL
:::success
:bulb: Lambdaを使用して、署名付きURLを発行してみましょう。
:::
---
<div class="head">S3 -> Lambda</div>
署名付きURLとは?<br>(Pre-Signed URL)
<div class="font75">
S3ではアクセスのポリシーをパブリックに設定したり、IAMユーザ単位での細かなアクセス制御などを行うことが可能。
署名付きURLとは、その一環として、有効期限を設けて、ある特定のURLからのみアクセスできるようにするための機能。
これを利用することで、基本はプライベートにしておいて、ポリシーを緩めることなく、一時的に他のユーザにファイルを共有したりすることが可能となる。
なお、ユーザ単位のアクセス制御ではないため、有効期限内であれば、誰でもそのURLからアクセスできるという点には注意が必要。
**「特定の人に特定の時間だけファイルを配布したい」といった場合に便利。**
</div>
---
<div class="head">S3 -> Lambda</div>
署名付きURLとは?<br>(Pre-Signed URL)
<div class="font75">
マネジメントコンソール(GUI)から署名付きURLを作成することはできない。
署名付きURLをコマンドラインで発行する際は以下を実行(有効期限:300秒)
※AWSCLIが必要となるため今回はコマンドでのURL作成は省略
</div>
```
aws s3 presign s3://xxxxx-bucket/test-file --expires-in 300
```
---
<div class="head">S3 -> Lambda</div>
署名付きURLとは?<br>(Pre-Signed URL)
<div class="font75">
署名付きURLの例
</div>

---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
1. 先ほど作成したLambda関数「SNSPublishFunction」を開く。
2. 既に書いてあるコードは一旦コメントアウト(以降コメントアウト部分は省略)
</div>
```python=
import boto3
def lambda_handler(event, context):
print("start SNSPublishFunction")
## Publish to AWS SNS.
# topic = 'arn:aws:sns:us-east-1:XXXXXXXXXXXXXX:S3PreSignedURLTOPIC' # 作成したSNSトピックのARN
# subject = 'Lambda to SNS' # 件名
# message = event["key"] # 本文
# sns = boto3.client('sns')
# mail = {'TopicArn': topic ,'Message': message ,'Subject': subject}
# sns.publish(**mail)
```
---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
3. S3のバケット名、オブジェクトキー名を取得するようにコードを修正
</div>
```python=
import boto3
import urllib
def lambda_handler(event, context):
print("start SNSPublishFunction")
## Generate a pre-signed URL for an Amazon S3 object.
s3 = boto3.client('s3')
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
print("bucket:",bucket) # デバッグ
print("key:",key) # デバッグ
```
---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
4. 保存後新しいテストを作成。(テンプレートそのまま)
</div>

---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
5. テストの実行
</div>

<div class="font50">
バケット名、オブジェクトキー名が取得できている。
</div>
---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
先ほど作成したS3バケットからのイベントで起動させたい
6. 「トリガー追加」をクリック
</div>

---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
7. 先ほど作成したS3を選択
8. 「追加」をクリック
</div>

---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
9. S3にファイルをアップロードしてみる。
10. モニタリング→CloudWatchのログを表示
</div>

<div class="font50">
アップロードしたバケット名、オブジェクトキー名が取得できている。
</div>
---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
11. 署名付きURLを作成するようにコードを修正。保存。
</div>
```python=
import boto3
import urllib
def lambda_handler(event, context):
print("start SNSPublishFunction")
## Generate a pre-signed URL for an Amazon S3 object.
s3 = boto3.client('s3')
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
presigned_url = s3.generate_presigned_url(
ClientMethod = 'get_object',
Params = {'Bucket' : bucket, 'Key' : key},
ExpiresIn = 300, # ダウンロード期限:5分
HttpMethod = 'GET')
print ( presigned_url )
```
---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
12. IAMを開きLambda実行ロールにS3へのアクセス権限を与える。
</div>

<div class="font50">
※この権限付与を行わなくても署名付きURLは作成できるが、
URLへアクセスした際に権限がないエラーになる。
</div>
---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
13. 再度S3にファイルをアップロードしてみる。
14. CloudWatchから再度ログを確認する。
</div>

<div class="font50">
署名付きURLが作成できている。
</div>
---
<div class="head">S3 -> Lambda</div>
署名付きURLの作成(Lambda)
<div class="font75">
15. 作成されたURLへアクセスしてみる。
</div>

<div class="font50">
画像が見れた!
</div>
---
<div class="head">S3 -> Lambda</div>
署名付きURLの通知
:::success
:bulb: 作成した署名付きURLをSNSに発行してみましょう。
:::
---
<div class="head">S3 -> Lambda</div>
署名付きURLの通知
<div class="font75">
1. コメントアウトしていた部分を戻し、以下のように修正。保存。
</div>
```python=
import boto3
import urllib
def lambda_handler(event, context):
print("start SNSPublishFunction")
## Generate a pre-signed URL for an Amazon S3 object.
s3 = boto3.client('s3')
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
presigned_url = s3.generate_presigned_url(
ClientMethod = 'get_object',
Params = {'Bucket' : bucket, 'Key' : key},
ExpiresIn = 300, # ダウンロード期限:5分
HttpMethod = 'GET')
## Publish to AWS SNS.
topic = 'arn:aws:sns:us-east-1:XXXXXXXXXXXX:S3PreSignedURLTOPIC' # 作成したSNSトピックのARN
subject = 'Lambda to SNS' # 件名
message = presigned_url # 本文
sns = boto3.client('sns')
mail = {'TopicArn': topic ,'Message': message ,'Subject': subject}
sns.publish(**mail)
```
---
<div class="head">S3 -> Lambda</div>
署名付きURLの通知
<div class="font75">
2. S3にファイルをアップロード
3. 届いたメールのURLをクリック
</div>

<div class="font50">
メールが届いて、画像が見れる。
※@3sss.co.jpのアドレスだとうまくいかないことがあるのでできない場合は別アドレスにで試す。(URLが途中で改行されてしまう)
</div>
---
### 通して動かせるようになった。<br>最後に、、

---
### Slackへ通知する

---
#### S3にファイルアップロードすると<br>メールと同様にSlackに通知が来るようにする
:::success
:bulb: LambdaからSlackへ通知できるようにしてみましょう。
:::
---
<div class="head">Lambda -> Slack</div>
なぜLambdaを間に挟むのか。
<div class="font75">
現状、SNSからSlackへは直接通知することはできない。
</div>

<div class="font50">
いつか画面から選択できるようになってるといいな。。。
</div>
---
<div class="head">Lambda -> Slack</div>
なぜLambdaを間に挟むのか。
<div class="font75">
そのためにはLambdaを呼び出し、
LambdaへSlackに通知する処理を記載する必要がある。
Slackは様々なAPIが存在し、その中でも「Incoming Webhook」というAPIを今回は利用する。
簡単にいうとHTTP通信だけで外部サービス(今回はAWS)からSlackへメッセージの送信ができるものである。
</div>
---
<div class="head">Lambda -> Slack</div>
Slack APIの準備
:::success
:bulb: Slack側へ通知するための準備(URL作成)をしましょう。
:::
---
<div class="head">Lambda -> Slack</div>
Slack APIの準備
<div class="font75">
1. Slackのメニューから「APP管理」をクリック
</div>

---
<div class="head">Lambda -> Slack</div>
Slack APIの準備
<div class="font75">
2. 検索し、「Incoming Webhook」をクリック
</div>

---
<div class="head">Lambda -> Slack</div>
Slack APIの準備
<div class="font75">
3. 「設定を追加」をクリック
4. チャンネルに自分のプライベートチャンネル(自分の名前)を選択し、「Incoming Webhook インテグレーションの追加」をクリック
</div>

---
<div class="head">Lambda -> Slack</div>
Slack APIの準備
<div class="font75">
5. Webhook URLをコピーしておく。
</div>

---
<div class="head">Lambda -> Slack</div>
LambdaからのSlack通知
:::success
:bulb: 生成したURLを使用してLambdaから適当なメッセージをSlackに通知してみましょう。
:::
---
<div class="head">Lambda -> Slack</div>
LambdaからのSlack通知
<div class="font75">
1. Lambdaを開く
2. 「関数の作成」をクリック
3. 関数名に「SlackPostFunction」、ランタイムに「Python3.7」を選択。
4. 画面下の「関数の作成」をクリック
</div>

---
<div class="head">Lambda -> Slack</div>
LambdaからのSlack通知
<div class="font75">
5. コードを修正、保存。(SLACK_POST_URLは先ほどコピーしたものを使用)
</div>
```python=
import json
import urllib.request
def lambda_handler(event, context):
response = post_slack(event)
return response
def post_slack(event):
# 設定
SLACK_POST_URL = "https://hooks.slack.com/services/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"
method = "POST"
# メッセージの内容
message = "Hello Slack from Lambda!"
send_data = {
"text": message,
}
send_text = ("payload=" + json.dumps(send_data)).encode('utf-8')
request = urllib.request.Request(
SLACK_POST_URL,
data=send_text,
method=method
)
with urllib.request.urlopen(request) as response:
response_body = response.read().decode('utf-8')
return response_body
```
---
<div class="head">Lambda -> Slack</div>
LambdaからのSlack通知
<div class="font75">
6. テストを作成。(デフォルト値のままでOK)
7. テスト実行
</div>

<div class="font50">
Slackにメッセージを通知できた。
</div>

---
<div class="head">Lambda -> Slack</div>
SNSからLambdaの呼び出し
:::success
:bulb: S3へファイルアップロードした際に発行されるSNSトピックから、今作ったLambdaを起動してみましょう。
:::
---
<div class="head">Lambda -> Slack</div>
SNSからLambdaの呼び出し
<div class="font75">
1. Lambdaの画面から「トリガーを追加」をクリック
2. SNSを選択し、SNSトピックのARNに「S3PreSignedURLTOPIC」のものを記載
3. 「追加」をクリック
</div>

---
<div class="head">Lambda -> Slack</div>
SNSからLambdaの呼び出し
<div class="font75">
4. コードの修正、保存
※ついでにBot名とアイコンも変えてみる。
</div>
```python=
import json
import urllib.request
def lambda_handler(event, context):
response = post_slack(event)
return response
def post_slack(event):
# 設定
SLACK_POST_URL = "https://hooks.slack.com/services/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"
username = "署名付きURL発行bot" #Bot名
icon = ":robot_face:" #アイコン
method = "POST"
# メッセージの内容
message = event['Records'][0]['Sns']['Message']
message = urllib.parse.quote(message) #URLエンコード
send_data = {
"username": username,
"icon_emoji": icon,
"text": message,
}
send_text = ("payload=" + json.dumps(send_data)).encode('utf-8')
request = urllib.request.Request(
SLACK_POST_URL,
data=send_text,
method=method
)
with urllib.request.urlopen(request) as response:
response_body = response.read().decode('utf-8')
return response_body
```
---
<div class="head">Lambda -> Slack</div>
SNSからLambdaの呼び出し
<div class="font75">
5. S3にファイルをアップロードしてみる。
</div>

---
### 完成!

---
### さらに改良していくとしたら
* 署名付きURLの有効期限をパラメータとして設定できるようにしてみる。
* ファイル圧縮できるようにしてみる。
* ファイル暗号化できるようにしてみる。パスワードも送られてくる。
* S3にアップロードするためのWEB画面を作ってみる。
* etc...
<div class="font75">
気が向いたら改良してみてください。
早いスパンでアジャイル的に開発(改良)→リリースを繰り返せるのもクラウドのメリットです。
</div>
---
### クリンアップ
<div class="left">
S3以外は起動しない限りは課金されないので、残しておいてもいいと思います。
消すのであれば下記を消せば元に戻せます。
</div>
* S3バケットの削除
* Lambda関数の削除(2つ)
* SNSトピックの削除
* SNSサブスクリプションの削除(2つか3つ)
* IAMロールの削除(Lambda関数の名前が入っているもの2つ)
---
### 宣伝
<div class="font75">
2019/8/26(月) 19:00~
◎題名
沼崎さんによる「疎結合アーキテクチャの構築、マイクロサービスとサーバーレスアーキテクチャ集合研修」
◎備考
AWS公式のArchitecting on AWSの一部と同等の内容を想定しております。
本勉強会は基本的には講義を聞くスタイルになります。
※勉強会時にPCやAWSアカウントは不要です。
</div>
---

---
# END
{"metaMigratedAt":"2023-06-14T23:21:28.011Z","metaMigratedFrom":"YAML","title":"AWS HandsOn 20190819","breaks":true,"slideOptions":"{\"theme\":\"white\"}","contributors":"[{\"id\":\"207f0d78-c51c-4e9f-9e9f-2ee4194eef62\",\"add\":27097,\"del\":4437}]","description":"S3/SNS/Lambdaでサーバレスに作るファイルダウンロードURL発行処理"}