S3サーバーアクセスログを設定する上での注意点を確認する構成
AWS DVAの出題範囲の1つでもある、モニタリング・トラブルシューティングに関する内容です。
S3サーバーアクセスログを設定する上での注意点をご紹介します。
S3にはさまざまなモニタリングオプションが用意されています。サーバーアクセスログはS3が提供するログ記憶オプションの一種です。
サーバーアクセスのログには、Amazon S3 バケットに対するリクエストの詳細が記録されます。サーバーアクセスのログは、多くのアプリケーションに役立ちます。たとえば、アクセスのログ情報は、セキュリティやアクセスの監査に役立ちます。また、顧客基盤について知り、Amazon S3 の請求を理解することにも役立ちます。
Amazon S3 サーバーアクセスログを有効にします
ログ機能を有効化するために様々なパラメータがありますが、その1つにログの配信先に関するパラメータがあります。サーバーアクセスログの配信先を設定する際に注意するべきポイントは、ログ機能を有効化したバケットにログを配信してはいけないという点です。
バケットについてのサーバーアクセスログを同じバケットにプッシュしないでください。この方法でサーバーアクセスログを設定した場合、ログの無限ループが発生します。これは、バケットにログファイルを書き込むと、バケットにもアクセスが発生し、別のログを生成するためです。ログファイルは、バケットに書き込まれるすべてのログに対して生成され、ループが作成されます。
Amazon S3 バケットについてのサーバーアクセスログを同じバケットにプッシュすることはできますか?
今回は敢えてログ機能を有効化したバケットにログを配信するように設定し、その際の挙動を確認します。
構築する環境
パターンごとにS3バケットを作成します。
通常パターンでは、2つのバケットを作成します。1つはサーバーアクセスログ機能を有効化したバケット(normal-bucket)です。もう1つはログの配信先です(log-bucket)。
NGパターンでは、1つのバケット(error-bucket)を作成します。このバケットはログ機能を有効化した上で、自分自身に対してログを配信するように設定します。
環境構築用のCloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-dva/tree/main/05/001
テンプレートファイルのポイント解説
今回の環境を構成するための、各テンプレートファイルのポイントを取り上げます。
サーバーアクセスログ機能を有効化するためには、配信先バケットを指定する
まず通常パターンにおける、ログ機能を有効化するバケットを作成します。
Resources:
NormalBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${Prefix}-normal-bucket
AccessControl: Private
LoggingConfiguration:
DestinationBucketName: !Ref LogBucket
LogFilePrefix: test-normal-log
Code language: YAML (yaml)
LoggingConfigurationプロパティが、サーバーアクセスログ機能に関するパラメータです。同プロパティ内のDestinationBucketNameプロパティにて、ログの配信先バケットを指定します。今回は組み込み関数Fn::Refを使用して、後述のログ用バケットを指定します。
ログ配信を受けるバケットはACLに「LogDeliveryWrite」を指定する
次に先述のバケットから配信されたログを受け付けるバケットを定義します。
Resources:
LogBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${Prefix}-log-bucket
AccessControl: LogDeliveryWrite
Code language: YAML (yaml)
ログ配信を受ける側のバケットにおいて、ポイントとなるのはAccessControlプロパティです。本プロパティはS3バケットにおけるACL(Access Control List)に関するパラメータです。ACLはバケット・オブジェクトに対するアクセス制御機能です。
Amazon S3 のアクセスコントロールリスト (ACL) では、バケットとオブジェクトへのアクセスを管理できます。各バケットとオブジェクトには、サブリソースとして ACL がアタッチされています。これにより、アクセスが許可される AWS アカウント またはグループと、アクセスの種類が定義されます。リソースに対するリクエストを受け取ると、Amazon S3 は該当する ACL を確認して、リクエスタに必要なアクセス許可があることを確かめます。
アクセスコントロールリスト (ACL) の概要
ACLには、AWSによって予め用意された既定ACLと呼ばれるものがあります。既定ACLを利用することによって、目的のアクセス権限作成をショートカットすることができます。既定ACKの中に、今回のログ配信を受けるバケット用の設定があります。「log-delivery-write」という名前です。
LogDelivery グループはバケットに対する WRITE および READ_ACP アクセス許可を取得します。
既定ACL
Amazon S3 Log Delivery グループについての WRITE および READ_ACP アクセス権限によりますと、本ACLを使用するということは、以下の手続きを実施することと同義です。
- ログ配信グループに対して、バケットへのログ書き込み権限(WRITE)を付与する
- ログ配信グループに対して、バケットに付与されているACLを読み込む権限(READ_ACP)を付与する
CloudFormationでは、本ACLを指定するためには、「LogDeliveryWrite」を指定することとなっています。
自分自身にログを配信するためには、AWS CLIを使用する
最後にNGパターン用のバケットを作成します。
Resources:
ErrorBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${Prefix}-error-bucket
AccessControl: LogDeliveryWrite
Code language: YAML (yaml)
ACLに関しては、先述の通り、AccessControlプロパティに「LogDeliveryWrite」を指定します
LoggingConfigurationプロパティに関しては、CloudFormationでは定義しません。自分自身に対してログを配信するためには、組み込み関数Fn::Refを使って、自分を参照することになります。ただこういった振る舞いはCloudFormationではエラーとして処理されてしまいます。
こちらに関しては、後述のAWS CLIにて、手動で設定を行います。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
次に作成されたCloudFormationスタック内の各種リソースを確認します。作成されたスタック内のリソースにおいて、以下に特に重要な情報をまとめます。
- 通常パターンのログ機能を有効化したバケットの名前:dva-05-001-normal-bucket
- 通常パターンのログ配信を受けるバケットの名前:dva-05-001-log-bucket
- NGパターンの自分自身に対してログを配信するバケットの名前:dva-05-001-error-bucket
AWS CLIからサーバーアクセスログの設定状況を確認する
AWS Management Consoleからnormal-bucketのログ設定を確認します。
ログ設定が有効化されていることがわかります。
ログ設定の詳細も確認します。
LoggingEnabledの値にlog-bucketが指定されています。
先述の通り、ログ配信グループ(http://acs.amazonaws.com/groups/s3/LogDelivery)に対して、「WRITE」および「READ_ACP」の権限が付与されていることがわかります。
上記と同様の設定が、error-bucketに対しても適用されています。
S3サーバーアクセスログの正常時の挙動を確認する
まずサーバーアクセスログにおける、通常パターンの挙動を確認します。
テスト用ファイルをnormal-bucketに配置することで、ログを発生させます。
$ aws s3 cp test.txt s3://dva-05-001-normal-bucket
upload: test.txt to s3://dva-05-001-normal-bucket/test.txt
Code language: Bash (bash)
しばらく待つと、空だったlog-bucketにログファイルが生成されます。
1つをダウンロードし、中身を確認します。
cd3b764ff044236dfe910b663c273b1f98dd3299f4d524a32909f70581c332fa dva-05-001-normal-bucket [09/Jan/2022:11:56:02 +0000] 172.18.95.21 cd3b764ff044236dfe910b663c273b1f98dd3299f4d524a32909f70581c332fa A49XFDPQ95407VX8 REST.PUT.LOGGING_STATUS - "PUT /?logging HTTP/1.1" 200 - - - 350 - "-" "AWS CloudFormation, aws-internal/3" - fW2gj4UbfzIKmeLUVkSvzO4qp9hMDn2iLvWJ6b8FzE0Us8VQOYW0nJ1mqOn8NLF16ClLaG2nYNo= SigV4 ECDHE-RSA-AES128-GCM-SHA256 AuthHeader dva-05-001-normal-bucket.s3-ap-northeast-1.amazonaws.com TLSv1.2 -
Code language: plaintext (plaintext)
ログの読み方はAmazon S3 サーバーアクセスログの形式に詳しいですが、オペレーションフィールドを見ると、「PUT」とあり、テストファイルが設置された際のログであることがわかります。
S3サーバーアクセスログのループ時の挙動を確認する
続けて異常時の挙動を確認します。
まずCloudFormationで未設定だったログ配信設定を行います。
改めて現在のログ配信に関する設定を確認します。
現状では何も設定されていません。
AWS CLIのリファレンスを確認すると、AWS CLIからログ配信設定を行うためには、JSON形式で配信先バケットを指定する必要があるとされています。今回はJSONデータをテキストファイルとして用意し、これをパラメータとして指定します。
$ cat logging.json
{
"LoggingEnabled": {
"TargetBucket": "dva-05-001-error-bucket",
"TargetPrefix": "test-error-log",
"TargetGrants": [
{
"Grantee": {
"Type": "AmazonCustomerByEmail",
"EmailAddress": "[account-mail-address]"
},
"Permission": "FULL_CONTROL"
}
]
}
}
$ aws s3api put-bucket-logging \
--bucket dva-05-001-error-bucket \
--bucket-logging-status file://logging.json
Code language: Bash (bash)
コマンド実行後、再度ログ設定を確認します。
これで自分自身に対して、ログ配信するように設定できました。
準備が整いました。こちらでもテストファイルを設置することで、ログを発生させます。
$ aws s3 cp test.txt s3://dva-05-001-error-bucket
upload: test.txt to s3://dva-05-001-error-bucket/test.txt
Code language: Bash (bash)
テストファイルを設置した直後は、何も起きていません。ただししばらく待ってみると、バケット内に大量のログファイルが生成されていることが確認できます。
これは先述の通り、ログの書き込み処理に対してログが発生するという、一種のループ構造が出来上がっていることが原因です。この状態になると、短時間で数百GBものログファイルが生成され、高額な料金が発生する恐れがありますので、ご注意ください。
まとめ
S3サーバーアクセスログ機能に関して、通常パターンとNGパターンの構築方法や挙動を確認しました。
NGパターンでは、ログがループ的に生成され、大量のファイルとともに、意図せず高額な料金が発生する可能性について確認しました。