【Excel改造】AWSへのアクセスログをExcelで表示してみた【CloudTrail編】

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS CloudTrailのログがどんなものかもっと見てみたい

弊社横田あかりの下記ブログにて先日のAWS re:Invent2013で発表されたAWSのログ追跡機能AWS CloudTrailが紹介されていました。

AWS re:Invent2013参加レポート #3 新サービス AWS CloudTrail | Developers.IO

AWS re:Invent2013参加レポート #6 AWS CloudTrailを使ってサーバーを起動した時刻と接続元を確認する | Developers.IO

現在はアクセスログがS3にJSON形式で出力されるだけなので、なんらかのツールで解析をしないと人間が見るにはまだ辛い状態です。

弊社のメンバーズポータルでもひょっとするとログ閲覧機能が実装されるかもしれませんが、それらツールを待ってられない気分なので、いつもの如く(?)Excelで表示してみることにしましたwww

本記事のアプリケーションの実行結果

本記事ではAWS CloudTrailアプリケーションの開発の紹介の前に、開発したアプリケーションの実行結果をご紹介したいと思います。今回は簡単なExcelベースのAWSアクセスログビューアを作成していますが、その雰囲気だけでも味わって頂ければと思います。

シナリオ

ここでは下記のシナリオで作業を行った結果のログの内容を可視化してみたいと思います。

  1. AWSアカウントのマスターアカウントでAWS Manage Consoleにログインする。
  2. IAMユーザー(iam-fukuda)を作成する。
  3. IAMユーザーのアクセスキーを作成する。
  4. IAMユーザーをグループに所属させる。
  5. IAMユーザーのログインプロファイルを作成する。
  6. ログアウトする。
  7. IAMユーザー(iam-fukuda)でAWS Manage Consoleにログインする。
  8. ウィザードを使ってEC2インスタンスを起動する。
  9. EC2インスタンス一覧画面でインスタンスをTerminateする。

アプリケーションの実行

今回作成したAWSアクセスログビューアはExcelのリボンから起動するので、下記のCloudTrailグループのログ一覧ボタンをクリックします。

Excel CloudTrail 01

実行結果の確認:マスターアカウントでの操作

アプリケーションを実行すると、ログが下記のように出力されています。

Excel CloudTrail 02

※ここではフィルターの設定とオレンジ色のセル着色のみ手で行っています。

本アプリケーションではログのほぼすべての属性をそのまま表示してみました。プロパティ名の解説をしなくても、値をみれば一目瞭然なログの内容かと思います。

上記ではシナリオの2番めから5番目の作業が実際にログに残されていることがわかります(オレンジ色のセル)

上記からわかること:

  • シナリオにそってAPI実行のイベントが正しく記録されている。
    • IAMユーザー(iam-fukuda)を作成する:CreateUser
    • IAMユーザーのアクセスキーを作成する:CreateAccessKey
    • IAMユーザーをグループに所属させる:AddUserToGroup
    • IAMユーザーのログインプロファイルを作成する:CreateLoginProfile
  • 誰がAPIを実行したかが記録されている。
    • 【Account Alias】=マスターアカウントのアカウント・エイリアス
  • いつAPIを実行したかが記録されている。
    • 2013-11-15T12:20:13Z 等
  • どこからAPIを実行したかが記録されている。
    • xxx.xxx.xxx.xxx = クラスメソッド社内のIPアドレス

確かに誰がいつどこから何にアクセスしたかが、ちゃんと記録されていました。ここではオミットしていますが、API実行に対してどのようなリクエストパラメータが渡され、どのようなレスポンスが返されているかも、すべて記録されています。

実行結果の確認:IAMユーザーでの操作

さらに、IAMユーザーでAWS Management Consoleを操作したシナリオ部分のアクセスログを確認してみたいと思います。

Excel CloudTrail 03

上記ではシナリオの7番めから9番目の作業がログに残されていることがわかります(オレンジ色のセル)

