【アップデート】CloudWatch EventsのターゲットにKinesis Firehoseを選択できるようになりました!

森永です。

AWSのAPIイベントなどを契機にアクションを起こすことが出来るサービス「CloudWatch Events」ですが、アクションを起こすターゲットとして「Kinesis Firehose」が選択できるようになりました!

今までも「Kinesis Streams」は選択することが出来たのですが、Streamsの場合はLambdaなどで転送処理を書いて上げる必要がありました。 「Kinesis Firehose」は転送処理込みでデータをS3やRedshift、Elasticsearch Serviceなどに連携するためのサービスですので、準リアルタイムにAWSのAPIの動きを収集、分析するのが簡単になったというわけです。

試してみる

現在(2017/06/26)Kinesis Firehoseが東京リージョンに対応していません。そのため、今回の連携も東京では使用することが出来ません。今回の検証ではオレゴンリージョンを使用しています。今後東京リージョンにKinesis Firehoseが来ることをお祈り下さい。

構成

今回はCloudWatch Eventsで拾える全てのイベント(だいたいCloudTrailで拾えるイベントと同じ)をS3に投げてみます。
あくまでも検証用ですので、本番投入される際は可用性などを考えて設計して下さい。

CT+CWE+ESS (1)

S3の準備

適当にS3バケットを作成しておきます。
IAM Roleでアクセス権限は付与するのでバケットポリシーは何も設定しなくて構いません。

Kinesis Firehoseの準備

データ転送先を設定する「Destination」にて「S3」を選択し、適当な名前をつけます。
「S3 bucket」の項目では、保管先のS3バケットを指定します。 prefixをつけることも出来るので、「cwe-kinesis」というprefixをつけておきます。(末尾に/をつけ忘れないように…)

Amazon_Kinesis_Firehose

次画面の設定は初期値でやっていきます。
ここで、データの整形など設定することも可能です。
一番下のIAM Roleの設定のみ行って下さい。(新規作成で大丈夫です。)

screencapture-us-west-2-console-aws-amazon-firehose-home-1498030112311

CloudWatch Eventsの準備

次にCloudWatch Eventsの設定をしていきます。
どんなイベントが来たらアクションを起こすか(Event Source)とどこにアクションさせるか(Event Target)を設定します。

Event Sourceでは、全てのイベントを取得したいので「All Events」を選択します。
Event Targetでは、「Firehose delivery stream」を選択し、「Delivery stream」に先ほど作成したKinesis Firehoseを選択します。
連携するためにIAM Roleが必要ですが、既存のものがなければ新しいものを作成して下さい。

CloudWatch_Management_Console

名前などを入力したら完成です。

動作確認

では、動作を確認するために、EC2の起動停止をしてみます。

操作した後にKinesis Firehoseのメトリクスを確認するとちゃんと転送されていることが分かりました。

Amazon_Kinesis_Firehose 2

S3を確認すると、prefix-YYYY-MM-DDというディレクトリ構造が出来ています。
他のログと同じバケットに入れる場合はprefixをつけないとごちゃごちゃしそうです。

S3_Management_Console

ディレクトリの中には、ファイルが出来ていました。

S3_Management_Console 2

中身を確認してみます。

