💨

【初心者向け】Amazon CloudWatch Logs CloudTrail管理イベントをKMSで暗号化されたS3へ配信

2024/08/25に公開

はじめに

本ページは個人の勉強で使用することを目的に作成しておりますが、記載の誤り等が含まれる場合がございます。
最新の情報についてはAWS公式ドキュメントをご参照ください。

やること

  • CloudTrailからCloudWatch Logsに保存したイベントの内、イベント名:ConsoleLoginに一致するイベントをData Firehose経由でS3に配信する。


前提条件

  • CloudTrailの管理イベントの証跡を作成し、CloudWatch Logsに保存するよう設定していること。
  • KMSカスタマーマネージドキーを作成していること。

参考:

https://zenn.dev/smori/articles/4af0d0f9273438


1. Data Firehose用のIAMロール作成

  1. IAMロールを作成します。
  • IAMロール名:mori-role-firehose
  • 信頼されたエンティティタイプ:AWSのサービス
    • ユースケース:Kinesis Firehose
  • 許可ポリシー:mori-policy-firehose



mori-policy-firehose

{
    "Version": "2012-10-17",  
    "Statement":
    [    
        {      
            "Effect": "Allow",      
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:GetBucketLocation",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:ListBucketMultipartUploads",
                "s3:PutObject"
            ],      
            "Resource": [        
                "${保存先S3バケットARN}",
                "${保存先S3バケットARN}"		    
            ]    
        },        
        {
            "Effect": "Allow",
            "Action": [
                "kinesis:DescribeStream",
                "kinesis:GetShardIterator",
                "kinesis:GetRecords",
                "kinesis:ListShards"
            ],
            "${FirehoseストリームARN}"
        },
        {
           "Effect": "Allow",
           "Action": [
               "kms:Decrypt",
               "kms:GenerateDataKey"
           ],
           "Resource": [
               "${CloudWatch Logs暗号化に使用したKMS CMKのARN}"           
           ],
           "Condition": {
               "StringEquals": {
                   "kms:ViaService": "s3.region.amazonaws.com"
               },
               "StringLike": {
                   "kms:EncryptionContext:aws:s3:arn": "${保存先S3バケットARN}/${プレフィックス名}*"
               }
           }
        },
        {
           "Effect": "Allow",
           "Action": [
               "logs:PutLogEvents"
           ],
           "Resource": [
               "${CloudWatchログストリーム名}"
           ]
        }
    ]
}

※参考:https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/controlling-access.html#using-iam-s3

2. KMS CMKキーポリシーの修正

  1. KMSカスタマーマネージドキーのキーポリシーに以下のステートメントを追加します。
{
            "Sid": "Allow use of the key",
            "Effect": "Allow",
            "Principal": {
                "AWS": "${Data Firehose用のIAMロールARN}"
            },
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": "${KMS CMKのARN}"
}

参考:https://repost.aws/ja/knowledge-center/kinesis-data-firehose-s3-access-error

3. Data Firehoseの作成

  1. Amazon Data FirehoseコンソールからFirehoseストリームを作成をクリックします。
  2. Firehose ストリームを作成画面で以下の設定値を入力し、Firehose ストリームを作成をクリックします。
  • ソースと送信先を選択
    • ソース:Direct PUT
    • 送信先:Amazon S3
  • Firehoseストリーム名
    • Firehoseストリーム名:mori-stream-console_login
  • レコードを変換および転換 - オプション
    • AWS Lambda でソースレコードを変換:未選択
    • レコード形式を転換:未選択
    • Amazon CloudWatch Logs からソースレコードを解凍する - 新着:解凍をオンにする ※CloudWatch Logs のログは通常GZip 形式で圧縮される。2023/12のアップデート。


  • 送信先の設定
    • S3バケット:s3://mori-s3-cloudtrail-management-event
    • 改行の区切り文字:有効ではありません
    • 動的パーティショニング:有効ではありません
    • S3 バケットプレフィックス - オプション:consolelogin/!{timestamp:yyyy}/!{timestamp:MM}/!{timestamp:dd}/
    • S3 バケットエラー出力プレフィックス - オプション:consolelogin/!{firehose:error-output-type}/!{timestamp:yyyy}/!{timestamp:MM}/!{timestamp:dd}/
    • S3 バケットと S3 エラー出力プレフィックスタイムゾーン:Asia/Tokyo
    • バッファヒント、圧縮、ファイル拡張子、暗号化
      • バッファサイズ:1MiB ※最小
      • バッファ間隔:10秒
      • データレコードの圧縮:有効ではありません
      • ファイル拡張子フォーマット - オプション:.json
      • データレコードの暗号化:SSE-KMS を使用
      • 暗号化タイプ:カスタマーマネージドキーを使用
      • AWS KMS にあるカスタマーマネージドキー:/mori/kms ※S3バケット暗号化で使用したCMK
  • 詳細設定
    • サーバー側の暗号化:未選択
    • Amazon CloudWatch エラーのログ記録:有効
    • サービスアクセス:既存のIAMロールを選択
    • 既存のIAMロール:mori-role-firehose
  • タグ:未設定