上記からわかること:

  • シナリオにそってAPI実行のイベントが正しく記録されている。
    • IAMユーザー(iam-fukuda)でAWS Manage Consoleにログインする:GetSessionToken
    • ウィザードを使ってEC2インスタンスを起動する:RunInstances
    • EC2インスタンス一覧画面でインスタンスをTerminateする:TerminateInstances
  • 誰がAPIを実行したかが記録されている。
  • aim-fukuda:IAMユーザー名

上記ではGetSessionTokenだけが少しわかりづらいイベント名になっていますが、ログイン処理はSTS(AWS Security Token Service)からTokenを取得する処理なので、このようにアクセスログに記録されています。

一旦まとめ

簡単なExcelベースのAWSアクセスログビューアを作ってみたわけですが、個人的にもAWS CloudTrailの内容がよく理解できました。開発中のデバッグ環境ではAPIリクエスト、レスポンスの中身も見えたので、詳細な証跡がちゃんと記録されていて、AWS CloudTrailは様々なシーンで活用できそうだなと感じました。

プチ注意点

  • 正:AWS CloudTrail(クラウドトレイル)
  • 誤:AWS CloudTail(クラウドテイル)

(参考)同様の注意点

  • 正:AWS Elastic Beanstalk(ビーン・ストーク)
  • 誤:AWS Elastic Beanstalk(ビーンズ・トーク)

※以後、本アプリケーションの開発概要となります