$ cat cwe-kinesis-integration-1-2017-06-26-01-09-01-8288619c-5452-488b-81d8-40c1b8b8d9ec | jq .
{
  "version": "0",
  "id": "5fa3590e-5012-4e97-b12e-0465339db3df",
  "detail-type": "AWS API Call via CloudTrail",
  "source": "aws.events",
  "account": "123456789012",
  "time": "2017-06-26T01:08:44Z",
  "region": "us-west-2",
  "resources": [],
  "detail": {
    "eventVersion": "1.05",
    "userIdentity": {
      "type": "IAMUser",
      "principalId": "ABCDEFGHIJ1234567890",
      "arn": "arn:aws:iam::123456789012:user/cm-morinaga.taishi",
      "accountId": "123456789012",
      "accessKeyId": "ABCDEFGHIJKLMNOPQRST",
      "userName": "cm-morinaga.taishi",
      "sessionContext": {
        "attributes": {
          "mfaAuthenticated": "true",
          "creationDate": "2017-06-26T00:55:09Z"
        }
      },
      "invokedBy": "signin.amazonaws.com"
    },
    "eventTime": "2017-06-26T01:08:44Z",
    "eventSource": "events.amazonaws.com",
    "eventName": "PutTargets",
    "awsRegion": "us-west-2",
    "sourceIPAddress": "123.11.123.22",
    "userAgent": "signin.amazonaws.com",
    "requestParameters": {
      "targets": [
        {
          "inputPath": "",
          "arn": "arn:aws:firehose:us-west-2:123456789012:deliverystream/cwe-kinesis-integration",
          "input": "",
          "roleArn": "arn:aws:iam::123456789012:role/service-role/AWS_Events_Invoke_Firehose_1119709575",
          "id": "Id318456208838"
        }
      ],
      "rule": "cwe-kinesis-integration"
    },
    "responseElements": {
      "failedEntryCount": 0,
      "failedEntries": []
    },
    "requestID": "003748ee-5a0c-11e7-9f6d-2307a1836b89",
    "eventID": "e46b2c9b-dadf-4b24-a9b8-a8d44e899565",
    "eventType": "AwsApiCall",
    "apiVersion": "2015-10-07"
  }
}
{
  "version": "0",
  "id": "ab574c57-bd27-481a-995f-1d28ff60a84f",
  "detail-type": "AWS API Call via CloudTrail",
  "source": "aws.events",
  "account": "123456789012",
  "time": "2017-06-26T01:08:44Z",
  "region": "us-west-2",
  "resources": [],
  "detail": {
    "eventVersion": "1.05",
    〜省略〜
    "eventSource": "events.amazonaws.com",
    "eventName": "PutRule",
    "requestParameters": {
      "description": "",
      "name": "cwe-kinesis-integration",
      "state": "ENABLED",
      "eventPattern": "{\"account\":[\"123456789012\"]}",
      "scheduleExpression": ""
    },
    〜省略〜
  }
}
{
  "version": "0",
  "id": "27150cf2-ea29-408e-a7e9-fe4b4ae97779",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2017-06-26T01:09:47Z",
  "region": "us-west-2",
  "resources": [
    "arn:aws:ec2:us-west-2:123456789012:instance/i-01234567891234567"
  ],
  "detail": {
    "instance-id": "i-01234567891234567",
    "state": "pending"
  }
}
{
  "version": "0",
  "id": "a1badfe1-5cd2-45c4-a7b4-f14a9fbae7e8",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2017-06-26T01:10:02Z",
  "region": "us-west-2",
  "resources": [
    "arn:aws:ec2:us-west-2:123456789012:instance/i-01234567891234567"
  ],
  "detail": {
    "instance-id": "i-01234567891234567",
    "state": "running"
  }
}
{
  "version": "0",
  "id": "b2b7edf5-8f60-4763-b891-9d72b4d818c4",
  "detail-type": "AWS API Call via CloudTrail",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2017-06-26T01:09:47Z",
  "region": "us-west-2",
  "resources": [],
  "detail": {
    "eventVersion": "1.05",
    〜省略〜
    "eventSource": "ec2.amazonaws.com",
    "eventName": "RunInstances",
    "requestParameters": {
      "instancesSet": {
        "items": [
          {
            "imageId": "ami-12345678",
            "minCount": 1,
            "maxCount": 1,
            "keyName": "cm-morinaga-oregon"
          }
        ]
      },
      "groupSet": {
        "items": [
          {
            "groupId": "sg-d0162db5"
          }
        ]
      },
      "instanceType": "t2.nano",
      "blockDeviceMapping": {
        "items": [
          {
            "deviceName": "/dev/xvda",
            "ebs": {
              "volumeSize": 8,
              "deleteOnTermination": true,
              "volumeType": "gp2"
            }
          }
        ]
      },
      "tenancy": "default",
      "monitoring": {
        "enabled": false
      },
      "disableApiTermination": false,
      "instanceInitiatedShutdownBehavior": "stop",
      "clientToken": "SjTRx1498439386418",
      "ebsOptimized": false
    },
    〜省略〜
  }
}
{
  "version": "0",
  "id": "8e1540a7-9498-4444-9569-a2662e8f92e7",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2017-06-26T01:12:42Z",
  "region": "us-west-2",
  "resources": [
    "arn:aws:ec2:us-west-2:123456789012:instance/i-01234567891234567"
  ],
  "detail": {
    "instance-id": "i-01234567891234567",
    "state": "stopping"
  }
}
{
  "version": "0",
  "id": "fd00a2be-3f64-4a1c-8421-8fe609ccd2c1",
  "detail-type": "AWS API Call via CloudTrail",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2017-06-26T01:12:42Z",
  "region": "us-west-2",
  "resources": [],
  "detail": {
    "eventVersion": "1.05",
    〜省略〜
    "eventSource": "ec2.amazonaws.com",
    "eventName": "StopInstances",
    "requestParameters": {
      "instancesSet": {
        "items": [
          {
            "instanceId": "i-01234567891234567"
          }
        ]
      },
      "force": false
    },
    〜省略〜
  }
}
{
  "version": "0",
  "id": "06e72f01-af96-43ea-9fae-b8ee400aa859",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2017-06-26T01:13:07Z",
  "region": "us-west-2",
  "resources": [
    "arn:aws:ec2:us-west-2:123456789012:instance/i-01234567891234567"
  ],
  "detail": {
    "instance-id": "i-01234567891234567",
    "state": "stopped"
  }
}

