Slide 1

Slide 1 text

tslogで実現するセキュアな メタデータ管理とロギング 2024/11/16 TSKaigi Kansai @sugar235711

Slide 2

Slide 2 text

2 sugar cat(@sugar235711) 仕事: SRE(オブザーバビリティ、インフラ構築) 興味: セキュリティ、パフォーマンスチューニング 登壇者情報 @sugar235711 @sugar-cat7

Slide 3

Slide 3 text

3 この発表ではアプリケーションログを扱います。 ※アクセスログや監査ログ、システムログのようなものは扱いません。 この発表で扱うログ

Slide 4

Slide 4 text

4 構造化ロギングを行うためのロギングライブラリ ● Node.js/ブラウザどちらも対応 ● 外部ライブラリへの依存なし ● コードベースがTypeScript tslog概要

Slide 5

Slide 5 text

5 構造化ロギングを行うためのロギングライブラリ ● Node.js/ブラウザどちらも対応 ● 外部ライブラリへの依存なし ● コードベースがTypeScript tslog概要

Slide 6

Slide 6 text

6 tslogでは2種類のログの形式での出力が可能 tslogと構造化ロギング Pretty JSON

Slide 7

Slide 7 text

7 デフォルトの設定のままシンプルにJSON形式でログを出力する tslogの内部実装について

Slide 8

Slide 8 text

8 デフォルトの設定のままシンプルにJSON形式でログを出力する tslogの内部実装について

Slide 9

Slide 9 text

9 デフォルトの設定のままシンプルにJSON形式でログを出力する tslogの内部実装について

Slide 10

Slide 10 text

10 デフォルトの設定のままシンプルにJSON形式でログを出力する tslogの内部実装について 内部関数

Slide 11

Slide 11 text

11 デフォルトの設定のままシンプルにJSON形式でログを出力する tslogの内部実装について 内部関数

Slide 12

Slide 12 text

12 デフォルトの設定のままシンプルにJSON形式でログを出力する tslogの内部実装について 内部関数

Slide 13

Slide 13 text

13 デフォルトの設定のままシンプルにJSON形式でログを出力する tslogの内部実装について これらのメソッドは オーバーライド可能

Slide 14

Slide 14 text

14 デフォルトの設定のままシンプルにJSON形式でログを出力する tslogの内部実装について これらのメソッドは オーバーライド可能

Slide 15

Slide 15 text

15 意図せず個人情報がログに含まれストレージに保存されているというのは よくある 一度保存されたログを削除したり、アーカイブ済みのものを操作するには コストや時間がかかる ログに含まれる秘匿情報について

Slide 16

Slide 16 text

16 意図せず個人情報がログに含まれストレージに保存されているというのは よくある 一度保存されたログを削除したり、アーカイブ済みのものを操作するには コストや時間がかかる ログに含まれる秘匿情報について 出力前にマスキング or 意図しないフィールドであれば 削除する

Slide 17

Slide 17 text

17 デフォルトでマスクキングを行える機構が 備わっている tslogでマスキングをする

Slide 18

Slide 18 text

18 デフォルトでマスクキングを行える機構が 備わっている 再帰的にネストされたオブジェクトを探索 し、文字列の場合にreplaceを挟む あらゆる型、正規表現に対応するために重 そうな実装をしている tslogでマスキングをする

Slide 19

Slide 19 text

19 デフォルトでマスクキングを行える機構が備わっている 再帰的にネストされたオブジェクトを探索し、文字列の場 合にreplaceを挟む あらゆる型、正規表現に対応するために重そうな実装をし ている tslogでマスキングをする

Slide 20

Slide 20 text

20 あらかじめキーが分かっている場合であれば有用だが、意図せず混入した フィールドをマスキングするのは難しい 不要なフィールドを取り除く

Slide 21

Slide 21 text

21 あらかじめキーが分かっている場合であれば有用だが、意図せず混入したフィールドをマスキングす るのは難しい 不要なフィールドを取り除く ログ出力時の型を定義し制御できないか🤔 ユーザー入力を Parse 標準出力前に挟む文字列化するタ イミングでフィルタリング

Slide 22

Slide 22 text

22 あらかじめキーが分かっている場合であれば有用だが、意図せず混入したフィールドをマスキングす るのは難しい 不要なフィールドを取り除く ログ出力時の型を定義し制御できないか🤔 ユーザー入力を Parse →ZodでParse 標準出力前に挟む文字列化するタ イミングでフィルタリング

Slide 23

Slide 23 text

23 あらかじめキーが分かっている場合であれば有用だが、意図せず混入したフィールドをマスキングす るのは難しい 不要なフィールドを取り除く ログ出力時の型を定義し制御できないか🤔 ユーザー入力を Parse →ZodでParse 標準出力前に挟む文字列化するタ イミングでフィルタリング →JSON.stringifyの第二引数 (replacerでフィルタリング )

