API Gatewayのカスタムアクセスログに無理やり情報を追加してみた

2022.04.08

いわさです。

API Gatewayのカスタムアクセスログに様々な情報を出力し、Athenaで眺めようとしています。
先日はAthenaで正しく認識させるためのポイントを紹介しました。

API Gatewayのカスタムアクセスログは変数を使うことで出力内容をカスタマイズ出来ます。
どこまで出来るのかを少し検証してみましたので、共有のために試したことなどを残しておきたいと思います。

変数の使用

まず初めに、API Gatewayのカスタムアクセスログで使用出来る変数は以下にまとめられています。

こちらの中の$context変数のみがカスタムアクセスログで使用出来ます。
例えば、以下のようなフォーマットを指定することが出来ます。

フォーマット

{ "requestid": "$context.requestId" "status": "$context.status" }

出力

{ "requestid": "b8f6c6f3-8e43-4b0f-ad80-6caa34ef21a4" "status": "200" }

$context.requestIdのみ必須です。

注意点として、$input変数はサポートされていません。
そして、上述のドキュメントを確認するに、$context変数自体には標準ではbodyやheaderを出力するオプションは無いようです。
よって、生のリクエストボディやパラメータを出力することは難しそうです。

少しカスタマイズ

この$contextですが、いくつかカスタマイズ出来る要素があります。
ドキュメント内の赤字になっているプロパティです。

  • $context.authorizer.claims.hogehoge
  • $context.authorizer.hogehoge

あとは、以下のマッピングテンプレートでオーバーライド可能な部分も一応カスタマイズ出力可能な要素と言えます。
マッピングテンプレートを使用して、API のリクエストおよびレスポンスパラメータとステータスコードをオーバーライドする - Amazon API Gateway

今回は上記のうちの、$context.authorizerに生データに近いものを設定しログ出力をしてみます。

オーソライザーを作成する

以前、API GatewayのLambdaオーソライザーについて調べたことがあります。

まず、リクエストベースのLambdaオーソライザーの場合は、body以外の大部分のリクエストデータをオーソライザーで取り扱うことが出来ました。
そして、Lambdaオーソライザーでは$contextへの値の設定を行うことが出来ます。

正しい使い方ではないですが、Lambdaオーソライザーを$context編集のために使ってみました。
IDソースは特に指定しません。

import json, datetime

def lambda_handler(event, context):
    print(json.dumps(event))
    return {
        'principalId': 'hoge',
        'policyDocument': {
            'Version': '2012-10-17',
            'Statement': [{
                'Action': 'execute-api:Invoke',
                'Effect': 'Allow',
                'Resource': event['methodArn']
            }]
        },
        'context': {
            'hogeheaders': json.dumps(event['headers'])
        }
    }

hogeheadersにJSONのまま設定し、パスでアクセス出来そうですが、今回はまとめて取得したかったのでdumpしています。
Lambdaの実行ログを見る限りでは期待どおり設定出来ていそうです。

{
    "principalId": "hoge",
    "policyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": "execute-api:Invoke",
                "Effect": "Allow",
                "Resource": "arn:aws:execute-api:ap-northeast-1:123456789012:0k6swiekjc/hoge/POST/hogehoge"
            }
        ]
    },
    "context": {
        "hogeheaders": "{\"accept\": \"*/*\", \"Content-Length\": \"35\", \"content-type\": \"application/x-www-form-urlencoded\", \"hoge-header1\": \"hoge-value1\", \"hoge-header2\": \"hoge-value2\", \"Host\": \"0k6swiekjc.execute-api.ap-northeast-1.amazonaws.com\", \"user-agent\": \"curl/7.64.1\", \"X-Amzn-Trace-Id\": \"Root=1-624f616b-4dc8ca72313ad9d8460987cf\", \"X-Forwarded-For\": \"203.0.113.1\", \"X-Forwarded-Port\": \"443\", \"X-Forwarded-Proto\": \"https\"}"
    }
}
{ "requestid": "9283965b-f4db-4c4c-a5bd-d603db6d86d0", "hogeheader": "{"accept": "*/*", "Content-Length": "35", "content-type": "application/x-www-form-urlencoded", "hoge-header1": "hoge-value1", "hoge-header2": "hoge-value2", "Host": "0k6swiekjc.execute-api.ap-northeast-1.amazonaws.com", "user-agent": "curl/7.64.1", "X-Amzn-Trace-Id": "Root=1-624f6169-4e63b7e92c9e689856d1bf9d", "X-Forwarded-For": "203.0.113.1", "X-Forwarded-Port": "443", "X-Forwarded-Proto": "https"}" }

文字列にはなってしまうのですが、ログに出力することが出来ました。
同じ方法でステージ変数なども出力出来てそうですね。

さいごに

本日はLambdaオーソライザーをカスタムアクセスログに情報を追加するために使ってみました。

Authorizationトークンなどもログ出力出来てしまいそうなので注意が必要ですね。
$contextは「エラー」に関する出力が可能なのですが、統合バックエンドで処理されないゲートウェイレスポンスに限って利用出来るようも見えます。マッピングテンプレートなど未設定の状態だとバックエンド用のLambda関数で設定した500エラーなどのメッセージは出力されませんでした。このあたりをもう少し掘り下げてみたいと思います。