Lambda & CloudWatchEvents & Slackで 長期的にログインしていないIAMユーザを検知・通知する

# 概要

　AWSを利用する際には、利用者ごとにIAMユーザを作成して、作業を進めていると思いますが、IAMユーザがどう管理されているのでしょうか？　
　自分が勤めている会社の社内基準では、定期的にアカウント(AWSだとIAMユーザになります)の棚卸しを実施する必要がありますが、実際に各AWSアカウントごとにIAMの棚卸しをちゃんと管理されているかと聞かれると、正直に言って微妙だなという感じです。
　IAMユーザの棚卸し的な機能はAWSが提供されていないこともあって、今回はpythonの学習も兼ねて、CloudWatch Events、Lambda、Slackを使って、長期的にログインしていないIAMユーザを検知・通知するようなものを作ってみました。
　まだpythonを勉強し始めたばかりでもあって、コード自体がきれいになっていませんが、少し皆さんと共有できたらと思います。

# 使えるまでの流れ

Slackの設定とかLambdaの作成とかの作業がありますが、特に難しくはありません。下記の流れでやります。
1. Slack側の設定(Incoming WebHooksを利用)
2. ローカル環境で、コードなどの準備(LambdaからSlackへの送信用に[slackweb](https://github.com/satoshi03/slack-python-webhook)を使います)
3. Lambdaにコードをあげて、定期的に実行するように設定
4. 実行結果を確認

# Slack

Slackについては、設定する作業が少ないです。
Custom Integrationsの[Incoming WebHooks](https://qiubinbin.slack.com/apps/new/A0F7XDUAZ-incoming-webhooks)を利用して、Configurationsを作成します。
Lambdaから送信するチャンネルの設定とかWebhookのURLをメモるとかやっておけばいいです。

イメージ的にはこんな画面になります。
<img width="1898" alt="2.pic_hd.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/9b91ed31-1f81-37d7-6aea-1881051ec8f4.jpeg">

# ローカル環境で、コードの準備

slackwebを作業用のディレクトリにインストールします。今回の例ではcheck-iam-usersを作業用のディレクトリにします

```
$ mkdir ~/check-iam-users

$ sudo pip install slackweb -t ./check-iam-users/

$ cd check-iam-users/ && ls
slackweb			slackweb-1.0.5-py2.7.egg-info
```

check-iam-usersに下記のlambda用のpythonコードのWebhookの箇所に作成したIncoming WebHooksのURLを記入し、作成する。
なお、下記の例では、 90日以上ログインしていないユーザを検出・通知する例です。

```lambda_function.py
# -*- coding: utf-8 -*-
from __future__ import print_function
import boto3
import time
import calendar
import slackweb

print('Loading function')

# Webhook
Slack = slackweb.Slack(url="https://hooks.slack.com/services/T0HTZK5S4/******************z5w")

client = boto3.client('iam')

def lambda_handler(event, context):

    # Slack Message Attachments
    Attachments = []

    # 指定した日数以上ログインしていないユーザ
    Users = []

    # 日数を指定
    Days = 90
    Interval = 60 * 60 * 24 * Days
    print(Interval)

    # 現在の時刻を取得
    Now = time.time()
    print(Now)

    UsersList = client.list_users()
    for User in UsersList["Users"]:
        print(User)

        if str(User.get("PasswordLastUsed")) != 'None':
            PasswordLastUsedUnixTime = calendar.timegm(User["PasswordLastUsed"].utctimetuple())
            print(PasswordLastUsedUnixTime)

            if Now - PasswordLastUsedUnixTime > Interval:
                Info = {
                    "UserName" : User['UserName'],
                    "LastLogin" : str(User['PasswordLastUsed'])
                }
                Users.append(Info)
    print('######################')


    if len(Users) != 0:

        Attachments = [
            {"pretext": str(Days) + "日以上、ログインしていないユーザがあります!"}
        ]

        print(Users)
        for User in Users:
            print('######################')
            print(User["UserName"])
            print('######################')
            UserName = User["UserName"]
            PasswordLastUsed = User["LastLogin"]
            Text = "```IAMユーザ: " + UserName + "\n" + \
                    "LastLogin: " + PasswordLastUsed + "```"

            Attachment = {
                "text": Text,
                "color": "danger",
                "mrkdwn_in": ["text"]
            }
            Attachments.append(Attachment)

    else :
        Attachments = [
            {"pretext": "IAMユーザをログイン状況を確認しました.\n" + \
                        str(Days) + "日以上、ログインしていないユーザがありません!"}
        ]

    Slack.notify(attachments = Attachments)

```

ソースコードをzip化

```
$ zip -r src.zip lambda_function.py slackweb
  adding: lambda_function.py (deflated 59%)
  adding: slackweb/ (stored 0%)
  adding: slackweb/__init__.py (deflated 4%)
  adding: slackweb/__init__.pyc (deflated 28%)
  adding: slackweb/slackweb.py (deflated 60%)
  adding: slackweb/slackweb.pyc (deflated 54%)
```


# Lambdaの作成

　Lambdaの作成については、特に詳しく書くつもりがありません、 [「スケジュールされたイベントでの AWS Lambda の使用」](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-scheduled-events.html)をご参考に、Lamda用のroleの設定とかを注意して、作っていただければいいと思います。

# 実行結果

動作を確認するために、Lambdaをテストしてみると、イメージ的には、下記ようなmessgaeがSlackに送信されます。

指定した90日以上、ログインしていないIAMユーザがある場合
<img width="1476" alt="IAMユーザ棚卸し.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/79b79bab-af5a-6d2a-ae10-74c3a989e861.jpeg">

指定した90日以上、ログインしていないIAMユーザがない場合
<img width="1466" alt="5.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/f4c01b9d-4912-793a-b4a5-9e1a4e851331.jpeg">

# 最後

非常にざっくりではありますが、Lambda & CloudWatchEvents & Slackで 長期的にログインしていないIAMユーザを検知・通知するものを皆さんと共有しまいた。

仕組みがだいたい同じですが、次は 長期的に利用されていないAccessKeyを検知・通知するものを紹介したいと思います。