たそらぼ

日頃思ったこととかメモとか。

CloudWatchLogsからクロスアカウントでS3にエクスポートする

別のアカウントのCloudWatch Logsに格納されたログデータを、別のアカウントのS3に持ってくる場合です。
自分のアカウント内の記事はよくありますが、クロスアカウントでやってみた報告がないので書きました。

やりたいこと

以下のような構成を実現したいです。

f:id:tasotasoso:20200418182126p:plain:w500
やりたいこと

CloudWatch Logsの中身を取り出す方法

AWSサービスを使ってCloudWatch LogsからS3に中身をエクスポート方法は、調べた限りだと以下の2つがあります。

ちなみに、3rdパーティのログコレクタまで視野に入れているなら、fluentdなどを使って取り出すことも可能です(この場合は、実質的にはSDKを使っている)。
今回は、「エクスポート機能を使う方法」を説明します。

サブスクリプションフィルタを使った方法はとても便利ですが、サブスクリプションフィルタがロググループに1つしかつけられないため、すでに使われている場合は実現できません。その場合は、簡単に実現できるエクスポート機能を使う方法が有力な候補になります。


エクスポート機能を使う

公式の方法がドキュメントにあるため、こちらを参考に行います。
docs.aws.amazon.com
バケットポリシーなど、私の記載が間違っているかもしれないので、こっちも見てからやって見てくださいね

コンソールで行う方法を説明します。


1. エクスポート先のS3に権限を設定する。
まず、エクスポート先にS3バケットを作成します。今回は東京リージョンにmy-exported-logstというバケットを作り、random-stringという階層にエクスポートするとします。

次に、このバケットに、バケットポリシーをつけます。アカウントIDが111111111111のアカウントに所属するCWLExportUserというユーザーを使ってエクスポートするとします。

バケットポリシーは、以下のようになります。

#Refer https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/S3ExportTasksConsole.html

{
    "Version": "2012-10-17",
    "Statement": [
      {
          "Action": "s3:GetBucketAcl",
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::my-exported-logs",
          "Principal": { "Service": "logs.ap-northeast-1.amazonaws.com" }
      },
      {
          "Action": "s3:PutObject" ,
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::my-exported-logs/random-string/*",
          "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } },
          "Principal": { "Service": "logs.ap-northeast-1..amazonaws.com" }
      },
      {
          "Action": "s3:PutObject" ,
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::my-exported-logs/random-string/*",
          "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } },
          "Principal": { "AWS": "arn:aws:iam::111111111111:user/CWLExportUser" }
      }
    ]
}

CloudWatch LogsからGetBucketAclとPutObjectする許可に加え、CWLExportUserからもPutObjectする権限をつけます。もしユーザーではなくロールで行う場合は、3つ目のJSONのConditionキーのバリューをロールのarnに変えるとよいでしょう。


2. エクスポートする
続いて、エクスポートする側のアカウントからエクスポート操作を行います。
この時、CloudWatch LogsとS3にフルアクセスのついたユーザーでログインします。この権限がないとエクスポート時に弾かれてしまいます。

CloudWatch Logsの画面に入り、エクスポートするロググループを選択して[アクション]から[データを Amazon S3 にエクスポートする]を押すと、以下のポップアップが表示されます。


f:id:tasotasoso:20200418182218p:plain:w500
クロスアカウントでのエクスポート設定

以下のように設定を入力します。

  • ①で「別のアカウント」を選択する
  • ②でmy-exported-logsを入力する
  • ③でrandom-stringを入力する

[データのエクスポート]を押すことで、エクスポートが実行できます。


問題がある場合は、[データのエクスポート]押下時にエラーが表示されます。
もし公式ドキュメントも見て、バケットポリシーやロールにつけたポリシーなども完璧に合っているなら、IP制限などがかかっていないか確認すると良いです。

参考・関連文献

fluentdでCloudWatch Logsの中身を取り出す。
github.com

Lambda + Step Functionsでエクスポートする。
dev.classmethod.jp
qiita.com