各種AWSサービスのアクセスログ保存のためのS3バケットアクセス制御をまとめてみた

アクセスログを出力するAWSサービスによって、ログを保存するS3バケットに必要な設定は異なります

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。AWS事業本部トクヤマシュンです。

AWSサービスで日々大量に記録されるアクセスログについて、 ストレージ費用は抑えたいけど、いざという時のために取っておきたい。
そんな時は、まずS3に保存するのが一般的です。

AWSにはアクセスログの保存先にS3を指定可能なサービスがいくつか存在します。
しかし、AWSサービス毎にログ保存用のS3バケットに必要なアクセス制御設定は異なります
GUIでアクセスログを設定する場合にはあまり意識しなくても良いのですが、TerraformやCloudFrontで構築する際には自分でS3バケットのアクセス制御設定が必要です。  

構築の度に調べるのにいい加減うんざりしてしまったので、いくつかのサービスについてアクセスログ保存用のS3バケットの設定をまとめます。
構築用のTerraformコードも記載しているので、参考にしてみてください。

S3アクセス制御設定まとめ表

いくつかのAWSサービスとアクセスログ保存先のS3バケットのアクセス制御設定をまとめたのが次の表です。AWSサービスはアクセスログを取る機会が多いと思われるサービスを対象としています。

なお前提として、AWSサービスのアカウントとアクセスログを保存するS3バケットの所持アカウントは同一としています。

以降は各AWSサービスでの設定を見ていきます。

CloudFrontアクセスログ保存バケット設定

Amazon CloudFrontのアクセスログを保存するS3バケットには、ACLの設定が必要です。

2022/6/14時点では、CloudFrontアクセスログを保存するS3バケットのアクセス制御はACLで実施するよう案内されています。
ただ、re:Invent 2021期間中に発表されたS3のACL無効化機能に代表されるように、Amazon S3のACLは無効化が推奨されていますので、近い将来変更される予感がします。
この辺りの詳細は下記ブログをご参照ください。

制御パーミッションの付与対象はawslogsdeliveryアカウントIDで、下記のActionを許可します。

  • バケットACL
    • FULL_CONTROL
  • オブジェクトACL
    • 読み取りアクセス許可
    • 書き込みアクセス許可

awslogsdeliveryアカウントIDはグローバルで共通のアカウントです。
CloudFrontのアクセスログはこのアカウント上から自アカウントのS3バケットに書き込まれます。
GUIからアクセスログを設定すると自動でACLが追加されるため、ふとした時にS3バケットのパーミッションを確認すると、知らないアカウントからのアクセス許可が設定されていて驚くことがあります。
怪しいアカウントではないので安心してください。

ACL設定の詳細は、こちらの公式ドキュメント内のACL for the bucketACL for each log fileをご覧ください。

Terraformコード(CloudFrontアクセスログバケット作成)

Terraformでバケット作成を行うコードを記載しますので、参考まで。

resource "aws_S3_bucket" "log_cloudfront" {
  bucket = "<バケット名>"

  ##バケット所有者(自身のAWSアカウントの許可設定)の許可設定
  grant {
    id          = data.aws_canonical_user_id.current_user.id
    type        = "CanonicalUser"
    permissions = ["FULL_CONTROL"]
  }

  ##awslogsdeliveryアカウントIDの許可設定
  grant {
    id          = "c4c1ede66af53448b93c283ce9448c4ba468c9432aa01d700d3878632f77d2d0"
    type        = "CanonicalUser"
    permissions = ["FULL_CONTROL"]
  }
}

ALBアクセスログ保存バケット設定

Application Load Balancerのアクセスログを保存するS3バケットには、バケットポリシーの設定が必要です。

制御パーミッションの付与対象(principal)は2つあります。

1つは外部アカウントElastic Load BalancingアカウントIDで、s3:PutObjectアクションを許可します。
ALBのアクセスログは外部アカウントElastic Load BalancingアカウントID上から自アカウントのS3バケットに書き込まれます。
外部アカウントからアクセスログが書き込まれるのはCloudFrontと同様ですね。
ただし、Elastic Load BalancingアカウントIDはリージョン毎に異なります。
また、ALBとログ用バケットは同じリージョンである必要があります。
複数リージョンに設定する場合は注意しましょう。

もう1つはサービスlogdelivery.elb.amazonaws.comで、s3:GetBucketAclアクションを許可します。

バケットポリシーの詳細は、こちらの公式ドキュメントをご覧ください。各リージョンのElastic Load BalancingアカウントIDの値も記載されています。

Terraformコード(ALBアクセスログバケットポリシー作成)

Terraformでのバケットポリシー作成用のコードを記載しますので、参考まで。

## Elastic Load Balancing アカウント ID
data "aws_elb_service_account" "tf_elb_service_account" {}

## S3 Bucket Policy
data "aws_iam_policy_document" "log_alb" {
  statement {
    effect    = "Allow"
    actions   = [ "s3:PutObject" ]
    resources = [ "<S3バケットのARN>/*" ]
    principals {
      type = "AWS"
      identifiers = [ data.aws_elb_service_account.tf_elb_service_account.arn ]
    }
  }
  statement {
    effect    = "Allow"
    actions   = [ "s3:GetBucketAcl" ]
    resources = [ "<S3バケットのARN>" ]
    principals {
      type = "Service"
      identifiers = [ "logdelivery.elb.amazonaws.com" ]
    }
  }
}

