CloudFront/WAF/API GatewayのアクセスログをS3保存するようにしてAthenaで確認できるようにしてみた

関連記事で実装しているサーバレスWebアプリのサンプルのアクセスログ確認をAthenaでお手軽にしたいと思いました。そこでCloudFront/WAF/API Gatewayアクセスログをデータレイクとして用意したS3バケットへ保存するようにしてみました。

今回のコード

それぞれ記事時点のコードにタグを打ってあります。

アクセスログ保存の設定概要

全体構成は下記です。

f:id:nihma:20191026195205p:plain

データレイクとして作成するS3バケットは下記です。

  • CloudFront(API):${var.resource_prefix}-cloudfront-logs-api-01
  • CloudFront(SPA):${var.resource_prefix}-cloudfront-logs-web-01
  • WAF(API):${var.resource_prefix}-waf-logs-api-01
  • WAF(SPA):${var.resource_prefix}-waf-logs-web-01
  • API Gateway${var.resource_prefix}-apigw-logs-01

CloudFront

CloudFrontのアクセスログをS3バケットに保存するには下記の対応が必要です。*1

  1. ログ保存用のS3バケットを用意する
  2. CloudFrontのログ出力先に上記のS3バケットドメイン名を指定する

プルリクは下記です。

ログ保存用のS3バケット

まずAPIのS3バケットです。

aws-sls-spa-sample-terraform/environments/service/base/after_api/main.tf:L95-L99

module "s3_bucket_cloudfront_log_api" {
  source            = "../../../../modules/s3/bucket/cloudfront_log_api"
  resource_prefix   = "${local.resource_prefix}"
  logging_bucket_id = "${local.s3_bucket_audit_log_id}"
}

そしてSPAのS3バケットです。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L219-L223

module "s3_bucket_cloudfront_log_web" {
  source            = "../../../../modules/s3/bucket/cloudfront_log_web"
  resource_prefix   = "${local.resource_prefix}"
  logging_bucket_id = "${var.s3_bucket_audit_log_id}"
}

CloudFrontのログ出力先

まずAPIのCloudFrontです。s3_bucket_log_domain_nameにS3バケットドメイン名を指定します。

aws-sls-spa-sample-terraform/environments/service/base/after_api/main.tf:L101-L108

module "cloudfront_api" {
  source                    = "../../../../modules/cloudfront/api"
  resource_prefix           = "${local.resource_prefix}"
  stage                     = "${var.stage}"
  apigw_api_domain_name     = "${var.apigw_api_id}.execute-api.ap-northeast-1.amazonaws.com"
  s3_bucket_log_domain_name = "${module.s3_bucket_cloudfront_log_api.bucket_domain_name}"
  waf_acl_id                = "${data.terraform_remote_state.service_base_pre.outputs.waf_acl_api_id}"
}

モジュールの中は下記です。aws_cloudfront_distributionリソースのlogging_configにS3バケットドメイン名を指定します。

aws-sls-spa-sample-terraform/modules/cloudfront/api/main.tf:L71-L73

