CloudWatchとLambdaでユーザーの操作をチェックする

記事タイトルとURLをコピーする

こんにちは、技術4課の多田です。

突然ですが、みなさん、CloudTrail使っていますか?

ユーザーの証跡管理に便利なサービスですが、今回はCloudTrailで溜めたログを活用する話です。

既に昨年のJAWS-UG横浜で発表させていただいた内容ですが、詳細をブログにまとめていきたいと思います。尚、発表資料に関するブログは、こちらになります。

経緯として、私が担当したお客様にて「特定ユーザーのAWS環境での操作を通知する仕組みを入れて欲しい」とご依頼いただき、本エントリで紹介する仕組みで対処しました。

今回やること

今回やることは、以下のことです。

  1. CloudTrailとCloudWatch Logsとの連携
  2. CloudWatch Logsの情報をLambdaへ流す
  3. Lambdaがユーザーに通知内容をカスタマイズし、SNSで通知する

イメージとしては以下のようになります。ユーザーがAWS環境を参照/更新/削除などを行うと、CloudTrail -> CloudWatch Logs -> Lambda -> SNS通知が飛ぶという仕組みです。

それでは、各内容について以下で触れていきます。

CloudTrailとCloudWatch Logsとの連携

CloudTrailのログをCloudWatch Logsに連携するのは非常に簡単です。

CloudTrailの画面より設定ができます。[証跡情報] -> [対象のTrailsを選択] -> [CloudWatch Logs]から設定します。

デフォルトですと、新規に「CloudTrail/DefaultLogGroup」というCloudWatch Logsグループが作成されますが、格納したい保管先があればそのグループ名を指定します。

次に、CloudWatch LogsにアクセスするためのIAMロールとポリシーをウィザードに沿って作成します。

CloudTrailの画面に戻ってきましたら、設定が完了です。

Lambdaがユーザーに通知内容をカスタマイズし、SNSで通知する

CloudWatch Logsから流れてくるデータをカスタマイズする処理は、Lambdaで行います。

CloudWatch Logsから渡されるデータ、以下のような構造で渡されます。

{u'awslogs': {u'data': u'H4sIAAAAAAAAAH1TYU/bMBD9L/7ctHHsOG2+ebSwiI4hWmCCIuQkbmctibPYoXSo/33npAXEJtQPcX3v3rt7d35BpTRGbORyV0sUoylf8sdvs8WCn83QAOltJRu4Dn1GGGWE+tEErgu9OWt0W0NkJLZmlBW6zW0jVDEy22evO/WwhW2kKD8wPJ44/NKhHkXtVbqxP6Uw1sOQZNrUZI2qrdLVqSqsbAyK79FclGkuerp3+d6FtmqtMuHg6KHTnD3JyrqkF6RykCYEh/DzQ4onLKARjaKIsRBHGBMaEOKODGNMSehHdByFPh5TSsdQjFVgjxUldIrpmIUApcz3/cHRNqB/WSHpFG+gUihiheIVwkM/XKHBCrVGNkkOUWV3EAGsBaM7TMK/XUO0g9WNqjJViyLJuxhPpjwJbu8ury/mV3c3PIzm7LZDiqZXgG8M1sdKlHH83tzYSY5EXqpKGZiE1b2EyDLdVvYg8D7jGIaOzuXuWMEi4ckPQsnyO/+6OCf89Jy/dnQhyr6Hf2UMsIALJ7qy8tn2LQtrG5W2Vpr+f7kWvIWRgyswONkLrkVhZEeRwYzdOKcQ60KBjyPPDzx/vMQ0pkFM2N0K7feAVdWT/iXzL7sOaNSmUtVQlOKPrsCdYaZLAA4OE1qq8r+EYUwd4RG20G2T9cC3xf5IegS/WjGVbm1T2a2l6T3dmiu5Oe5Ea7wtLJMX9D51Isklz/MGLOu3JiRDHPlD92WTV7f5BnQ+6Q9gjfzdAvelaKAc92QOu+ZqcRXOYUZwdf+w78Cm1pWRs0KW7qVAoGqL4o0mmXZqlLE08CeZJ6WfexhL5qURnPJwTSbp2u3O+M2IQ5IM0oDkAdjLQuLRScC8cUakR0mayknE1lEQviUtj4+Bbw2v1YkoikM/8BoUAPgnW7tH+4f9X23arOvBBAAA'}}