「detail-type」が「AWS API Call via CloudTrail」となっているものはCloudTrailで取得したイベントです。
こちらの場合は、「detail.eventName」にどんなAPI呼び出しが行われたのか、「detail.requestParameters」にAPI呼び出しに使用されたリクエストパラメータ、「responseElements」にそのレスポンスが記載されています。
もちろんリクエスト元のIPアドレスやユーザー名、IAM UserなのかIAM Roleなのかも分かります。

{
  "version": "0",
  "id": "5fa3590e-5012-4e97-b12e-0465339db3df",
  "detail-type": "AWS API Call via CloudTrail",
  "source": "aws.events",
  "account": "123456789012",
  "time": "2017-06-26T01:08:44Z",
  "region": "us-west-2",
  "resources": [],
  "detail": {
    "eventVersion": "1.05",
    "userIdentity": {
      "type": "IAMUser",
      "principalId": "ABCDEFGHIJ1234567890",
      "arn": "arn:aws:iam::123456789012:user/cm-morinaga.taishi",
      "accountId": "123456789012",
      "accessKeyId": "ABCDEFGHIJKLMNOPQRST",
      "userName": "cm-morinaga.taishi",
      "sessionContext": {
        "attributes": {
          "mfaAuthenticated": "true",
          "creationDate": "2017-06-26T00:55:09Z"
        }
      },
      "invokedBy": "signin.amazonaws.com"
    },
    "eventTime": "2017-06-26T01:08:44Z",
    "eventSource": "events.amazonaws.com",
    "eventName": "PutTargets",
    "awsRegion": "us-west-2",
    "sourceIPAddress": "123.11.123.22",
    "userAgent": "signin.amazonaws.com",
    "requestParameters": {
      "targets": [
        {
          "inputPath": "",
          "arn": "arn:aws:firehose:us-west-2:123456789012:deliverystream/cwe-kinesis-integration",
          "input": "",
          "roleArn": "arn:aws:iam::123456789012:role/service-role/AWS_Events_Invoke_Firehose_1119709575",
          "id": "Id318456208838"
        }
      ],
      "rule": "cwe-kinesis-integration"
    },
    "responseElements": {
      "failedEntryCount": 0,
      "failedEntries": []
    },
    〜省略〜
  }
}

「detail-type」が「EC2 Instance State-change Notification」となっているものはEC2の状態変化によって起きるイベントです。pendingなど途中の状態も記録されます。
記録されたログを見ると、pendingrunningのイベントが連続して出力されていることがわかります。

{
  "version": "0",
  "id": "27150cf2-ea29-408e-a7e9-fe4b4ae97779",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2017-06-26T01:09:47Z",
  "region": "us-west-2",
  "resources": [
    "arn:aws:ec2:us-west-2:123456789012:instance/i-01234567891234567"
  ],
  "detail": {
    "instance-id": "i-01234567891234567",
    "state": "pending"
  }
}
{
  "version": "0",
  "id": "a1badfe1-5cd2-45c4-a7b4-f14a9fbae7e8",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2017-06-26T01:10:02Z",
  "region": "us-west-2",
  "resources": [
    "arn:aws:ec2:us-west-2:123456789012:instance/i-01234567891234567"
  ],
  "detail": {
    "instance-id": "i-01234567891234567",
    "state": "running"
  }
}

かなり細かく出力されるので色々分析できそうです。

最後に

今回は全てのイベントを投げましたが、ログイン関連のイベントやEC2の状態変化だけ出力するということも可能です。
CloudWatch LogsでCloud Trailのログを取得して処理、という方法もありましたが、Kinesisを使用したほうがよりスマートに、よりお安く出来るかと思いますのでぜひご検討下さい。

S3に投げておいて、Athenaで分析とかもできそうですね!