各サービスから S3 へのログ出力が失敗している状態を検知してアラートを出してみた
こんにちは、大前です。
VPC フローログや AWS WAF など、いくつかのサービスのログを S3 に配信する場合、delivery.logs.amazonaws.com を介してログ配信が行われます。具体的にどのサービスが S3 に直接ログを配信するのかは下記ドキュメントを参照ください。
参考 : 特定の AWS のサービスからのログの記録を有効にする - Amazon CloudWatch Logs
今回は delivery.logs.amazonaws.com を介して配信されるログに対して、例えば意図しないバケットポリシーの変更によってログが出力されない状態になっている場合、それの検知とアラート発砲をやってみました。
先にまとめ
- delivery.logs.amazonaws.com が行うログ配信イベントは CloudTrail データイベントもしくは S3 アクセスログで確認することができる
- アラート発砲まで行いたい場合は、CloudWatch Logs 連携ができる CloudTrail データイベントの方が設定が容易
やってみた
ログの設定
今回は VPC フローログを使って試してみます。
まず、任意の VPC に対してフローログを設定します。送信先に S3 を指定し、すぐにログを確認生成するために最大集約間隔は 1分にしました。それ以外の項目はデフォルトです。
フローログが作成されたら、送信先として指定した S3 のバケットポリシーが以下の様に更新されていることも確認します。
{ "Version": "2012-10-17", "Id": "AWSLogDeliveryWrite20150319", "Statement": [ { "Sid": "AWSLogDeliveryWrite", "Effect": "Allow", "Principal": { "Service": "delivery.logs.amazonaws.com" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::<バケット名>/AWSLogs/<アカウントID>/*", "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control", "aws:SourceAccount": "<アカウントID>" }, "ArnLike": { "aws:SourceArn": "arn:aws:logs:ap-northeast-1:<アカウントID>:*" } } }, { "Sid": "AWSLogDeliveryAclCheck", "Effect": "Allow", "Principal": { "Service": "delivery.logs.amazonaws.com" }, "Action": "s3:GetBucketAcl", "Resource": "arn:aws:s3:::<バケット名>", "Condition": { "StringEquals": { "aws:SourceAccount": "<アカウントID>" }, "ArnLike": { "aws:SourceArn": "arn:aws:logs:ap-northeast-1:<アカウントID>:*" } } } ] }
また、VPC フローログの保存先 S3 バケットに対し、S3 アクセスログの設定も行います。
S3 が複数登場して紛らわしいので、ここまでの設定を図に起こしておきます。
CloudTrail データイベントの設定
続いて、CloudTrail データイベントの設定をします。
証跡の作成から、新規証跡を設定します。
記録するイベントは "データイベント" のみを選択
「データイベントタイプ」で "S3" を選択し、以下の様に設定。今回は検証のために、必要なログのみ記録する様イベントセレクターを設定していますが、用途に合わせて調整してください。
- ログセレクターテンプレート ... カスタム
- 高度なイベントセレクター
- resources.ARN ... 次で始まる :
- eventName ... 次と等しい : PutObject
- resources.ARN ... 次で始まる :
ここまでの設定を改めて図にしておきます。
ログを見てみる
VPC フローログが発生する様なアクションを行い、VPC フローログが出力されていることを確認します。
その後、CloudTrail データイベントの出力先 S3 にもログが出力されていることが確認できます。
出力されている CloudTrail データイベントのログを見てみると、invokedBy が delivery.logs.amazonaws.com である PutObject イベントが記録されていることがわかります。requestParameters の中身を見ても、VPC フローログの出力に関するイベントであることが読み取れます。
{ "eventVersion": "1.08", "userIdentity": { "type": "AWSService", "invokedBy": "delivery.logs.amazonaws.com" }, "eventTime": "2022-04-01T08:07:42Z", "eventSource": "s3.amazonaws.com", "eventName": "PutObject", "awsRegion": "ap-northeast-1", "sourceIPAddress": "delivery.logs.amazonaws.com", "userAgent": "delivery.logs.amazonaws.com", "requestParameters": { "bucketName": "vpc-flowlog-111111111111", "Host": "vpc-flowlog-111111111111.s3.ap-northeast-1.amazonaws.com", "x-amz-acl": "bucket-owner-full-control", "key": "AWSLogs/111111111111/vpcflowlogs/ap-northeast-1/2022/04/01/111111111111_vpcflowlogs_ap-northeast-1_fl-0f18460ce9bf38313_20220401T0800Z_4ed8338a.log.gz" }, (省略) }
S3 アクセスログについても確認してみます。下記は出力された S3 アクセスログを Athena でクエリ *1 し一部のカラムだけ出力した結果ですが、requester に svc:delivery.logs.amazonaws.com とあり、S3 アクセスログでも delivery.logs.amazonaws.com からのログ出力を記録できていることが確認できます。
bucket_name | requestdatetime | requester | operation | request_uri | httpstatus | errorcode | endpoint |
---|---|---|---|---|---|---|---|
vpc-flowlog-111111111111 | 01/Apr/2022:07:37:43 +0000 | svc:delivery.logs.amazonaws.com | REST.PUT.OBJECT | "PUT /AWSLogs/111111111111/vpcflowlogs/ap-northeast-1/2022/04/01/111111111111_vpcflowlogs_ap-northeast-1_fl-0f18460ce9bf38313_20220401T0735Z_84cc7f1a.log.gz HTTP/1.1" | 200 | - | vpc-flowlog-111111111111.s3.ap-northeast-1.amazonaws.com |
出力時のログ
delivery.logs.amazonaws.com からのログ配信アクションが CloudTrail データイベントと S3 アクセスログで記録できることがわかったため失敗時のログについても確認しておきます。
VPC フローログの出力先バケットのポリシーを削除し、delivery.logs.amazonaws.com からの VPC フローログ出力が失敗する様な状態にします。
この状態で、再度 VPC フローログが生成される様なアクションを実施し、少し待機します。(今回は EC2 から ping を実行)
当然、VPC フローログは増えませんが、CloudTrail データイベントと S3 アクセスログが新しく出力されていることが確認できると思います。
CloudTrail データイベントでは以下の様なイベントが確認できます。errorCode と errorMessage に AccessDenied の旨のメッセージが確認でき、delivery.logs.amazonaws.com からのログ配信に失敗していることが読み取れます。
{ "eventVersion": "1.08", "userIdentity": { "type": "AWSService", "invokedBy": "delivery.logs.amazonaws.com" }, "eventTime": "2022-04-01T08:42:42Z", "eventSource": "s3.amazonaws.com", "eventName": "PutObject", "awsRegion": "ap-northeast-1", "sourceIPAddress": "delivery.logs.amazonaws.com", "userAgent": "delivery.logs.amazonaws.com", "errorCode": "AccessDenied", "errorMessage": "Access Denied", "requestParameters": { "bucketName": "vpc-flowlog-111111111111", "Host": "vpc-flowlog-111111111111.s3.ap-northeast-1.amazonaws.com", "x-amz-acl": "bucket-owner-full-control", "key": "AWSLogs/111111111111/vpcflowlogs/ap-northeast-1/2022/04/01/111111111111_vpcflowlogs_ap-northeast-1_fl-0f18460ce9bf38313_20220401T0835Z_0aa2c88b.log.gz" }, (省略) }
S3 アクセスログでは以下の様なレコードが確認できます。httpstatus が 403 で、errorcode に "AccessDenied" と記録されています。
bucket_name | requestdatetime | requester | operation | request_uri | httpstatus | errorcode | endpoint |
---|---|---|---|---|---|---|---|
vpc-flowlog-111111111111 | 01/Apr/2022:08:42:43 +0000 | svc:delivery.logs.amazonaws.com | REST.PUT.OBJECT | "PUT /AWSLogs/111111111111/vpcflowlogs/ap-northeast-1/2022/04/01/111111111111-northeast-1_fl-0f18460ce9bf38313_20220401T0840Z_6ae40c86.log.gz HTTP/1.1" | 403 | AccessDenied | vpc-flowlog-111111111111.s3.ap-northeast-1.amazonaws.com |
delivery.logs.amazonaws.com からのログ出力失敗を検知してみる
CloudTrail は CloudWatch Logs と連携してログのモニタリングを行うことができるため、これを利用して delivery.logs.amazonaws.com からのログ出力に失敗したらアラートを出してみたいとおもいます。S3 アクセスログについては、S3 に出力されたアクセスログの中身を都度チェックする仕組みが必要になりそうなため、別途試してみたいと思います。
作成した CloudTrail データイベントの「CloudWatch Logs」オプションを編集し、CloudWatch Logs にイベントが出力される様にします。ロググループ名や IAM ロール名はよしなに命名します。
CloudWatch Log Group が作成されるので、グループを開き、「メトリクスフィルターの作成」に進みます。
エラーを拾いたいため、フィルターパターンには { $.errorCode = "AccessDenied" }
を入力します。
フィルター名やメトリクス名などを入力します。メトリクス値は 1 とし、他はデフォルト値のままとします。
メトリクスフィルターを作成します。
作成したメトリクスフィルターを選択し、「アラームを作成」に進みます。
「統計」は "合計"、「期間」は "5分" としました。
条件については、メトリクスが 1つでも存在すればアラート対象となる様に設定します。
「アラーム状態トリガー」は "アラーム状態" とし、今回は自分宛にメールを送信するための SNS トピックを作成し、指定しました。(SNS トピックがない場合は新規作成を選択してください)
アラーム名を記入し、アラームを作成します。
この様な状態になりました。
この状態で再度 VPC フローログの出力に失敗させると、下記の様なメールが来ました。細かいですが、設定したアラームが発砲していることがわかります。これにて、delivery.logs.amazonaws.com によるログ配信の失敗を検知することができました。
おわりに
delivery.logs.amazonaws.com から配信されるログの出力失敗イベントを検知し、アラートまでやってみました。直感的に、delivery.logs.amazonaws.com に関するイベントを取得する方法はないものと思っていましたが、CloudTrail データイベントや S3 アクセスログに記録されることがわかり、勉強になりました。
あくまで delivery.logs.amazonaws.com が S3 にログを出力しようとした際に失敗した 事を検知するための方法となります。例えば、出力先を間違える、といったサービス側のログ設定ミスについては、別途検知する必要がありますので、ご注意ください。
以上、AWS 事業本部の大前でした。