最近ランニングを始めたCI部1課の山﨑です。
今回はCloudWatch LogsのログをKinesis Data Firehose経由でS3バケットに転送してみました。
- はじめに
- ポリシー設計について
- アカウントB の実装
- アカウントA の実装
- ログ配信の確認
- まとめ
はじめに
最近はAWSアカウントを単一アカウントで利用するのではなく、マルチアカウントで利用することが増えてきたように感じています。そこで今回はアカウントA からアカウントB に対してログのバックアップを出力し、ログ自体はアカウントB で長期保存するというログ運用を想定し、アカウントA で出力したCloudWatch LogsのログをKinesis Data Firehose 経由でアカウントB のS3バケットに転送する方法をご紹介します。
基本的には以下のリンクに従って実装すれば上手くいくのですが、イマイチ何をしているのかをイメージしずらいため今回は図を利用して実装イメージを可視化させながらご紹介します。
ポリシー設計について
以降の実装手順の中には IAMロールの設計、リソースベースのポリシー設計が含まれています。それぞれのポリシー設計は以下のブログに記載の設計ポイントを沿って考えておりますのでこちらのページを別タブで開いた上で本ブログをお読み頂くとよりイメージしやすいと思います。
以下、重要なポイントのみブログより一部抜粋します。
5Wで要件を整理する
以下の5Wで要件を整理することで定義すべきポリシーが可視化されます。
- Who(何が)
- ポリシーの適用主体
- Where(何に対して)
- Resource要素
- When(どんな条件下で)
- Condition要素
- What(どんな操作を)
- Action要素
- Want(どうしたい)
- Effect要素
ポリシー要件の早見表
ポリシーの関連付け対象 | Who(何が) | Where(何に対して) | When(どんな条件下で) | What(どんな操作を) | Want(どうしたい) |
---|---|---|---|---|---|
Organizations SCP | ・メンバーアカウント ・OU内の全アカウント |
要定義 | 要定義 | 要定義 | 要定義(Allow or Deny) |
リソースベースのポリシー | 要定義 | ポリシーを適用したAWSリソース ※AWSリソースを絞ることは可 |
要定義 | 要定義 | 要定義(Allow or Deny) |
IAMユーザー | IAMユーザー | 要定義 | 要定義 | 要定義 | 要定義(Allow or Deny) |
IAMロール | 要定義 | 要定義 | 要定義 | 要定義 | 要定義(Allow or Deny) |
アカウントB の実装
Step1. S3バケットの作成
まずはアカウントA から転送されてくるログを保管するS3バケットを任意の名前で作成してください。実際にS3バケットに書き込むのは Kinesis Data Firehose のストリームであるため、バケットポリシーでKinesis Data Firehose からの書き込みを許可します。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowWritingFromKinesisDataFirehose", "Effect": "Allow", "Principal": { "Service": "firehose.amazonaws.com" }, "Action": "s3:PutObject", "Resource": [ "arn:aws:s3:::バケット名", "arn:aws:s3:::バケット名/*" ], "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } } } ] }
Step2. Kinesis Data Firehose に関連付けるIAMロールの作成
Kinesis Data Firehose に関連付けるIAMロールを作成します。Kinesis Data Firehose は S3 にログを書き込む必要があるためIAMロールにはS3バケットへの書き込みを許可するバケットポリシーを割り当てます。
# IAMロール作成 aws iam create-role \ --role-name FirehosRoleToS3 \ --assume-role-policy-document file://~/TrustPolicyForFirehose.json # IAMポリシー作成 aws iam create-policy \ --policy-name Permissions-Policy-For-Firehose \ --policy-document file://~/PermissionsForFirehose.json # IAMポリシーを割り当て aws iam attach-role-policy \ --policy-arn IAMポリシーのARN \ --role-name FirehosRoleToS3
TrustPolicyForFirehose.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "firehose.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "アカウントBのAccount ID" } } } ] }
PermissionsForFirehose.json
{ "Statement": [ { "Effect": "Allow", "Action": [ "s3:AbortMultipartUpload", "s3:GetBucketLocation", "s3:GetObject", "s3:ListBucket", "s3:ListBucketMultipartUploads", "s3:PutObjectAcl", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::バケット名", "arn:aws:s3:::バケット名/*" ] } ] }
Step3. Kinesis Data Firehose の配信ストリームの作成
Kinesis Data Firehose がログデータを受け取ってS3へと配信する配信ストリームを作成します。RoleARNはStep2. で作成したIAMロールのARNを、BucketARNにはStep1. で作成したS3バケットのARNを、--s3-destination-configuration のプロパティは必要に応じて追加してください。
aws firehose create-delivery-stream \ --delivery-stream-name 'delivery-test-stream' \ --s3-destination-configuration \ '{"RoleARN": "arn:aws:iam::アカウントBのAccount ID:role/FirehosRoleToS3", "BucketARN": "arn:aws:s3:::バケット名", "Prefix": "プレフィックス"}'
Step4. CloudWatch Logs destination の作成
アカウントA で出力したCloudWatch LogsのログをKinesis Data Firehose 経由でアカウントB のS3バケットに転送する場合、CloudWatch Logs から Kinesis Data Firehose に直接データが転送されるわけではありません。Kinesis Data Firehose の前段でCloudWatch Logs destination と呼ばれる転送先に先にログデータが集約され、この転送先からKinesis Data Firehose にログデータが転送されます。つまり、以下の経路でアカウントB のS3までログデータは転送されます。
CloudWatch Logs(アカウントA) → CloudWatch Logs destination(アカウントB) → Kinesis Data Firehose(アカウントB) → S3バケット(アカウントB)
上記の経路よりCloudWatch Logs destination は Kinesis Data Firehose にログデータを転送するので、Kinesis Data Firehose に対するアクセス許可を付与する必要があり、これはIAMロールを関連付けることで実現することができます。
まずはIAMロールを作成します。
# IAMロール作成 aws iam create-role \ --role-name CWLtoKinesisFirehoseRole \ --assume-role-policy-document file://~/TrustPolicyForCWL.json # IAMポリシー作成 aws iam create-policy \ --policy-name CWL-Policy-For-Kinesis \ --policy-document file://~/PermissionsForCWL.json # IAMポリシーを割り当て aws iam attach-role-policy \ --policy-arn IAMポリシーのARN \ --role-name CWLtoKinesisFirehoseRole
TrustPolicyForCWL.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "logs.ap-northeast-1.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
PermissionsForCWL.json
{ "Statement": [ { "Effect": "Allow", "Action": [ "firehose:*" ], "Resource": [ "arn:aws:firehose:ap-northeast-1:アカウントBのAccount ID:*" ] }, { "Effect": "Allow", "Action": [ "iam:PassRole" ], "Resource": [ "arn:aws:iam::アカウントBのAccount ID:role/CWLtoKinesisFirehoseRole" ] } ] }
IAMロールが作成できたらCloudWatch Logs destination を作成します。
aws logs put-destination \ --destination-name "delivery-test-destination" \ --target-arn "arn:aws:firehose:ap-northeast-1:アカウントBのAccount ID:deliverystream/delivery-test-stream" \ --role-arn "arn:aws:iam::アカウントBのAccount ID:role/CWLtoKinesisFirehoseRole"
Step5. CloudWatch Logs destination にリソースベースのポリシーを割り当てる
本StepではアカウントA がアカウントB のCloudWatch Logs destination にサブスクリプションフィルター経由でログデータを転送する権限をリソースベースのポリシーで割り当てます。
aws logs put-destination-policy \ --destination-name "delivery-test-destination" \ --access-policy file://~/AccessPolicy.json
AccessPolicy.json
{ "Version" : "2012-10-17", "Statement" : [ { "Sid" : "", "Effect" : "Allow", "Principal" : { "AWS" : "アカウントA のAccount ID" }, "Action" : "logs:PutSubscriptionFilter", "Resource" : "arn:aws:logs:ap-northeast-1:アカウントBのAccount ID:destination:delivery-test-destination" } ] }
アカウントA の実装
Step6. サブスクリプションフィルターの作成
アカウントA で転送したいCloudWatch Logs のロググループに対してサブスクリプションフィルターを作成します。
--filter-pattern プロパティで転送するログデータをフィルタリングすることが可能ですが、今回はフィルタリングなしで設定します。
aws logs put-subscription-filter \ --log-group-name "delivery-test" \ --filter-name "delivery-test-filter" \ --filter-pattern "" \ --destination-arn "arn:aws:logs:ap-northeast-1:アカウントBのAccount ID:destination:delivery-test-destination"
ログ配信の確認
S3バケットを確かめてみると無事にログが配信されていました。
まとめ
今回はCloudWatch LogsのログをKinesis Data Firehose経由でS3バケットに転送してみました。マルチアカウントになるとアイデンティティベースのポリシーやリソースベースのポリシーを用いて、アカウントをまたぐアクセス制御を行う必要があるため理解が難しくなります。面倒ではありますが、実装イメージを図で表現して整理すると結果的に短時間で理解が進みますので是非お試しください。
また、AWSで取り扱われるポリシーについては以下のブログで整理しておりますのでお手すきの際にご覧ください。
山﨑 翔平 (Shohei Yamasaki) 記事一覧はコチラ
カスタマーサクセス部所属。2019年12月にインフラ未経験で入社し、AWSエンジニアとしてのキャリアを始める。2023 Japan AWS Ambassadors/2023-2024 Japan AWS Top Engineers