CloudWatch LogsデータをKinesis Data Streams を使用してクロスアカウント共有

# 内容
アカウント内のCloudWatch Logsのデータを別アカウントのKinesis Data Streamsを使用して共有します。下記公式マニュアル中に手順がありますが、文字だけだと分かり辛い箇所があるため、図解化しながらまとめました。下記構成図中のステップ●や●～●などの番号はマニュアル中の手順の番号と同様となります。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/CrossAccountSubscriptions-Kinesis.html

![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/8ce0ba6f-ecc9-d670-0963-f5c8715c075e.png)

# 手順

まずは下記青枠の箇所を実施します。

![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/a0621bc8-7be7-0e23-512e-ac8900cf1811.png)

## 送信ストリームの作成・確認

kinesisデータストリームで送信先ストリームを作成します。
```shell
aws kinesis create-stream --stream-name "RecipientStream" --shard-count 1
```

ストリームがアクティブになるのを待ちます。下記のStreamStatusがActiveになればOKです。
```shell
aws kinesis describe-stream --stream-name "RecipientStream"
{
  "StreamDescription": {
    "StreamStatus": "ACTIVE",
    "StreamName": "RecipientStream",
    "StreamARN": "arn:aws:kinesis:us-east-1:999999999999:stream/RecipientStream",
    "Shards": [
      {
        "ShardId": "shardId-000000000000",
        "HashKeyRange": {
          "EndingHashKey": "34028236692093846346337460743176EXAMPLE",
          "StartingHashKey": "0"
        },
        "SequenceNumberRange": {
          "StartingSequenceNumber": "4955113521868881845667950383198145878459135270218EXAMPLE"
        }
      }
    ]
  }
}
```

## CloudWatch Logsに付与するIAMロールの作成
ここからマニュアルだと結構色々書いていますが、IAMロールを作成しているだけです。マニュアル中に「このポリシーの作成にはテキストエディタを使用します。IAM コンソールは使用しないでください。」と記載がありますのでマニュアル通りコマンドで実施していきます。

```shell:~/TrustPolicyForCWL.json
{
    "Statement": {
        "Effect": "Allow",
        "Principal": {
            "Service": "logs.amazonaws.com"
        },
        "Condition": {
            "StringLike": {
                "aws:SourceArn": [
                    "arn:aws:logs:region:sourceAccountId:*",
                    "arn:aws:logs:region:recipientAccountId:*"
                ]
            }
        },
        "Action": "sts:AssumeRole"
    }
}
```
上記のファイル作成後、下記コマンドを実行します。これにより、`CWLtoKinesisRole`というIAMロールが作成されます。信頼ポリシーは`TrustPolicyForCWL.json`の内容が設定されます。

```shell
aws iam create-role \
--role-name CWLtoKinesisRole \
--assume-role-policy-document file://~/TrustPolicyForCWL.json
```

```shell:~/PermissionsForCWL.json
{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "kinesis:PutRecord",
      "Resource": "arn:aws:kinesis:region:999999999999:stream/RecipientStream"
    }
  ]
}
```

上記のファイル作成後、下記コマンドを実行します。これにより先ほど作成したIAMロールに`PermissionsForCWL.json`の内容の許可ポリシーが設定されます。

```shell
aws iam put-role-policy \
    --role-name CWLtoKinesisRole \
    --policy-name Permissions-Policy-For-CWL \
    --policy-document file://~/PermissionsForCWL.json
```

IAMロールの作成が完了しました。ここからは下記2つの青枠の箇所を設定していきます。

![スライド3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/e4cbb5ff-be40-52fb-21c4-4f3ae47b11d2.png)

## CloudWatch送信先の作成

CloudWatch Destination(送信先)というコンポーネントを作成します。ここで受信したものをkinesisの送信ストリームに送信します。なおIAMロールは先ほど作成したものを紐づけます。

```shell
aws logs put-destination \
    --destination-name "testDestination" \
    --target-arn "arn:aws:kinesis:region:999999999999:stream/RecipientStream" \
    --role-arn "arn:aws:iam::999999999999:role/CWLtoKinesisRole"
```
## リソースポリシーの作成と紐づけ

```shell:~/AccessPolicy.json
{
  "Version" : "2012-10-17",
  "Statement" : [
    {
      "Sid" : "",
      "Effect" : "Allow",
      "Principal" : {
        "AWS" : "111111111111"
      },
      "Action" : "logs:PutSubscriptionFilter",
      "Resource" : "arn:aws:logs:region:999999999999:destination:testDestination"
    }
  ]
}
```

上記のファイル作成後、下記コマンドを実行します。これにより先ほど作成したCloudWatch Destinationにリソースポリシーとして`AccessPolicy.json`の内容の許可ポリシーが設定されます。

```shell
aws logs put-destination-policy \
    --destination-name "testDestination" \
    --access-policy file://~/AccessPolicy.json
```

ここまでで送信の準備が完了しました。ここから下記青枠の箇所を設定し、ログを送信します。

![スライド4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/bf9d125b-d76a-4821-403a-9357760c91de.png)

## サブスクリプションフィルターの作成
この操作のみアカウント(111111111111)の方で実施します。
サブスクリプションフィルターの設定で送信元ロググループ、送信先ストリーム名、フィルターパターン、CloudWatch送信先を指定します。フィルターする必要がない場合は`--filter-pattern ""`を指定します。

```shell
aws logs put-subscription-filter \
    --log-group-name "CloudTrail/logs" \
    --filter-name "RecipientStream" \
    --filter-pattern "{$.userIdentity.type = Root}" \
    --destination-arn "arn:aws:logs:region:999999999999:destination:testDestination"
```

## ログイベントを検証
送信ストリーム内にログが転送されていることを確認します。


```shell
aws kinesis get-shard-iterator \
      --stream-name RecipientStream \
      --shard-id shardId-000000000000 \
      --shard-iterator-type TRIM_HORIZON

{
    "ShardIterator":
    "AAAAAAAAAAFGU/kLvNggvndHq2UIFOw5PZc6F01s3e3afsSscRM70JSbjIefg2ub07nk1y6CDxYR1UoGHJNP4m4NFUetzfL+wev+e2P4djJg4L9wmXKvQYoE+rMUiFq+p4Cn3IgvqOb5dRA0yybNdRcdzvnC35KQANoHzzahKdRGb9v4scv+3vaq+f+OIK8zM5My8ID+g6rMo7UKWeI4+IWiKEXAMPLE"
}

aws kinesis get-records \
      --limit 10 \
      --shard-iterator
      "AAAAAAAAAAFGU/kLvNggvndHq2UIFOw5PZc6F01s3e3afsSscRM70JSbjIefg2ub07nk1y6CDxYR1UoGHJNP4m4NFUetzfL+wev+e2P4djJg4L9wmXKvQYoE+rMUiFq+p4Cn3IgvqOb5dRA0yybNdRcdzvnC35KQANoHzzahKdRGb9v4scv+3vaq+f+OIK8zM5My8ID+g6rMo7UKWeI4+IWiKEXAMPLE"
      ```