Slide 24

Slide 24 text

24 あらかじめキーが分かっている場合であれば有用だが、意図せず混入したフィールドをマスキングす るのは難しい 不要なフィールドを取り除く ログ出力時の型を定義し制御できないか🤔 標準出力前に挟む文字列化するタ イミングでフィルタリング →JSON.stringifyの第二引数 (replacerでフィルタリング ) ログ内部で付加される暗黙的 なメタデータについても最終 的な出力の型が決まっていれ ばフィルタリングができそう

Slide 25

Slide 25 text

25 あらかじめキーが分かっている場合であれば有用だが、意図せず混入したフィールドをマスキングす るのは難しい 不要なフィールドを取り除く ログ出力時の型を定義し制御できないか🤔 標準出力前に挟む文字列化するタ イミングでフィルタリング →JSON.stringifyの第二引数 (replacerでフィルタリング ) ログ内部で付加される暗黙的 なメタデータについても最終 的な出力の型が決まっていれ ばフィルタリングができそう →出力の型から特定のフィー ルドを含まない含むのバリ デーションを自動生成できな いだろうか?

Slide 26

Slide 26 text

26 TypeScriptの型情報を元にコンパイル時にValidationを生成することがで きるライブラリ Typia

Slide 27

Slide 27 text

27 tscでコンパイルするとバリデーションされたstringifyが使える 型情報からフィルタリングをする

Slide 28

Slide 28 text

28 型を決めtscでコンパイルするとバリデーションされたstringifyが使える 型情報からフィルタリングをする コンパイル後

Slide 29

Slide 29 text

29 型を決めtscでコンパイルするとバリデーションされたstringifyが使える 型情報からフィルタリングをする コンパイル後 バリデーションの ロジックが生成さ れている

Slide 30

Slide 30 text

30 型を決めtscでコンパイルするとバリデーションされたstringifyが使える 型情報からフィルタリングをする transportの処理を オーバライド

Slide 31

Slide 31 text

31 型を決めtscでコンパイルするとバリデーションされたstringifyが使える 型情報からフィルタリングをする transportの処理を オーバライド stringifyはrequiredな フィールドが欠けている 場合errorが投げられる のでisで安全に処理

Slide 32

Slide 32 text

32 型を決めtscでコンパイルするとバリデーションされたstringifyが使える 型情報からフィルタリングをする 余分なフィールドが 除去されログが出力される (secret: “password”)

Slide 33

Slide 33 text

33 A.transportJSONをJSON.stringifyにした場合 B.transportJSONをJSON.stringify + loggerに渡すObjectをzodでパースした場合 C.transportJSONをtypiaを使用したstringifyにした場合 [条件] 実行環境 アプリケーションサーバー(Node.js)が動くコンテナ(CPU 1、Memory 512MB)とリクエストを送るコン テナを用意し、autocannonで負荷をかける 負荷のかけ方 最初の3秒間でウォームアップを行い、その後30秒間にわたり、100同時接続しつつ10リクエストをパイプ ライン化して送信。コンテナを作り直し5回繰り返す 比較の仕方 30秒間で得た総処理数からrpsを計算 各手法の実行速度比較

Slide 34

Slide 34 text

34 A.transportJSONをJSON.stringifyにした場合 B.transportJSONをJSON.stringify + loggerに渡すObjectをzodでパースした場合 C.transportJSONをtypiaを使用したstringifyにした場合 各手法の実行速度比較結果

Slide 35

Slide 35 text

35 A.transportJSONをJSON.stringifyにした場合 B.transportJSONをJSON.stringify + loggerに渡すObjectをzodでパースした場合 C.transportJSONをtypiaを使用したstringifyにした場合 各手法の実行速度比較結果 ・BのZodを挟む場合は明らかに処理性能が落ちている ・A、Cのパターンではほぼ変わらない →渡されたオブジェクトが小さい、別の処理がボトル ネックとなり、stringifyの性能の差ではあまり影響が なかった (Profileの結果console.logやstream関連の内部関数の 実行が支配的だった)

Slide 36

Slide 36 text

36 A.transportJSONをJSON.stringifyにした場合 B.transportJSONをJSON.stringify + loggerに渡すObjectをzodでパースした場合 C.transportJSONをtypiaを使用したstringifyにした場合 各手法の実行速度比較結果 ・BのZodを挟む場合は明らかに処理性能が落ちている ・A、Cのパターンではほぼ変わらない →渡されたオブジェクトが小さい、別の処理がボトル ネックとなり、stringifyの性能の差ではあまり影響が なかった (Profileの結果console.logやstream関連の内部関数の 実行が支配的だった) →Typiaを使用する方法がセキュリティ、パフォーマン ス共に良い結果となった

Slide 37

Slide 37 text

37 tslogとTypiaを組み合わせセキュアでハイパフォーマンスな構造化ロ ギングを行おう まとめ