CloudTrailのログデータは、「u' 'data':」以降から値の中に存在するのですが、ぱっと見該当箇所がわかりません。。

というのもドキュメントによりますと、データ部分はBase64 でエンコードされており、gzip 形式で圧縮されているので、Lambdaのコードでもデータをデコードする必要があります。

実際にデコードしてみますと、以下のようなJSON構造となっており、先ほどよりは見えやすくなりました。

CloudTrailのログは、「"logEvents"」セクションに格納されていますので、このデータの中から必要な情報を抽出して、SNS通知を行う処理を実装しました。

{
 "messageType": "DATA_MESSAGE",
 "owner": "AccountID",
 "logGroup": "/aws/cloudtrail/swx-trail",
 "logStream": "AccountID_CloudTrail_ap-northeast-1",
 "subscriptionFilters": [
 "LambdaStream_CloudTrail-Notification"
 ],
  "logEvents": [
 {
  "id": "33151510541962474777665171134233651761114350748750184448",
  "timestamp": 1486565146000,
  "message": "{\"eventVersion\":\"1.05\",\"userIdentity\":{\"type\":\"IAMUser\",\"principalId\":\"AIDAI2WZPUNLRZVA57L6W\",\"arn\":\"arn:aws:iam::AccountID:user/xxxxxxxx\",\"accountId\":\"AccountID\",\"accessKeyId\":\"xxxxxx\",\"userName\":\"xxxxxx\",\"sessionContext\":{\"attributes\":{\"mfaAuthenticated\":\"false\",\"creationDate\":\"2017-02-08T14:42:36Z\"}},\"invokedBy\":\"signin.amazonaws.com\"},\"eventTime\":\"2017-02-08T14:45:46Z\",\"eventSource\":\"cloudtrail.amazonaws.com\",\"eventName\":\"DescribeTrails\",\"awsRegion\":\"us-west-2\",\"sourceIPAddress\":\"153.170.153.69\",\"userAgent\":\"signin.amazonaws.com\",\"requestParameters\":{\"trailNameList\":[]},\"responseElements\":null,\"requestID\":\"466b209c-ee0d-11e6-b70d-d5f39bf34078\",\"eventID\":\"e2b23d27-0653-4926-8c3e-43bbe976f725\",\"eventType\":\"AwsApiCall\",\"recipientAccountId\":\"AccountID\"}"
  }
 ]
}

CloudWatch Logsの情報をLambdaへ流す

CloudWatch Logsの情報をLambdaに流す設定も非常に簡単です。

まず、CloudWatch LogsからCloudTrailと連携したロググループを選択して、[アクションタブ] -> [Lambdaサービスへのストリーミングの開始]をクリックします。

次に、作ったLambda Functionを選択します。

次に、CloudTrailのログからLambdaに渡すデータをフィルタリングする設定です。

今回は、特定のユーザーのすべての操作をフィルターしたいので、以下のようなフィルタのパターンを定義しました。

{ $.userIdentity.userName = 対象のユーザー名}

上記のフィルター定義は、CloudTrailのJSON形式のログの中でIAMユーザー情報が記録されるセクションなのですが、userIdentity要素という箇所にあたります。

IAMユーザー名の他、ユーザーのcredential情報なども含まれています。詳しくはこちらを合わせてご覧ください(英語のドキュメントになります)。

CloudWatch Logsの画面に戻ってきて、以下の画像のようなメッセージが出力されたら設定は完了です。

これまでの設定でどのような通知が行われるのかを確認すると、以下の通りです。

SNSの通知でカスタマイズしたのは、ログが作成された時間帯、ユーザーがどんな操作(APIをコールしたか)、ユーザーの送信元IPやユーザーエージェントを通知するように設定しました。その他に必要な情報があれば、追加することができます。

まとめ

CloudTrail、CloudWatch Logs、Lambdaの連携いかがでしょうか?

溜めたログを利活用して、ユーザー操作を監視することができるため、AWS環境のセキュリティ向上に役立つ手段の一つかと私自身思いました。

この仕組みでは、CloudWatch Logsの保管料Lambdaの利用料SNSの利用料がCloudTrailのログ保管料の他に必要となる点に注意が必要です。

何か参考になる情報があれば、幸いです。それでは!