resource "aws_cloudfront_distribution" "api" {
  # ...(省略)...
  logging_config {
    bucket = "${var.s3_bucket_log_domain_name}"
  }

そしてSPAのCloudFrontです。こちらもs3_bucket_log_domain_nameにS3バケットドメイン名を指定します。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L231-L238

module "cloudfront_web" {
  source                    = "../../../../modules/cloudfront/web"
  resource_prefix           = "${local.resource_prefix}"
  s3_bucket_log_domain_name = "${module.s3_bucket_cloudfront_log_web.bucket_domain_name}"
  s3_bucket_web_id          = "${module.s3_bucket_web.id}"
  s3_bucket_web_domain_name = "${module.s3_bucket_web.domain_name}"
  waf_acl_id                = "${module.waf_acl_web.id}"
}

モジュールの中は下記です。こちらもaws_cloudfront_distributionリソースのlogging_configにS3バケットドメイン名を指定します。

aws-sls-spa-sample-terraform/modules/cloudfront/web/main.tf:L25-L28

resource "aws_cloudfront_distribution" "web" {
  # ...(省略)...
  logging_config {
    include_cookies = false
    bucket          = "${var.s3_bucket_log_domain_name}"
  }

WAF

WAFのアクセスログをS3バケットに保存するには下記の対応が必要です。*2

  1. ログ保存用のS3バケットを用意する
  2. Kinesis Firehoseを用意して出力先に上記のS3バケットARNを指定する
  3. WAFのログ出力先に上記のKinesis FirehoseのARNを指定する

プルリクは下記です。

ログ保存用のS3バケット

まずAPIのS3バケットです。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L106-L110

module "s3_bucket_waf_log_api" {
  source            = "../../../../modules/s3/bucket/waf_log_api"
  resource_prefix   = "${local.resource_prefix}"
  logging_bucket_id = "${var.s3_bucket_audit_log_id}"
}

そしてSPAのS3バケットです。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L142-L146

module "s3_bucket_waf_log_web" {
  source            = "../../../../modules/s3/bucket/waf_log_web"
  resource_prefix   = "${local.resource_prefix}"
  logging_bucket_id = "${var.s3_bucket_audit_log_id}"
}

Kinesis Firehose

用意するKinesis Firehoseにはいくつか注意点があります。*3*4

  • 作成するリージョンをus-east-1にする必要がある
  • 名称のプレフィックスaws-waf-logs-にする必要がある
  • ログファイルをGZIP形式にする必要がある

まずAPIKinesis Firehoseです。aws_kinesis_firehose_delivery_streamリソースのs3_configurationにS3バケットARNを指定します。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L112-L129

module "iam_role_waf_log_api_firehose_to_s3" {
  source          = "../../../../modules/iam/waf_log_api_firehose_to_s3"
  path            = "../../../../modules/iam/waf_log_api_firehose_to_s3"
  resource_prefix = "${local.resource_prefix}"
  s3_bucket_arn   = "${module.s3_bucket_waf_log_api.arn}"
}

resource "aws_kinesis_firehose_delivery_stream" "waf_log_api" {
  provider    = aws.useast1
  name        = "aws-waf-logs-${local.resource_prefix}-api"
  destination = "s3"

  s3_configuration {
    role_arn           = "${module.iam_role_waf_log_api_firehose_to_s3.arn}"
    bucket_arn         = "${module.s3_bucket_waf_log_api.arn}"
    compression_format = "GZIP"
  }
}

名称プレフィックスGZIPは注意点の通りです。リージョンはaws.useast1というus-east-1providerを新たに用意して指定しました。aws.useast1は下記になっています。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L11-L13

provider "aws" {
  alias   = "useast1"
  version = ">= 2.24"
  region  = "us-east-1"
}

そしてSPAのKinesis Firehoseです。こちらもaws_kinesis_firehose_delivery_streamリソースのs3_configurationにS3バケットARNを指定します。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L148-L165

module "iam_role_waf_log_web_firehose_to_s3" {
  source          = "../../../../modules/iam/waf_log_web_firehose_to_s3"
  path            = "../../../../modules/iam/waf_log_web_firehose_to_s3"
  resource_prefix = "${local.resource_prefix}"
  s3_bucket_arn   = "${module.s3_bucket_waf_log_web.arn}"
}

resource "aws_kinesis_firehose_delivery_stream" "waf_log_web" {
  provider    = aws.useast1
  name        = "aws-waf-logs-${local.resource_prefix}-web"
  destination = "s3"

  s3_configuration {
    role_arn           = "${module.iam_role_waf_log_web_firehose_to_s3.arn}"
    bucket_arn         = "${module.s3_bucket_waf_log_web.arn}"
    compression_format = "GZIP"
  }
}

こちらもリージョン、名称プレフィックスGZIPは注意点の通りです。

WAFのログ出力先

まずAPIのWAFです。firehose_arnKinesis FirehoseのARNを指定します。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L131-L138

module "waf_acl_api" {
  source                      = "../../../../modules/waf/api"
  resource_prefix             = "${local.resource_prefix}"
  firehose_arn                = "${aws_kinesis_firehose_delivery_stream.waf_log_api.arn}"
  rule_size_constraint_id     = "${module.waf_rule.rule_size_constraint_id}"
  rule_sql_injection_match_id = "${module.waf_rule.rule_sql_injection_match_id}"
  rule_xss_match_id           = "${module.waf_rule.rule_xss_match_id}"
}

モジュールの中は下記です。aws_waf_web_aclリソースのlogging_configurationKinesis FirehoseのARNを指定します。

aws-sls-spa-sample-terraform/modules/waf/api/main.tf:L42-L44

resource "aws_waf_web_acl" "api" {
  # ...(省略)...
  logging_configuration {
    log_destination = "${var.firehose_arn}"
  }

そしてSPAのWAFです。こちらもfirehose_arnKinesis FirehoseのARNを指定します。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L167-L174

module "waf_acl_web" {
  source                      = "../../../../modules/waf/web"
  resource_prefix             = "${local.resource_prefix}"
  firehose_arn                = "${aws_kinesis_firehose_delivery_stream.waf_log_web.arn}"
  rule_size_constraint_id     = "${module.waf_rule.rule_size_constraint_id}"
  rule_sql_injection_match_id = "${module.waf_rule.rule_sql_injection_match_id}"
  rule_xss_match_id           = "${module.waf_rule.rule_xss_match_id}"
}

モジュールの中は下記です。こちらもaws_waf_web_aclリソースのlogging_configurationKinesis FirehoseのARNを指定します。

aws-sls-spa-sample-terraform/modules/waf/web/main.tf:L42-L44

resource "aws_waf_web_acl" "web" {
  # ...(省略)...
  logging_configuration {
    log_destination = "${var.firehose_arn}"
  }

API Gateway

API GatewayアクセスログをS3バケットに保存するには下記の対応が必要です。*5*6*7*8*9

  1. API GatewayのCloudWatch Logsへのアクセスログ保存を有効にする*10
  2. ログ保存用のS3バケットを用意する
  3. ログフォーマットをAthena用に変換するLambdaを用意する
  4. Kinesis Firehoseを用意して出力先に2.のS3バケットARN、ログ変換Lambdaに3のLambdaのARNを指定する
  5. CloudWatch Logsのサブスクリプションフィルタを用意してロググループに1.のロググループ名、出力先にKinesis FirehoseのARNを指定する

プルリクは下記です。

API GatewayのCloudWatch Logsへのアクセスログ保存

serverless.ymlrestApiを追加しました。*11*12Athenaで操作しやすくするためにJSONフォーマットです。*13

aws-sls-spa-sample-api/serverless.yml:L11-L25

provider:
  name: aws
  logs:
    restApi:
      format:
        '{
          "request_id":"$context.requestId",
          "ip": "$context.identity.sourceIp",
          "caller": "$context.identity.caller",
          "user": "$context.identity.user",
          "request_time": "$context.requestTime",
          "http_method": "$context.httpMethod",
          "resource_path": "$context.resourcePath",
          "status": "$context.status",
          "protocol": "$context.protocol",
          "response_length": "$context.responseLength"
        }'

これで/aws/api-gateway/${local.cloudformation_api_stack}というロググループにアクセスログが保存されるようになります。

ログ保存用のS3バケット

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L41-L45

module "s3_bucket_apigw_log" {
  source            = "../../../../modules/s3/bucket/apigw_log"
  resource_prefix   = "${local.resource_prefix}"
  logging_bucket_id = "${local.s3_bucket_audit_log_id}"
}

ログフォーマット変換Lambda

amazon-kinesis-firehose-cloudwatch-logs-processorを使いました。*14めんどくさかったので今回はindex.jsをダウンロードしてserverless frameworkでLambdaデプロイして使うようにしました。

まず、serverless frameworkのプロジェクトです。amazon-kinesis-firehose-cloudwatch-logs-processorindex.jsはCodeBuildのタイミングで取得するためbuildspec.ymlcurlしました。

aws-sls-spa-sample-terraform/serverless/buildspec.yml:L6-L10

    commands:
      - cd serverless
      - npm install -g serverless@1.49.0
      - COMMIT="ec522aa8c09df0eafbfe286cd1275ca5eb418e98"
      - curl -s -qL -o index.js "https://raw.githubusercontent.com/tmakota/amazon-kinesis-firehose-cloudwatch-logs-processor/${COMMIT}/index.js"

次にCodeBuildプロジェクトの作成です。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L6-L10

## tool

module "iam_role_build_tool" {
  source                    = "../../../../modules/iam/build_tool"
  path                      = "../../../../modules/iam/build_tool"
  aws_account_id            = "${data.aws_caller_identity.current.account_id}"
  resource_prefix           = "${local.resource_prefix}"
  cloudformation_tool_stack = "${local.cloudformation_tool_stack}"
}

module "s3_bucket_build_tool" {
  source            = "../../../../modules/s3/bucket/build_tool"
  resource_prefix   = "${local.resource_prefix}"
  logging_bucket_id = "${var.s3_bucket_audit_log_id}"
}

module "iam_role_exec_tool" {
  source                    = "../../../../modules/iam/exec_tool"
  path                      = "../../../../modules/iam/exec_tool"
  aws_account_id            = "${data.aws_caller_identity.current.account_id}"
  resource_prefix           = "${local.resource_prefix}"
  cloudformation_tool_stack = "${local.cloudformation_tool_stack}"
}

module "codebuild_tool" {
  source                  = "../../../../modules/codebuild/tool"
  codecommit_repository   = "${data.terraform_remote_state.setup.outputs.codecommit_infra_repository}"
  iam_role_build_tool_arn = "${module.iam_role_build_tool.arn}"
  s3_bucket_build_tool_id = "${module.s3_bucket_build_tool.id}"
  resource_prefix         = "${var.resource_prefix}"
  stage                   = "${var.stage}"
  iam_role_exec_tool_arn  = "${module.iam_role_exec_tool.arn}"
  service_name            = "${local.service_name}"
}

最後にCodeBuildプロジェクトを実行してLambdaのデプロイです。

aws-sls-spa-sample-terraform/bin/create_development_environment.sh:L52-L56

##
echo "START: base..."
##
# ...(省略)...
cd environments/service/base/pre/ || exit 99

codebuild_name=$(terraform output codebuild_tool_name)

cd - || exit 99

./bin/exec_codebuild.sh "${codebuild_name}" master

staging/productionも同様なbashですが割愛します。

Kinesis Firehose

aws_kinesis_firehose_delivery_streamリソースのextended_s3_configurationにS3バケットARNとLambdaのARNを指定します。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L47-L78

module "iam_role_apigw_firehose_to_s3" {
  source          = "../../../../modules/iam/apigw_firehose_to_s3"
  path            = "../../../../modules/iam/apigw_firehose_to_s3"
  resource_prefix = "${local.resource_prefix}"
  s3_bucket_arn   = "${module.s3_bucket_apigw_log.arn}"
  aws_account_id            = "${data.aws_caller_identity.current.account_id}"
  cloudformation_tool_stack = "${local.cloudformation_tool_stack}"
}

resource "aws_kinesis_firehose_delivery_stream" "apigw" {
  name        = "${local.resource_prefix}-apigw-cwl-to-s3-stream"
  destination = "extended_s3"

  extended_s3_configuration {
    role_arn           = "${module.iam_role_apigw_firehose_to_s3.arn}"
    bucket_arn         = "${module.s3_bucket_apigw_log.arn}"
    compression_format = "GZIP"

    processing_configuration {
      enabled = "true"

      processors {
        type = "Lambda"

        parameters {
          parameter_name  = "LambdaArn"
          parameter_value = "arn:aws:lambda:ap-northeast-1:${data.aws_caller_identity.current.account_id}:function:${local.cloudformation_tool_stack}-logsProcessor:$LATEST"
        }
      }
    }
  }
}

CloudWatch Logsのサブスクリプションフィルタ

aws_cloudwatch_log_subscription_filterリソースにロググループ名とKinesis FirehoseのARNを指定します。

aws-sls-spa-sample-terraform/environments/service/base/pre/main.tf:L80-L93

module "iam_role_apigw_cloudwatchlogs_to_s3_policy" {
  source          = "../../../../modules/iam/apigw_coudwatchlogs_to_s3_policy"
  path            = "../../../../modules/iam/apigw_coudwatchlogs_to_s3_policy"
  aws_account_id  = "${data.aws_caller_identity.current.account_id}"
  resource_prefix = "${local.resource_prefix}"
}

resource "aws_cloudwatch_log_subscription_filter" "apigw_logfilter" {
  name            = "${local.resource_prefix}-apigw_logfilter"
  role_arn        = "${module.iam_role_apigw_cloudwatchlogs_to_s3_policy.arn}"
  log_group_name  = "/aws/api-gateway/${local.cloudformation_api_stack}"
  filter_pattern  = ""
  destination_arn = "${aws_kinesis_firehose_delivery_stream.apigw.arn}"
}

Athenaで確認

SPAで色々と操作をしてしばらく経つとS3バケットアクセスログファイルが溜まってきます。

f:id:nihma:20191026190302p:plain

とりあえず今回は凝ったことをせずテーブル作ってSELECTするところまでしました。*15*16*17

CloudFront

まずはテーブルを定義します。*18*19

S3バケット名はAPI${var.resource_prefix}-cloudfront-logs-api-01、SPAが${var.resource_prefix}-cloudfront-logs-web-01です。

CREATE EXTERNAL TABLE IF NOT EXISTS `cloudfront_logs`(
  `date` date, 
  `time` string, 
  `location` string, 
  `bytes` bigint, 
  `request_ip` string, 
  `method` string, 
  `host` string, 
  `uri` string, 
  `status` int, 
  `referrer` string, 
  `user_agent` string, 
  `query_string` string, 
  `cookie` string, 
  `result_type` string, 
  `request_id` string, 
  `host_header` string, 
  `request_protocol` string, 
  `request_bytes` bigint, 
  `time_taken` float, 
  `xforwarded_for` string, 
  `ssl_protocol` string, 
  `ssl_cipher` string, 
  `response_result_type` string, 
  `http_version` string, 
  `fle_status` string, 
  `fle_encrypted_fields` int)
ROW FORMAT DELIMITED 
  FIELDS TERMINATED BY '\t' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://[S3バケット名]/'
TBLPROPERTIES (
  'skip.header.line.count'='2');

テーブルができたので検索できるようになりました。

SELECT * FROM "default"."cloudfront_logs" limit 10;

WAF

まずはテーブルを定義します。*20*21

S3バケット名はAPI${var.resource_prefix}-waf-logs-api-01、SPAが${var.resource_prefix}-waf-logs-web-01です。

CREATE EXTERNAL TABLE IF NOT EXISTS `waf_logs`(
  `timestamp` bigint, 
  `formatversion` int, 
  `webaclid` string, 
  `terminatingruleid` string, 
  `terminatingruletype` string, 
  `action` string, 
  `httpsourcename` string, 
  `httpsourceid` string, 
  `rulegrouplist` array<
                    struct<
                      rulegroupid: string,
                      terminatingrule: string,
                      nonterminatingmatchingrules: array< struct< action: string, ruleid: string > >,
                      excludedrules: array< struct< exclusiontype: string, ruleid: string > > > >, 
  `ratebasedrulelist` array< struct< ratebasedruleid: string, limitkey: string, maxrateallowed: int > >, 
  `nonterminatingmatchingrules` array< struct< action: string, ruleid: string > >, 
  `httprequest` struct<
                  clientip: string,
                  country: string,
                  headers: array< struct< name: string, value: string > >,
                  uri: string,
                  args: string,
                  httpversion: string,
                  httpmethod: string,
                  requestid: string>)
ROW FORMAT SERDE 
  'org.openx.data.jsonserde.JsonSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat'
LOCATION
  's3://[S3バケット名]/';

テーブルができたので検索できるようになりました。

SELECT * FROM "default"."waf_logs" limit 10;

API Gateway

まずはテーブルを定義します。CREATE 文はserverless.ymlrestApiに指定したJSONフォーマットから作りました。

S3バケット名は${var.resource_prefix}-apigw-logs-01です。

CREATE EXTERNAL TABLE IF NOT EXISTS `apigw_logs`(
  `request_id` string, 
  `ip` string, 
  `caller` string, 
  `user` string, 
  `request_time` string, 
  `http_method` string, 
  `resource_path` string, 
  `status` string, 
  `protocol` string, 
  `response_length` string)
ROW FORMAT SERDE 
  'org.openx.data.jsonserde.JsonSerDe' 
WITH SERDEPROPERTIES ( 
  'ignore.malformed.json'='true') 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat'
LOCATION
  's3://[S3バケット名]/'
TBLPROPERTIES (
  'has_encrypted_data'='false');

テーブルができたので検索できるようになりました。

SELECT * FROM "default"."apigw_logs" limit 10;

まとめ

今回はCloudFront/WAF/API GatewayアクセスログをS3に保存しデータレイクとしてAthenaで確認できるようにしてみました。

  • DynamoDBの情報もGlueなどでS3データレイクに同期するようにしても良いかも。そうすればAthenaでSQL使えるし分析のためにRCUを消費してサービスに影響するということもないし。
  • Cognitoの情報もS3データレイクに同期するようにしても良いかも。ただお手軽に同期する手段がないのでCognitoトリガーで一旦DynamoDBに同期してからのGlueなどでの同期になるかも。
  • LambdaのログもS3データレイクに同期するようにしても良いかも。

関連記事

*1:CloudFrontのアクセスログの設定および使用:https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html

*2:ウェブ ACL トラフィック情報のログ記録:https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/logging.html

*3:ウェブ ACL でログ記録を有効にするには:https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/logging.html#logging-procedure

*4:Athena圧縮形式:https://docs.aws.amazon.com/ja_jp/athena/latest/ug/compression-formats.html

*5:API Gateway CloudWatch の API ログ作成をセットアップする:https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-logging.html

*6:CloudWatch Logs サブスクリプションフィルタの使用:https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/SubscriptionFilters.html#FirehoseExample

*7:Amazon Kinesis Data Firehose のデータ変換:https://docs.aws.amazon.com/ja_jp/firehose/latest/dev/data-transformation.html

*8:AWS CloudWatch Logs に貯めこんだログをどうにかしようとしてハマった話:https://tech.actindi.net/2019/05/29/105748

*9:AWS Black Belt Online Seminar「Amazon Athena」の資料およびQA公開:https://aws.typepad.com/sajp/2017/03/aws-black-belt-online-seminaramazon-athena_slides_and_qa.html ... Q8にAmazon Kinesis FirehoseのData Transformationの必要性

*10:Firehoseを直接指定できるようになったので手順は変えた方が良いかも → Amazon API GatewayAmazon Kinesis Data Firehose へのアクセスログ記録をサポート開始:https://aws.amazon.com/jp/about-aws/whats-new/2019/10/amazon-api-gateway-now-supports-access-logging-to-amazon-kinesis-data-firehose/

*11:serverless/API Gateway REST API logs:https://serverless.com/blog/framework-release-v142/#api-gateway-rest-api-logs

*12:serverless/API Gateway REST API logshttps://serverless.com/framework/docs/providers/aws/events/apigateway/#logs

*13:API Gateway マッピングテンプレートとアクセスのログ記録の変数リファレンス:https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html

*14:Lambda設計図のKinesis Data Firehose CloudWatch Logs Processor (Kinesis Data Firehose CloudWatch ログプロセッサ) と同じ?

*15:S3のデータをAmazon Athenaを使って分析する:https://aws.amazon.com/jp/blogs/news/analyzing-data-in-s3-using-amazon-athena/

*16:CREATE TABLE:https://docs.aws.amazon.com/ja_jp/athena/latest/ug/create-table.html

*17:SELECT:https://docs.aws.amazon.com/ja_jp/athena/latest/ug/select.html

*18:Amazon CloudFront ログのクエリ:https://docs.aws.amazon.com/ja_jp/athena/latest/ug/cloudfront-logs.html

*19:CloudFrontログ形式:https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#LogFileFormat

*20:AWS WAFのフルログをAthenaで分析できるようにしてみた:https://dev.classmethod.jp/cloud/aws/query-aws-waf-full-log-by-athena/

*21:ログの例:https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/logging.html