開発環境

  • Windows 8
  • Visual Studio 2012(C#)
  • Excel 2013
  • AWS SDK for .NET

事前準備

リボン上にボタンを配置する

Excelアドインプロジェクトを用意したら、リボン上にボタンを配置し、イベントハンドラを作成しておきます。下図の一番右のボタンが今回実装するボタンです。

Excel CloudTrail 04

Excel関連の準備を行う

イベントハンドラではまずExcel関連の準備を行っています。

            #region ■アクティブシート参照の取得とセル変数の宣言

            activeWorksheet = ((Excel.Worksheet)Globals.ThisAddIn.Application.ActiveSheet);

            if (activeWorksheet == null)
            {
                return;
            }

            #endregion

            #region ■ログ一覧ヘッダーの作成

            rowCounter = 1;

            // ログ一覧ヘッダー
            cell = activeWorksheet.get_Range("A" + rowCounter);
            cell.Value2 = "awsRegion";
            cell.Interior.ColorIndex = 33;

            cell = activeWorksheet.get_Range("B" + rowCounter);
            cell.Value2 = "eventName";
            cell.Interior.ColorIndex = 33;

            cell = activeWorksheet.get_Range("C" + rowCounter);
            cell.Value2 = "eventSource";
            cell.Interior.ColorIndex = 33;

            cell = activeWorksheet.get_Range("D" + rowCounter);
            cell.Value2 = "eventTime";
            cell.Interior.ColorIndex = 33;

            cell = activeWorksheet.get_Range("E" + rowCounter);
            cell.Value2 = "eventVersion";
            cell.Interior.ColorIndex = 33;

            cell = activeWorksheet.get_Range("F" + rowCounter);
            cell.Value2 = "sourceIPAddress";
            cell.Interior.ColorIndex = 33;
            
            cell = activeWorksheet.get_Range("G" + rowCounter);
            cell.Value2 = "userAgent";
            cell.Interior.ColorIndex = 33;

            cell = activeWorksheet.get_Range("H" + rowCounter);
            cell.Value2 = "userIdentity.userName";
            cell.Interior.ColorIndex = 33;            

            rowCounter++;

            #endregion

Amazon S3からAWS CloudTrailのログファイルを取得する

Amazon S3からのAWS CloudTrailのログファイルの取得は下記のようなレガシーな同期処理で今回は取得してみました。

          #region ■AWSアクセスクライアントの作成

          var s3Client = new AmazonS3Client(region); // Amazon.RegionEndpoint.USEast1

          #endregion

          #region ■AWS CloudTailのログの取得

          var listObjectRequest = new ListObjectsRequest();

          listObjectRequest.BucketName = bucketName;

          using (var listObjectsResponse = s3Client.ListObjects(listObjectRequest))
          {
              foreach (var item in listObjectsResponse.S3Objects)
              {
                  Debug.WriteLine(item.Key);
      
                  GetObjectRequest getObjectRequest = new GetObjectRequest();

                  getObjectRequest.BucketName = bucketName;
                  getObjectRequest.Key = item.Key;
                    
                  using (S3Response getObjectResponse = s3Client.GetObject(getObjectRequest))
                  {
                      using (Stream s = getObjectResponse.ResponseStream)
                      {
                          using (GZipStream gzipStream = new GZipStream(s, CompressionMode.Decompress))
                          {
                              StreamReader Reader = new StreamReader(gzipStream, Encoding.Default);

                              string json = Reader.ReadToEnd();

                              if (!json.Equals(""))
                              {
                                  DisplayLog(json);
                              }                                
                          }
                      }
                  }
              }    
          }

          #endregion

S3のGetObject処理の結果のStreamをGZipStreamを用いて解凍しています。最後に取得したログのJSONファイルを後続のログ表示処理に渡しています。

※リージョンはここでは執筆時点でAWS CloudTrailのサービスが提供されている Amazon.RegionEndpoint.USEast1 で設定しています。

※最新のAWS SDK for .NET 2.0ではクラスインスタンス作成時のWithを使ったいわゆる「流れるようなインターフェース」が廃止になったので、上記でModelの作成時にはべたに値をセットしています(バケット名設定部分等)

※本来はAWS SDK for .NET 2.0から用意されている非同期インターフェースでAPIを呼び出したいところですが、それに関してはまた後日。

AWSアクセスログ一覧の描画

最後に先ほど取得したJSON形式のログファイルをExcelシートに出力してみたいと思います。

        private static void DisplayLog(string json)
        {
            var records = DynamicJson.Parse(json).@Records;

            foreach (var log in records)
            {
                string myUserAgent = log.@userAgent;

                // userAgentが長い場合は短くしています。
                // 長い例:"AWSConsole, aws-sdk-java/1.4.5 Linux/2.6.18-348.4.1.1123.13.fleetxen Java_HotSpot(TM)_64-Bit_Server_VM/24.45-b08"
                if (myUserAgent.IndexOf(",") > 0)
                {
                    myUserAgent = myUserAgent.Substring(0, myUserAgent.IndexOf(","));
                }

                cell = activeWorksheet.get_Range("A" + rowCounter);
                cell.Value2 = log.@awsRegion;

                cell = activeWorksheet.get_Range("B" + rowCounter);
                cell.Value2 = log.@eventName;

                cell = activeWorksheet.get_Range("C" + rowCounter);
                cell.Value2 = log.@eventSource;

                cell = activeWorksheet.get_Range("D" + rowCounter);
                cell.Value2 = log.@eventTime;

                cell = activeWorksheet.get_Range("E" + rowCounter);
                cell.Value2 = log.@eventVersion;

                cell = activeWorksheet.get_Range("F" + rowCounter);
                cell.Value2 = log.@sourceIPAddress;

                cell = activeWorksheet.get_Range("G" + rowCounter);
                cell.Value2 = myUserAgent;

                cell = activeWorksheet.get_Range("H" + rowCounter);
                cell.Value2 = log.@userIdentity.@userName;                

                rowCounter++;
            }
        }

ポイントはDynamicJsonを用いてJSONを読み込んでいる部分です。

DynamicJson - CodePlex

JSONオブジェクトからルートのRecords属性を取り出し、その中に複数格納されているアクセスログ情報をExcel上に展開しています。ドットの後にアットマークを用いることにより子要素の特定のキーの値を取得しています。この流儀はE4Xに似ていますね。

JSONからデータが取れれば、後はセルのValue2に値をセットすればOKです。

 アプリケーションの実行

それではアプリケーションを実行してみましょう(以後ブログの前半に続く)