CloudWatch Logs でサポートされたログ取り込み時の変換機能を紐解く
こんにちは!クラウド事業本部コンサルティング部のたかくに(@takakuni_)です。
一昔前、 CloudWatch Logs では、ログの取り込み時にログの内容を変換(トランスフォーム)する機能がリリースされました。
この機能を利用することで、ログに含まれる特定のキー/文字列を変換し、 CloudWatch Logs Insights での検索性の向上が見込めます。
機能
取り込み変換機能には、トランスフォーマー、プロセッサ、パーサーが登場します。
トランスフォーマー
トランスフォーマーは変換機能をまとめる仕組みです。1 つのロググループに対して 1 つトランスフォーマーを設定できます。
プロセッサ
プロセッサは具体的に、どのような変換処理を行うかを設定する部分です。
次のようなプロセッサが用意されています。
- 文字列ミューテーションプロセッサ
- 大文字/小文字変換など
- JSON ミューテーションプロセッサ
- キーの追加/削除/移動/名前変更など
- データ型コンバータプロセッサ
- 型の変換
パーサー
パーサーの役割はプロセッサと同じです。しかし、必要なプロセッサタイプ
や最初のプロセッサ
とも呼ばれます。文字通り、変換処理を行う順序が一番最初のプロセッサです。
パーサーの中には、プロセッサ(順序が2番目以降に)として利用可能なパーサー(Configurable Parser)も存在します。以下、AWS vended log 用にビルトインされたパーサーも用意されています。
- parseWAF
- parsePostgres
- parseCloudfront
- parseRoute53
- parseVPC
(重要) ログの表示について
少し癖があるのですが、ログは変換前と変換後のログが保管されます。
GetLogEvents, FilterLogEvents API を実行した場合は、変換前のログが表示され、 CloudWatch Logs Insights で検索した場合は変換後のログが表示されます。
ログイベントが変換されたら、CloudWatch Logs Insights クエリを使用して、変換されたバージョンのログを表示する必要があります。 GetLogEvents アクションと FilterLogEvents アクションは、変換される前のログイベントの元のバージョンのみを返します。
コスト
CloudWatch Logs の変換機能は、ログ取り込み時の料金に含まれています。
ログの変換および拡張機能は、AWS のすべての商用リージョンでご利用いただけます。この機能は、既存の標準ログクラス取り込みの料金に含まれています。
ただし、機能を利用するためには、標準ログクラスのロググループの利用が必須です。
ログ変換とエンリッチメントは、標準ログクラスのロググループでのみサポートされます。
取り込みと保管別の料金について
さらに深掘りしてみます。
CloudWatch Logs には、取り込み時の料金と保管時の料金の2パターンが発生します。
CloudWatch Logs と S3 にかかる料金比較 | DevelopersIOより画像引用
今回の機能は、先ほどの通り取り込み時の料金は変わらないものの、保管時の料金は増加する可能性があります。
変換はログの取り込み中にのみ行われます。既に取り込まれたログイベントを変換することはできません。変換は元に戻せません。元のログと変換されたログの両方が、同じ保持ポリシーで CloudWatch Logs に保存されます。ログ変換とエンリッチメント機能は、既存の標準ログクラスの取り込み料金に含まれています。ログストレージのコストは、変換後のログサイズに基づいており、元のログボリュームを超える可能性があります。
たとえば変換前後のログが、以下のバイト数と仮定します。(圧縮は無視します)
- 変換前のログ 4GB
- 変換後のログ 2GB
収集(データインジェスト)
収集(データインジェスト)は変換前の 4GB に対して課金が発生します。
4 GB * 0.5 = 2 USD
保存 (アーカイブ)
保存は変換前、変換後、両方のログに対して課金が発生します。
(4 GB + 2 GB) * 0.03 = 0.18 USD
クエリ
すべてのログを読み込み検索したと仮定した場合、変換前、変換後、両方のログに対して課金が発生します。
(4 GB + 2 GB) * 0.005 = 0.03 USD
やってみる
それでは今回、ビルトインで用意されている AWS WAF 用のパーサーを利用して、変換機能を試してみます。
httpRequest
の headers
の Key, Value を検索しやすく変換します。
変換前
{
"timestamp": 1576280412771,
"formatVersion": 1,
"webaclId": "arn:aws:wafv2:ap-southeast-2:111122223333:regional/webacl/STMTest/1EXAMPLE-2ARN-3ARN-4ARN-123456EXAMPLE",
"terminatingRuleId": "STMTest_SQLi_XSS",
"terminatingRuleType": "REGULAR",
"action": "BLOCK",
"terminatingRuleMatchDetails": [
{
"conditionType": "SQL_INJECTION",
"sensitivityLevel": "HIGH",
"location": "HEADER",
"matchedData": ["10", "AND", "1"]
}
],
"httpSourceName": "-",
"httpSourceId": "-",
"ruleGroupList": [],
"rateBasedRuleList": [],
"nonTerminatingMatchingRules": [],
"httpRequest": {
"clientIp": "1.1.1.1",
"country": "AU",
"headers": [
{ "name": "Host", "value": "localhost:1989" },
{ "name": "User-Agent", "value": "curl/7.61.1" },
{ "name": "Accept", "value": "*/*" },
{ "name": "x-stm-test", "value": "10 AND 1=1" }
],
"uri": "/myUri",
"args": "",
"httpVersion": "HTTP/1.1",
"httpMethod": "GET",
"requestId": "rid"
},
"labels": [{ "name": "value" }]
}
変換後
{
"httpRequest": {
"headers": {
"Host": "localhost:1989",
"User-Agent": "curl/7.61.1",
"Accept": "*/*",
"x-stm-test": "10 AND 1=1"
},
"clientIp": "1.1.1.1",
"country": "AU",
"uri": "/myUri",
"args": "",
"httpVersion": "HTTP/1.1",
"httpMethod": "GET",
"requestId": "rid"
},
"labels": { "name": "value" },
"timestamp": 1576280412771,
"formatVersion": 1,
"webaclId": "arn:aws:wafv2:ap-southeast-2:111122223333:regional/webacl/STMTest/1EXAMPLE-2ARN-3ARN-4ARN-123456EXAMPLE",
"terminatingRuleId": "STMTest_SQLi_XSS",
"terminatingRuleType": "REGULAR",
"action": "BLOCK",
"terminatingRuleMatchDetails": [
{
"conditionType": "SQL_INJECTION",
"sensitivityLevel": "HIGH",
"location": "HEADER",
"matchedData": ["10", "AND", "1"]
}
],
"httpSourceName": "-",
"httpSourceId": "-",
"ruleGroupList": [],
"rateBasedRuleList": [],
"nonTerminatingMatchingRules": []
}
CloudWatch Logs の設定
CloudWatch Logs 側を設定します。トランスフォーマーがありましたね。
パーサーに WAF を選びます。
トランスフォーマーには、最大 5 つのパーサーと、20つのプロセッサを指定できます。文字列ミューテーションプロセッサのため、大文字変換などが用意されてます。
今回は純粋な WAF Parser のみ利用します。保存を押すと、トランスフォーマーが有効になっています。
ログの確認
ログを確認しています。コンソール(GetLogEvents)で確認すると、変換前のログが表示されています。
一方、CloudWatch Logs Insights で確認すると、変換後のロググループが表示されていますね。@message
は変換前のログの内容が表示されているようでした。
まとめ
以上、「CloudWatch Logs でサポートされたログ取り込み時の変換機能を紐解く」でした。
Lambda などで、ログ変換を頑張っていた方にとっては、嬉しかったりするのではないでしょうか。
このブログがどなたかの参考になれば幸いです。クラウド事業本部コンサルティング部のたかくに(@takakuni_)でした!