AWSにログインしたことをSlackに通知したい

株式会社パーソンリンクアドベントカレンダー15日目です！🎉


# はじめに
完成形としてはこのようになっています！
誰が何時にログインしたかをSlackに通知が来るように今回設定していきます。

今回は、dev環境でLambdaを作成しました。そのため、ログインしたときではなくロール切り替え(dev環境）の際にログインしたことになっています。
**実際に実装する際には、本番環境にLambda関数を作成することでAWSログイン時の通知が来るようになります。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/154bb12e-bd64-b216-c328-28bf50566927.png)

## 使用したサービス
* Incoming Webhook
* CloudTrail
* Amazon EventBridge
* Cloud Watch
* Amazon Simple Notification Service （SNS）
* Lambda

## 流れ
**CloudTrail** (AWSマネジメントコンソールへのログインイベントを検知）
↓
**Amazon EventBridge**（検知されたイベントをSNSに通知）(Lambdaに渡せる形にする）
↓
**Amazon Simple Notification Service （SNS）**(SNSに登録のあった通知先にメールを送信）今回はいらない機能ですが、ログの確認ができたので一応送っていました
↓
**Lambda**（EventBridgeをトリガーにしてSlackに投げる）

## 指定したリージョン
**米国東部（バージニア北部）us-east-1**

どうしてバージニア北部に設定しないといけないのかは不明なのですが、[公式](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/EventTypes.html#console_event_type)によると
>AWS Management Console のサインインイベントは、米国東部 (バージニア北部) リージョンでのみ CloudWatch Events によって検出できます。

と記載されていました。なので今回はバージニア北部のリージョンを選択しました

## Webhook URLの取得
[SlackAppディレクトリ](https://personlink.slack.com/apps)から Incoming Webhookの設定をします。
```設定を追加```を押すとチャンネル選択画面に移行します。
Botを働かせたいチャンネルを選択して```Incoming Webhookインテグレーションの追加```を押します。
これでIncoming Webhookを使用する準備ができ、Webhook URLの取得が完了しました。
後にWebhook URLを使用するので記録しておくと便利です。
忘れた！という場合は[SlackAppディレクトリ](https://personlink.slack.com/apps)で Incoming Webhookの```設定```から自分が設定したIncoming Webhookの```編集```から確認することができますのでご安心を・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/49e5a6b6-8251-27d4-b9ee-3f0a3bffc059.png)

#  CloudTrail
CloudTrailでAWS アカウント内で行われた操作のイベントログを記録します。ここでサインインイベントが記録します。

ここでは
* 証跡の作成
* 作成した証跡のストレージの場所として、Amazon S3を使用

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/f2f15884-b67b-5649-eaef-5897c320c622.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/ff50d473-eff6-1058-5be3-7b9093ffeb0b.png)


# Amazon EventBridge

Amazon EventBridgeでは**ルール**を作成します

ターゲットは**SNSトピック**と**Lambda関数**に設定します。これにより上記の通りCloudTrailで検知されたイベントをSNSに通知、Lambdaに渡せる形にする事ができています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/bf4aef2a-dab2-dca0-14ac-f3bcb3168e0c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/019fd4a4-232d-45b3-d342-de3958fb9348.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/62f3db47-ec76-6fa9-d6d2-b7f761c3791f.png)


## Cloud Watch
Cloud WatchはEventBridgeと同じ動作をしています。
しかし、自分はここで**任意のユーザー**を指定しましたが、ARNを入力することで特定のユーザーに絞ることも可能である事がわかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/2703c4bb-8541-0b5a-ba39-a06019e2c8b3.png)



# Amazon Simple Notification Service （SNS）
今回は実験的に行ったため、一応メールにも通知が来るようにしましたが実際に実装する際には通知が山のように来るのでいらない気がします・・・
一応仕組みとして理解したのでこの場でアウトプットも兼ねて記述しておきます

ここでは以下の設定を行います
* トピック
* サブスクリプション

### トピック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/c4b0af0a-45e3-c527-d5c8-f9e635711f76.png)



### サブスクリプション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/2f65b1e7-59ed-476f-eda3-b6845d9fae70.png)



ここでは通知するメールアドレスとプロトコルの設定をします

# Lambda

ダッシュボードから**関数の作成**を選択します
関数名は任意の名前、ランタイムはPython3.8を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/d79de8f4-7bad-be98-dac2-9eb7738d0652.png)



関数の画面で**トリガーを追加**を選択し、今回のトリガーとなるEventBridgeを指定すると下画面のようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/dbf6c340-8dd4-44be-163a-897e58a6ec37.png)



**コード**は

```
import json
import urllib.request
import os



def lambda_handler(event, context):
    # TODO implement
   
    print(json.dumps(event))
    
    print(event['detail']['userIdentity']['principalId'])
    principalId = event['detail']['userIdentity']['principalId']
    target =':'
    idx =  principalId.find(target)
    username = principalId[idx+1:]
    print(username)
    post_slack(username)
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

def post_slack(username):
    message = username

    send_data = {
        "username": "AWSログイン通知",
        "icon_emoji": ":Aws Simple Icons Aws Cloud :",
        "text": message + "さんがログインしました",
    }
    send_text = "payload=" + json.dumps(send_data)
    # URLにはご自分のWebhook URLを入力してください
    request = urllib.request.Request(
        os.environ['webhookURL'], 
        data=send_text.encode("utf-8"), 
        method="POST"
    )
    with urllib.request.urlopen(request) as response:
        response_body = response.read().decode("utf-8")
```
として**Deploy**し**Test**することでメール通知が来るようになります。
ここで忘れ去られていたWebhookの設定をします。**環境変数**を選択し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1545871/6408e464-9475-5975-165c-a621f5bee0d3.png)



**キー**を```webhookURL```、値を先程記録したwebhookURLを選択します。
これによってSlack通知が来るようになります！