ControlTower⑩LogArchiveアカウント内バケットへのCloudWatchLogs集約

## ControlTower関連記事まとめ
[・ControlTower①マルチアカウント環境をセットアップする](https://qiita.com/tonkatsu_oishi/items/6890ecc24c3b3bf8ee32)
[・ControlTower②環境確認](https://qiita.com/tonkatsu_oishi/items/b6dc3d548461d21b440d)
[・ControlTower③SSOの確認・アカウントの追加・削除](https://qiita.com/tonkatsu_oishi/items/281ad127699115ff54c3)
[・ControlTower④ガードレールの設定](https://qiita.com/tonkatsu_oishi/items/4e7be29ffa6553322c65)
[・ControlTower⑤Auditアカウントに作成されるリソースについて](https://qiita.com/tonkatsu_oishi/private/82811c94ebdc6fe509f2)
[・ControlTower⑥LogArchiveアカウントに作成されるリソースについて ](https://qiita.com/tonkatsu_oishi/private/5bb4fea771ec2a5e075b)
[・ControlTower⑦SecurityHubの有効化](https://qiita.com/tonkatsu_oishi/private/6fd0e2c73718057adcc9)
[・ControlTower⑧GuardDutyの有効化](https://qiita.com/tonkatsu_oishi/private/c28b6dd7652c8546d745)
[・ControlTower⑨CloudWatchクロスアカウントダッシュボードの設定](https://qiita.com/tonkatsu_oishi/private/a9a7c1becb8bfa832573)
・ControlTower⑩LogArchiveアカウント内バケットへのCloudWatchLogs集約←今ここ

### 現在の構成と設定内容の確認
前回までの記事で、ControlTower配下のSecurityOUに所属するAuditアカウントでSecurityHub・GuardDutyを集約し、CloudWatchのクロスアカウントダッシュボードを有効化する手順を確認しました。各アカウントの役割について、下記図に整理します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/cf209a64-e908-6c50-f3b7-cab8bcdc160f.png)

今回は、Sandboxアカウントの存在するEC2インスタンスのログファイルをLogArchiveアカウントのS3バケットに集約する手順を確認します。


EC2インスタンスへCloudWathAgentをインストールする際の手順については[こちら](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/install-CloudWatch-Agent-on-EC2-Instance.html)をご参照ください。EC2にCloudWatchの権限を付与したIAMロールをアタッチする必要がある点、EC2がプライベートサブネットに存在する場合は[VPCエンドポイント](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/cloudwatch-logs-and-interface-VPC.html)を作成する必要がある点にご留意ください。

メンバーアカウント・Auditアカウント・LogArchiveアカウント間でのサービス連携は下記の構成図のようになります。AuditアカウントのクロスアカウントダッシュボードからSandboxアカウントのEC2のメトリクス確認やアラーム設定を行います。LogArchiveアカウントのS3バケットにはEC2インスタンスから出力されるログファイルが集約されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/1dbba4e5-f256-440c-76ac-eef9a8961747.png)

## 設定手順の確認・事前準備
設定は[AWS公式ブログ](https://aws.amazon.com/jp/premiumsupport/knowledge-center/kinesis-firehose-cloudwatch-logs/)の手順を参考に行います。ControlTowerにより作成されたS3バケットには設定変更が許可されていません。そのため、CloudWatch Logsの集約を行う場合はLogArchiveアカウントにログ収集用のS3バケットを作成しましょう。S3バケット作成後、LogArchiveアカウント側でKinesisFirehoseの設定を行います。

今回はAWS CLIを使用して、コマンドラインからAWSリソースの作成を行う必要があります。そのための準備作業として、以下二点の設定を行いました。
①[IAMユーザーを作成し、アクセスキー・シークレットアクセスキーの取得](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_users_create.html)
②[AWSCLIのインストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-windows.html)

また、今回はLogArchiveアカウント、Sandboxアカウント両方のリソースをCLIから操作する必要があります。CLIから複数アカウントを操作する場合は、[プロファイルの設定](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-profiles.html)を行っておくと、作業がしやすくなります。

具体的な設定手順の説明に入る前に、設定内容を確認しておきましょう。下記は前のセクションの構成図からCloudWatchLogs→S3の連携部分を抜き出し詳細化した構成図となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/1ca720a4-d7da-8eb3-4dc5-af92fce966ec.png)


LogArchiveアカウントのKinesisFirehose・CloudWatchDestinationにはそれぞれIAMロールを紐づけ、リソースへの書き込みを許可しておきます。SandboxアカウントのCloudWatchLogsにサブスクリプションフィルタを設定し、LogArchiveアカウントのCloudWatchLogsDestinationあてにログイベントを連携するように設定します。

### LogArchiveアカウント側の作業
まずはKinesisFireHose用のIAMロールの設定から行います。構成図の赤枠で囲った部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/bea8cd70-1ceb-a4f0-933e-de666455d738.png)
IAMロールに設定する信頼ポリシー用Jsonを作成します。
下記内容でjsonファイルを作成し、保存しておきましょう。
```
【ファイル名：TrustPolicyForFirehose.json】
{
    "Statement": {
        "Effect": "Allow",
        "Principal": {
            "Service": "firehose.amazonaws.com"
        },
        "Action": "sts:AssumeRole",
        "Condition": {
            "StringEquals": {
                “sts:ExternalId”: “ログアーカイブアカウントのアカウントID"
            }
        }
    }
}
```
信頼ポリシー用のJsonが作成できたら、KinesisFirehose用のIAMロールの作成を行います。
コマンドプロンプトから下記コマンドを実行します。
「assume-role-policy-document file」で指定した場所は、適宜ファイルを作成した場所を指定するようにしてください。

```
aws --profile logarchive iam create-role ^
    --role-name IAMロール名^
    --assume-role-policy-document file://~/TrustPolicyForFirehose.json
```
今回はLogArchiveアカウントを「logarchie」、Sandboxアカウントを「sandbox」としてプロファイルを登録しています。プロファイルを設定せず手順を行う場合は、コマンドの「 --profile logarchive」部分を抜いて実行ください。IAMロール作成後、出力されるARNを控えておきます。


また、IAMロールに紐づけるためのポリシーの内容もjsonファイルで定義します。構成図の赤枠で囲った部分の設定です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/c3d65e97-8e9c-a970-793f-eeda4bc812f6.png)

下記内容でjsonファイルを作成し、保存します。

```
【ファイル名：PermissionsForFirehose.json】
{
  "Statement": [
    {
      "Effect":
    "Allow",
      "Action": [ 
          "s3:AbortMultipartUpload", 
          "s3:GetBucketLocation", 
          "s3:GetObject", 
          "s3:ListBucket", 
          "s3:ListBucketMultipartUploads", 
          "s3:PutObjectAcl",
          "s3:PutObject"
    ],
      "Resource": [ 
          “arn:aws:s3:::S3バケット名", 
          "arn:aws:s3::: S3バケット名/*" ]
    }
    ]
}

```
S3バケットへの読み込み・書き込みなどを許可するIAMポリシーです。「S3バケット名」と記載の項目にログを集約したいバケット名を記入してください。
jsonファイルが作成できたら、IAMポリシーの作成・IAMロールへの紐づけを行います。
```
aws --profile logarchive  iam put-role-policy --role-name IAMロール名--policy-name Permissions-Policy-For-Firehose --policy-document file://~/PermissionsForFirehose.json
```



IAMロールの作成が完了したら、LogArchiveアカウントで使用するKinesisの配信ストリームを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/5ca529bf-3f80-1a70-63e1-6cafe1749d5f.png)
構成図の赤枠で囲った部分です。
下記コマンドを実行し、配信ストリームを作成しましょう。
```
aws --profile logarchive firehose create-delivery-stream --delivery-stream-name “配信ストリーム名” --s3-destination-configuration RoleARN=“IAMロールのARN”,Prefix=“プレフィックス名”,CompressionFormat=“ZIP”,BucketARN=“配信先バケットのARN" --region ap-northeast-1
```
今回は東京リージョンで設定を行っているため、「--region」の引数には「ap-northeast-1」を指定しています。実際に設定を行う場合は、適宜使用しているリージョン名に読み替えてコマンドを実行してください。
コマンドを実行後出力される配信ストリームのARNを控えて置きます。
また、下記コマンドを実行し、「DeliveryStreamStatus」が「ACTIVE」となることを確認します。
```
aws --profile logarchive firehose describe-delivery-stream --delivery-stream-name “配信先ストリーム名" --region ap-northeast-1
```
Kinesisの配信ストリーム作成が完了したら、CloudWatchLogsDestinationの設定を行います。まずはCloudWatchLogsDestinationに紐づけるIAMロールを作成しましょう。構成図の赤枠で囲った部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/f1408fc9-4222-fee0-8bd7-2da45b711b47.png)
IAMロールに紐づける信頼ポリシー用のjsonファイルを作成します。
下記内容でjsonファイルを作成し、保存します。
```
【ファイル名：TrustPolicyForCWL.json】
{
  "Statement": {
    "Effect": "Allow",
    "Principal": {
  "Service": "logs.ap-northeast-1.amazonaws.com"
},
    "Action": "sts:AssumeRole"
  }
}
```
「service」に指定したリージョン名は適宜読み替えてご使用ください。
信頼ポリシー用のJSONが作成できたら、コマンドを実行しIAMロールを作成します。
```
aws --profile logarchive iam create-role ^
    --role-name IAMロール名^
    --assume-role-policy-document file://~/TrustPolicyForCWL.json
```


また、IAMロールへ紐づけるIAMポリシーを作成します。作成するのは、Firehoseへの書き込みを許可するポリシーです。構成図の赤枠で囲った部分の作業となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/995020d2-ebc4-8e45-5bc7-9c4b7d4e83e9.png)
下記内容でJSONを作成し、保存します。
```
【ファイル名：PermissionsForCWL.json】
{
    "Statement":[
      {
        "Effect":"Allow",
        "Action":["firehose:*"],
       
    “Resource”:[“arn:aws:firehose:ap-northeast-1:LogArchiveアカウントのアカウントID:*"]
      },
      {
        "Effect":"Allow",
        "Action":["iam:PassRole"],
       
    “Resource”:[“arn:aws:iam::LogArchiveアカウントのアカウントID:role/CWLtoKinesisFirehoseRole"]
      }
    ]
}
```
リージョン・アカウントIDは適宜読み替えてご利用ください。
ここまで完了したら、IAMロールへIAMポリシーの紐づけを行います。

```
aws --profile logarchive iam put-role-policy --role-name IAMロール名--policy-name Permissions-Policy-For-CWL --policy-document file://~/PermissionsForCWL.json
```
これで、CloudWatchDestinationに紐づけるIAMロールの作成が完了しました。



次に、CloudWatchLogsDestinationの作成を行います。構成図の赤枠で囲った部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/ffb8eaac-7d9a-c1d6-2af7-d18e64c4d9e5.png)

下記コマンドを実行し、CloudWatchLogsDestinationを作成できます。
```
aws --profile logarchive logs put-destination --destination-name “CloudWatchLogsDestinationの名前” --target-arn “KinesisFirehoseストリームのARN” --role-arn “作成したCloudWatchLogs用IAMロールの名前" --region ap-northeast-1
```
また、CloudWatchLogsDestinationに紐づけるアクセスポリシー用のJSONを作成します。
Sandboxアカウントからの書き込みを許可するアクセスポリシーを作成し、CloudWatchLogsDestinationに関連付けることでSandboxアカウントからのログの連携が可能となります。構成図の赤枠で囲った部分の作業です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/ba2552fc-2d04-dae7-a373-5a576bf44393.png)
アクセスポリシーのJSONは下記内容で作成します。
```
【ファイル名：AccessPolicy.json】
{
  "Version" : "2012-10-17",
  "Statement" : [
    {
      "Sid" : "",
            "Effect" : "Allow",
            "Principal" : {
       “AWS” : “SandboxアカウントのアカウントＩＤ"
    },
    "Action" : "logs:PutSubscriptionFilter",
    “Resource” : “作成したKinesisFirehose配信ストリームのARN"
    }
  ]
}
```
アカウントIDには、ログ配信元のアカウントIDを指定します。また、Resourceに指定したARNには、KinesisFirehose配信ストリームのARNを指定します。
jsonファイルを作成したら、下記コマンドにてCloudWatchLogsDestinationへのアクセスポリシー紐づけを行います。
```
aws --profile logarchive logs put-destination-policy --destination-name " CloudWatchLogsDestinationの名前" --access-policy file://~/AccessPolicy.json --region ap-northeast-1
```
CloudWatchLogsDestinationの状態確認を行います。「AccessPolicy」のPrincipalで書き込み元のAWSアカウントIDが許可されていることをご確認ください。
```
aws --profile logarchive logs describe-destinations --region ap-northeast-1
```
これで、LogArchiveアカウント側での作業は完了です。

### SandBoxアカウント（ログ配信元）の作業
ここまでの手順が完了したら、Sandboxアカウント側でCloudWatchのサブスクリプションフィルタを作成します。構成図の赤枠で囲った部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2237429/f3ab7131-9c07-f48e-90f3-30504b5126eb.png)
下記コマンドにて、CloudWatchLogsのサブスクリプションフィルタの作成を行います。
```
aws  --profile sandbox logs put-subscription-filter --log-group-name “ロググループ名” --filter-name “サブスクリプションフィルタ名" --filter-pattern "" --destination-arn ^
“ ログアーカイブアカウントにて作成したCloudWatchLogsDestinationのARN " --region ap-northeast-1
```
これで、S3への配信設定が完了しました。
下記コマンドを実行すると、CloudWatchLogsのロググループにログイベントを出力することができます。ログイベントを出力し、S3バケットにログが配信されていることを確認しましょう。

```
aws logs put-log-events --log-group-name "ロググループ名" --log-events timestamp=1461997171845,message='Hello CloudWatch'
```
ここまでお読みくださりありがとうございました。次回はControlTower環境での通知の集約について書こうと思います。