AWS-CLIでルートユーザーでのログインを通知する

社内にてAWSを導入したいという話があり、部内での検証環境構築を依頼されました。
その際マルチアカウントでの環境構築を行っていましたが、アカウントを作成する毎にCloudTrailやCloudWatchの設定をマネジメントコンソールから行うのは非常に面倒でした。
そこでAWS-CLIを利用して、少しでもコンソール使わず作業を楽に出来ないかと試してみました。

# 今回やってみる事
誰かがルートユーザーでログインした時、メールでログイン通知が来るという設定をAWS-CLIから行いたい。


# 環境準備
## AWS-CLIのインストール
こちらを参考に各OS毎の手順でインストールを行いました。
[AWS-CLIのインストールと設定](https://docs.aws.amazon.com/ja_jp/streams/latest/dev/kinesis-tutorial-cli-installation.html)
手順はリンク先を確認してもらえればすぐわかると思いますが、windows以外はpython2.6.5以上のものとpipでインストールできます。ここではmacを用いています。

## AWS-CLIの設定
事前にCLIから接続するIAMユーザーとアクセスキーの発行を行っておいてください。

参考
[AWS アカウントでの IAM ユーザーの作成](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_users_create.html)

今回許可したIAMポリシーは

- CloudWatch
- EventBridge
- SNS  

の３つをひとまずフルアクセスで許可しております。(そのうちフルアクセスではなく必要なものだけに絞るかも)

それではCLIでアクセス出来るように設定していきます。
設定は次のコマンドで行えます。

```shell

$ aws configure
```
こちらを実行すると以下のような入力を求められます。

```
$ aws configure
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: 
Default output format [None]: 
```
上から順番にIAMユーザのアクセスキー、シークレットアクセスキー、利用するリージョン、出力形式となっております。
アクセスキー、シークレットアクセスキーは作成したIAMユーザーのものを入力します。
リージョンはこちらを参考に利用したいものを入力してください。
[AWS サービスエンドポイント](https://docs.aws.amazon.com/ja_jp/general/latest/gr/rande.html)
出力形式は選択肢としてJSON、text、tableの3つがありますが、ここではjsonを用います。
入力が終われば設定は完了です。

ちなみにAWS-CLIの認証設定は複数保存することもできます。

```shell

$ aws configure --profile hogehoge
```
というように設定情報に名前を付けてあげると先ほど登録した情報と別の名前で登録されるため、複数のIAMユーザーを保持している場合は大変便利になります。ちなみに名前を設定しない場合はdefaultとして登録されます。今回は先ほど登録したdefaultを使っていきます。

# ログイン通知の設定
それでは本題のログイン通知設定に取り掛かります。
手順としてはそう複雑なものではないです。

1. SNSトピックを作成する。
2. トピックにサブスクリプションを作成する。
3. イベントルールの作成
4. 作成したルールにターゲットを設定

この4ステップで設定完了です。

## 1.SNSトピックを作成する。
SNSトピックの作成は次のコマンドで実行できます。

```shell

$ aws sns create-topic --name topic_name
```

`--name`でトピック名を設定しています。必要があれば表示名なども設定できますが、今回は行いません。

##2.トピックにサブスクリプションを作成する。
先ほどのSNSトピックにサブスクリプションを作成するコマンドがこちらです。

```shell
aws sns subscribe --topic-arn topic_arn --protocol email --notification-endpoint your_mail
```

`--topic-arn`には先ほど作成したトピックのものを入れます。`--protocol`はemailとして、`--notification-endpoint`に通知したいメールアドレスを記載します。

コマンドを実行すると次のようなメールが送られてきます。

<img width="870" alt="スクリーンショット 2019-09-20 8.38.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492671/101403cb-e9f5-9ef5-5362-6f2322e94925.png">

こちらは「このメールアドレスで問題ないか」といった確認メールとなっています。「Confirm subscription」のリンクをクリックして有効にしてください。

##3.イベントルールの作成
ここでルートユーザによるログインを検知するトリガーを作成します。
実際のコマンドは次のものになります。

```shell

aws events put-rule --name rule_name --description login_root --event-pattern \
"{\"detail-type\":[\"AWS Console Sign In via CloudTrail\"],\"detail\":{\"userIdentity\":{\"type\":[\"Root\"]}}}"
```
これまでのコマンドと比べると複雑に見えますが、要はjsonでルールの設定を行っているだけです。
`--name`はルールの名前、`--description`はルールの説明です。ここまではこれまでと大きく変わりませんね。問題はjsonの中身です。
まず`--detail-type`に`[\"AWS Console Sign In via CloudTrail\"]`と設定しています。これが「マネジメントコンソールにログインした」ということを検知するトリガーとなっています。これ以降の設定を記述しなければ、任意のユーザーがログインした時にトリガーが動くようになります。
今回はルートユーザーのみを検知したいので、`--detail`を`{\"userIdentity\":{\"type\":[\"Root\"]}}`と設定します。これはユーザーがルートであるという条件になります。

###ちなみに
マネジメントコンソールからGUIでイベントの設定を行う場合、ユーザーのArn設定しかできずtypeを使う場合にはjson編集しか確認できませんでした。複数のアカウントで同じ設定を行う際に逐一Arnを調べるのは少し手間ですし、jsonは書きにくさから抵抗がある人が多いかと思いますので、GUIから設定できるようになればいいなと思います。

## 4.作成したルールにターゲットを設定
ターゲットの設定するコマンドは次になります。

```shell

aws events put-targets --rule rule_name --targets "Id"=1,"Arn"=topic_arn
```

`--rule`は先ほど作成したルール名を、`--targets`にはIdと最初に作成したSNSトピックのArnを記入してください。

これでログイン通知設定が完了しました。最後にルートユーザーでログインしてjsonにまみれたメールが飛んでくるのを確認してください。

##ログイン通知設定のシェルスクリプト
この4ステップのログイン通知設定を一括で流れるようにしたものがこちらです。

```shell:aleart_root_login_aws.sh
#!/bin/bash

# need jq library
topic_arn=$(aws sns create-topic --name send_mail_login_root | jq -r ".TopicArn")

aws sns subscribe --topic-arn $topic_arn --protocol email --notification-endpoint your_mail

aws events put-rule --name login_root --description login_root --event-pattern \
"{\"detail-type\":[\"AWS Console Sign In via CloudTrail\"],\"detail\":{\"userIdentity\":{\"type\":[\"Root\"]}}}"

aws events put-targets --rule login_root --targets "Id"=1,"Arn"=$topic_arn
```


#やってみて
マネジメントコンソールからポチポチして設定する方が直感的で、簡単なのですが何回も繰り返し行うのはやはり大変ですし手間です。同じ作業は出来るだけ簡易化していきたいですね。

今回は試しにAWS-CLIを使ってみましたが、多くの方が「いやCloud Formation使えよ」と思われたかもしれません。また個人的にはshellよりもpythonとかの方が経験があるのでSDKとかも良いかと思ってます。そこらへんでも同じ設定をしてみて、自分に合うもの、応用のきくものを選びたいです。