AWSコンソールへのログインをGoogle Hangouts Chatで通知する

CloudWatchイベントAWS Console Sign In via CloudTrailを使うと、AWSコンソールへのログインを検知できます。 イベントからLambdaを呼び出し、Hangouts Chatに投稿してみました。 イベントとLambdaのデプロイには、serverless frameworkを使いました。

作ったもの

IAMユーザーのログインを検知

IAMユーザーがAWSコンソールに接続すると、Hangouts Chatに通知されます。 送信元IPアドレスやログインの成功有無、User Agentなどを確認できます。

ログイン成功

IAMユーザーでログインすると、以下の通知が行われます。 ログインに成功するとConsoleLogin:Successにります。 IPアドレス、ユーザーエージェント、IAMユーザー名などを確認できます。

ログイン失敗

ログインに失敗すると、ConsoleLogin:Failureになります。

IAMロールでのログインを検知

IAMロールでのログインも通知されます。

Jumpアカウントに戻る操作(下図)を行うと、eventName:ExitRoleが通知されます。

事前準備

Serverless Frameworkをインストールしておきます。

$ node -v
v12.2.0
$ serverless -v
1.42.2
$

AWS LambdaからGoogle Hangouts Chatに投稿してみたを参考に、Chatルームを作成し、WebHook URLを発行します。 WebHook URLにリクエストを送り、チャットに通知します。

プラグインによるパッケージ管理

LambdaはPython3.7で実行しました。 Lambda関数でrequestsパッケージを呼び出します。 パッケージ管理にserverless-python-requirementsプラグインを利用します。 serverlessのブログを参考にしました。

プラグインとrequestモジュールをインストールします。

npm install --save serverless-python-requirements
pip install request
pip freeze

pip freezeの結果から、requestsについてrequirements.txtに記載します。 私の環境ではrequirements.txtは以下のようになりました。

requests==2.21.0

プラグインの実行にはDockerが必要です。 Dockerデーモンを起動しておきます。

serverless frameworkの作成

providedテンプレートの作成

以下のコマンドを実行すると、serverless.yml、handler.pyのテンプレートが作成されます。

serverless create -t aws-python3 -n lambda-awslogin2hangoutschat

ファイルの記載

3つのファイルを作成します。

  • serverless.yml(serverless frameworkの設定ファイル)
  • handler.py(Lambda関数)
  • consolelogin.json(テスト用のCloudWatchイベントファイル)

serverless.yml

Serverless Frameworkの設定ファイルです。 Lambda関数の設定や、CloudWatch Eventsなどを記述します。 environmentにはLambda関数で利用する環境変数を指定します。HANGOUT_WEBHOOK_URLにWeb HookのURLを記入します。 plugins以下は前述のプラグインの利用に必要です。

service: lambda-awslogin2hangoutschat

provider:
  name: aws
  runtime: python3.7

# you can overwrite defaults here
  stage: prod
  region: ap-northeast-1

# you can add packaging information here
package:
  exclude:
    - consolelogin.json

functions:
  main:
    handler: handler.main
    events:
      - cloudwatchEvent:
          event:
            detail-type:
              - "AWS Console Sign In via CloudTrail"

#    Define function environment variables here
    environment:
      HANGOUT_WEBHOOK_URL: 'Hangout-URL'

#    Add python package(https://github.com/UnitedIncome/serverless-python-requirements)
plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    dockerizePip: true

handler.py

Lambda関数ファイルです。 CloudWatchイベントの内容をevent変数で受け取ります。 body変数にイベントの内容eventevent['version']event['detail']['account']などを追加します。 最後にWebHookにPOSTして終了です。

# -*- coding: utf-8 -*-
from json import dumps, loads
import requests
import os

def main(event, context):
    URL = os.environ['HANGOUT_WEBHOOK_URL']

    ## event(version)
    body = "version:" + str(event['version']) + '\n'

    ## event(other)
    messages_keys = ["account","time","region","detail-type","eventTime","eventSource","eventName","awsRegion","requestParameters","sourceIPAddress","userAgent"]
    for key in messages_keys:
        if 'detail' in event:
            if key in event['detail']:
                body += key + ":" + str(event['detail'][key]) + '\n'

    ## event-detail-responseElements
    messages_response_keys = ["ConsoleLogin"]
    for key in messages_response_keys:
        if 'detail' in event:
            if 'responseElements' in event['detail']:
                if key in event['detail']['responseElements']:
                    body += key + ":" + str(event['detail']['responseElements'][key]) + '\n'

    ## event-detail-userIdentity
    messages_userIdentity_keys = ["type","principalId","arn","accountId"]
    for key in messages_userIdentity_keys:
        if 'detail' in event:
            if 'userIdentity' in event['detail']:
                if key in event['detail']['userIdentity']:
                    body += key + ":" + str(event['detail']['userIdentity'][key]) + '\n'

    ## event-detail-additionalEventData
    messages_additionalEventData_keys = ["LoginTo","MobileVersion","MFAUsed"]
    for key in messages_userIdentity_keys:
        if 'detail' in event:
            if 'additionalEventData' in event['detail']:
                if key in event['detail']['additionalEventData']:
                    body += key + ":" + str(event['detail']['additionalEventData'][key]) + '\n'

    bot_message = {
        'text' : body}

    message_headers = { 'Content-Type': 'application/json; charset=UTF-8'}

    ## POST
    response = requests.post(
        URL,
        headers=message_headers,
        data=dumps(bot_message),
    )

    return loads(response.text)

consolelogin.json

CloudWatchイベントのルールの作成からAWS コンソールのサインインを選択すると、サンプルイベントを表示できます。 jsonが表示されるので、コピーアンドペーストします。

デプロイ

デプロイコマンドを実行します。

$ sls deploy

サンプルイベントを使って、テストします。 チャットに通知されれば成功です。

$ sls invoke -f main -p consolelogin.json

全リージョンへのデプロイ

東京リージョン以外にもデプロイします。 EC2のようなリージョンをサポートするコンソールにログインした場合、そのリージョンでCloudWathイベントが発生します。S3のようなグローバルサービスにログインした場合は、バージニア北部でイベントが発生します。全てのリージョンにCloudWatchイベントとLambdaを設定します。

sls deploy --region us-east-2
sls deploy --region us-east-1
sls deploy --region us-west-1
sls deploy --region us-west-2
sls deploy --region ap-east-1
sls deploy --region ap-south-1
sls deploy --region ap-northeast-3
sls deploy --region ap-northeast-2
sls deploy --region ap-southeast-1
sls deploy --region ap-southeast-2
sls deploy --region ca-central-1
sls deploy --region cn-north-1
sls deploy --region cn-northwest-1
sls deploy --region eu-central-1
sls deploy --region eu-west-1
sls deploy --region eu-west-2
sls deploy --region eu-west-3
sls deploy --region eu-north-1
sls deploy --region sa-east-1

まとめ

CloudWatchイベントAWS Console Sign In via CloudTrailを使うと、AWSコンソールへのログインを検知できます。 イベントからLambdaを呼び出し、Hangouts Chatに投稿してみました。 Serverless Frameworkを使うことで、CloudWatchイベントの作成やPythonのパッケージ管理を簡単にできました。

参考