4. CloudWatch Logs用のIAMロール作成

  1. IAMロールを作成します。
  • IAMロール名:mori-role-cloudwatch_logs
  • 信頼されたエンティティタイプ:カスタム信頼ポリシー

カスタム信頼ポリシー

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Principal": {
				"Service": "logs.${CloudWath Logsのあるリージョン名}.amazonaws.com"
			},
			"Action": "sts:AssumeRole",
			"Condition": {
				"StringLike": {
					"aws:SourceArn": "arn:aws:logs:${CloudWath Logsのあるリージョン名}:${アカウントID}:*"
				}
			}
		}
	]
}


  • 許可ポリシー:mori-policy-cloudwatch_logs
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": "firehose:PutRecord",
			"Resource": "${Data FirehoseストリームARN}"
		}
	]
}

5. サブスクリプションフィルタの作成

  1. CloudWatchコンソールからS3への配信対象のロググループをクリックします。
  2. アクション - サブスクリプションフィルタ - Create Amazon Data Firehose subscription filterの順にクリックします。

  1. Create Amazon Data Firehose subscription filter画面で以下の設定値を入力し、ストリーミングを開始をクリックする。
  • 送信先を選択
    • 送信先アカウント:現在のアカウント
    • Amazon Data Firehose stream:mori-stream-consolelogin
  • アクセス許可を付与する
    • 既存のロールを選択:mori-role-cloudwatch_logs
  • ログ形式とフィルターを設定
    • ログの形式:その他
    • サブスクリプションフィルターのパターン:{ $.eventName = "ConsoleLogin" }
    • サブスクリプションフィルター名:mori-filter-consolelogin

6. サブスクリプションフィルターを使用してData FirehoseでS3にログが格納されている事を確認

  1. AWSアカウントからサインアウトし、以下のURLからサインインします。
https://${アカウントエイリアス}.signin.aws.amazon.com/console?region=ap-northeast-1

ap-northeast-1:東京リージョン


  1. AWSアカウントからサインアウトし、以下のURLからサインインします。
https://keenova-aws.signin.aws.amazon.com/console?region=ap-northeast-3