TerraformではData Source:aws_elb_service_accountを使うことで実行リージョンに応じたElastic Load BalancingアカウントIDを取得可能です。

AWS WAFのS3アクセス制御設定

AWS WAFのアクセスログを保存するS3バケットにはバケットポリシーの設定が必要です。
AWS WAFのアクセスログのS3出力は、2021年11月のアップデートによって可能になりました。

ALBとは違って制御パーミッションの付与対象(principal)は1つで、サービスdelivery.logs.amazonaws.comです。
このサービスに対してs3:PutObjectアクションとs3:GetBucketAclアクションを許可します。

logsというサービス名前空間の通り、裏ではCloudWatchLogsが動作し、ログを出力しています。
このようにCloudWatchLogsがS3に直接ログ送信を行うサービスはいくつかあります。
こちらのCloudWatchLogsのドキュメント 内の表のうち、Amazon S3の列に✔︎記載のサービスが該当しますので、覚えておくとどこかで役に立つかもしれません。

なお、AWS WAFのアクセスログを出力するS3バケットの制約として、ログバケット名がaws-waf-logs-から始まる必要がありますので、注意してください。 バケットポリシーの詳細は、こちらの公式ドキュメントをご覧ください。

Terraformコード(AWS WAFアクセスログバケットポリシー作成)

Terraformでのバケットポリシー作成用のコードを記載しますので、参考まで。

## S3 Bucket Policy
data "aws_iam_policy_document" "log_waf" {
  statement {
    effect    = "Allow"
    actions   = [ "s3:PutObject" ]
    resources = [ "<ログバケットのARN>/*" ]
    principals {
      type = "Service"
      identifiers = [ "delivery.logs.amazonaws.com" ]
    }
    condition {
      test     = "StringEquals"
      variable = "aws:SourceAccount"
      values = [
        "<自アカウントのID>"
      ]
    }
    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-acl"
      values = [
        "bucket-owner-full-control"
      ]
    }
    condition {
      test     = "ArnLike"
      variable = "aws:SourceArn"
      values = [
        "arn:aws:logs:<リージョン>:<アカウントID>:*"
      ]
    }
  }
  statement {
    effect    = "Allow"
    actions   = [ "s3:GetBucketAcl" ]
    resources = [ "<ログバケットのARN>" ]
    principals {
      type = "Service"
      identifiers = [ "delivery.logs.amazonaws.com" ]
    }
    condition {
      test     = "StringEquals"
      variable = "aws:SourceAccount"
      values = [
        "<自アカウントID>"
      ]
    }
    condition {
      test     = "ArnLike"
      variable = "aws:SourceArn"
      values = [
        "arn:aws:logs:<リージョン>:<アカウントID>:*"
      ]
    }
  }
}

S3アクセスログ保存バケット設定

Amazon S3バケットのアクセスログを保存する別のS3バケットには、バケットポリシーの設定が必要です。
以前はACLでの設定が主流でしたが、現在は非推奨となっており、公式ドキュメントにもその記載があります。
詳細は下記ブログをご参照ください。

制御パーミッションの付与対象(principal)はAWS WAFと同じく1つで、サービスlogging.s3.amazonaws.comです。
このサービスに対して、s3:PutObjectアクションのみを許可します。
なお、S3バケットのアクセスログを同じバケットに保存する設定はNGです。アクセスログ出力の無限ループが発生してしまいます。

バケットポリシーの詳細は、こちらの公式ドキュメントをご覧ください。

Terraformコード(S3バケットアクセスログバケットポリシー作成)

Terraformでのバケットポリシー作成用のコードを記載しますので、参考まで。

## S3 Bucket Policy
data "aws_iam_policy_document" "log_s3" {
  statement {
    effect    = "Allow"
    actions   = [ "s3:PutObject" ]
    resources = [ "<S3バケットのARN>/*" ]
    principals {
      type = "Service"
      identifiers = [ "logging.s3.amazonaws.com" ]
    }
  }
}

他サービスのアクセスログ保存バケット設定

2022/6/14現在、下記サービスにはアクセスログをS3バケットに保存するデフォルトの仕組みはありません。
何らかの仕組みを作り込むことが必要ですので、リンク先を参照しつつ検討しましょう。

趣味のスパイスカレー

突然ですが、私の趣味はスパイスカレー作りです(半月ぶり二度目)
前回ブログから自作カレーを投稿しています。
相変わらず本筋とは全然関係ありませんが、お付き合いいただけますと幸いです。

  • 豆豉豚キーマ
  • レンズ豆のダル
  • トマトとセロリのカチュンバル

豆豉を使った中華風豚キーマカレーを作りました。
辛さと痺れが程よく効いていて、ご飯が進みます!
カシューナッツの食感も程よいアクセントとなって◎でした。

最後に

このサービスのアクセスログってS3バケットにどうやって保存するんだっけ・・・??と毎回なっていたので、まとめてみました。
本ブログがどなたかの助けになれば幸いです。それでは。