ap-northeast-3:大阪リージョン


  1. S3コンソールから配信対象のバケットのconsolelogin/yyyy/mm/dd/配下にログが3つ配信されています。
    ※更新日時が最も古いものはサブスクリプションフィルタ作成時に自動配信されたヘルスチェックです。

  1. .json.gzをダウンロード・解凍して内容を確認します。サブスクリプションフィルターで、イベント名ConsoleLoginに一致するイベントのみ取得できています。
  • 東京リージョンのイベント
{
    "messageType": "DATA_MESSAGE",
    "owner": "484407776527",
    "logGroup": "/aws/cloudtrail/management-event",
    "logStream": "484407776527_CloudTrail_ap-northeast-1",
    "subscriptionFilters": [
        "mori-filter-consolelogin"
    ],
    "logEvents": [
        {
            "id": "38174239507788117679146500299632564763633296100326440960",
            "timestamp": 1711792102369,
            "message": "{\"eventVersion\":\"1.08\",\"userIdentity\":{\"type\":\"IAMUser\",\"principalId\":\"AIDAXBSHUCUH5OJYMN72K\",\"arn\":\"arn:aws:iam::${アカウントID}:user/${IAMユーザー名}\",\"accountId\":\"${アカウントID}\",\"userName\":\"${IAMユーザー名}\"},\"eventTime\":\"2024-03-30T09:45:53Z\",\"eventSource\":\"signin.amazonaws.com\",\"eventName\":\"ConsoleLogin\",\"awsRegion\":\"ap-northeast-1\",\"sourceIPAddress\":\"${IPアドレス}\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\"requestParameters\":null,\"responseElements\":{\"ConsoleLogin\":\"Success\"},\"additionalEventData\":{\"LoginTo\":\"https://ap-northeast-1.console.aws.amazon.com/console/home?hashArgs=%23&isauthcode=true&region=ap-northeast-1&state=hashArgsFromTB_ap-northeast-1_6b1e1551c87fb3b9\",\"MobileVersion\":\"No\",\"MFAIdentifier\":\"arn:aws:iam::${アカウントID}:mfa/${IAMユーザー名}\",\"MFAUsed\":\"Yes\"},\"eventID\":\"124ae584-ac31-4bfa-b396-7a1ba71efaed\",\"readOnly\":false,\"eventType\":\"AwsConsoleSignIn\",\"managementEvent\":true,\"recipientAccountId\":\"${アカウントID}\",\"eventCategory\":\"Management\",\"tlsDetails\":{\"tlsVersion\":\"TLSv1.3\",\"cipherSuite\":\"TLS_AES_128_GCM_SHA256\",\"clientProvidedHostHeader\":\"ap-northeast-1.signin.aws.amazon.com\"}}"
        }
    ]
}


  • 大阪リージョンのイベント
{
    "messageType": "DATA_MESSAGE",
    "owner": "484407776527",
    "logGroup": "/aws/cloudtrail/management-event",
    "logStream": "484407776527_CloudTrail_ap-northeast-1",
    "subscriptionFilters": [
        "mori-filter-consolelogin"
    ],
    "logEvents": [
        {
            "id": "38174267602802136672790270484762430800864040056526209027",
            "timestamp": 1711793362193,
            "message": "{\"eventVersion\":\"1.08\",\"userIdentity\":{\"type\":\"IAMUser\",\"principalId\":\"AIDAXBSHUCUH5OJYMN72K\",\"arn\":\"arn:aws:iam::${アカウントID}:user/${IAMユーザー名}\",\"accountId\":\"${アカウントID}\",\"userName\":\"${IAMユーザー名}\"},\"eventTime\":\"2024-03-30T10:09:04Z\",\"eventSource\":\"signin.amazonaws.com\",\"eventName\":\"ConsoleLogin\",\"awsRegion\":\"ap-northeast-3\",\"sourceIPAddress\":\"${IPアドレス}\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36\",\"requestParameters\":null,\"responseElements\":{\"ConsoleLogin\":\"Success\"},\"additionalEventData\":{\"LoginTo\":\"https://ap-northeast-3.console.aws.amazon.com/console/home?hashArgs=%23&isauthcode=true&region=ap-northeast-3&state=hashArgsFromTB_ap-northeast-3_f9b8281d5a72c339\",\"MobileVersion\":\"No\",\"MFAIdentifier\":\"arn:aws:iam::${アカウントID}:mfa/${IAMユーザー名}\",\"MFAUsed\":\"Yes\"},\"eventID\":\"3672028b-9023-426b-ac34-434ccaa1f6f5\",\"readOnly\":false,\"eventType\":\"AwsConsoleSignIn\",\"managementEvent\":true,\"recipientAccountId\":\"${アカウントID}\",\"eventCategory\":\"Management\",\"tlsDetails\":{\"tlsVersion\":\"TLSv1.3\",\"cipherSuite\":\"TLS_AES_128_GCM_SHA256\",\"clientProvidedHostHeader\":\"ap-northeast-3.signin.aws.amazon.com\"}}"
        }
    ]
}


※"message"の値が改行されておらず見にくい事が分かると思います。

おわりに

  • CloudTrailのフォーマットに成形する為にはLambda関数を使用する方法がありましたが、2024年の2月のアップデートで解凍された CloudWatch Logs のメッセージ抽出機能がサポートされるようにました。ただしメッセージの解凍を有効化する必要があり、そちらは従量課金となっているので注意が必要です。

https://docs.aws.amazon.com/firehose/latest/dev/writing-with-cloudwatch-logs.html#Message_extraction

参考

  • Amazon Data Firehoseを利用したサブスクリプションフィルタ

https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/SubscriptionFilters-AccountLevel.html#FirehoseExample-AccountLevel

  • DataFirehoseのポリシー

https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/controlling-access.html

  • S3バケットカスタムプレフィックス

https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/s3-prefixes.html

Discussion