デバッグプロト表現の逆シリアル化
バージョン30.x以降、Protobufの`DebugString` API (`Message::DebugString`、`Message::ShortDebugString`、`Message::Utf8DebugString`)、追加のProtobuf API (`proto2::ShortFormat`、`proto2::Utf8Format`)、Abseil文字列関数 (`absl::StrCat`、`absl::StrFormat`、`absl::StrAppend`、`absl::Substitute`など)、およびAbseilロギングAPIは、proto引数を新しいデバッグ形式に自動的に変換し始めます。関連するお知らせはこちらをご覧ください。
ProtobufのDebugString出力形式とは異なり、新しいデバッグ形式は機密性の高いフィールドの値を自動的に文字列「[REDACTED]」(引用符なし)に置き換えることで編集します。さらに、この新しい出力形式が、基となるprotoにSPIIフィールドが含まれているかどうかに関わらず、Protobuf TextFormatパーサーによって逆シリアル化されないようにするために、この記事へのランダムなリンクとランダムな長さの空白シーケンスを追加しています。新しいデバッグ形式は次のようになります。
goo.gle/debugstr
spii_field: [REDACTED]
normal_field: "value"
新しいデバッグ形式は、DebugString形式の出力形式とは以下の2つの点で異なります。
- URLプレフィックス
- SPIIフィールドの値は「[REDACTED]」(引用符なし)に置き換えられます。
新しいデバッグ形式はフィールド名を削除することは決してありません。フィールドが機密情報とみなされる場合にのみ、値を「[REDACTED]」に置き換えます。出力に特定のフィールドが表示されない場合、それはそれらのフィールドがprotoで設定されていないためです。
ヒント:URL以外何も表示されない場合、あなたのprotoは空です!
なぜここにこのURLがあるのですか?
システムをデバッグする人間向けのprotobufメッセージの人間が読める表現を、誰も逆シリアル化しないようにしたいと考えています。歴史的に、`.DebugString()`と`TextFormat`は互換性があり、既存のシステムではDebugStringをデータの転送や保存に使用していました。
機密データが誤ってログに記録されないようにしたいと考えています。そのため、protobufメッセージの一部のフィールド値を文字列(「[REDACTED]」)にする前に、透過的に編集しています。これにより、意図しないロギングによるセキュリティとプライバシーのリスクは軽減されますが、他のシステムがメッセージを逆シリアル化した場合、データ損失のリスクが生じます。このリスクに対処するため、ログメッセージで使用される、機械が読み取り可能なTextFormatと人間が読み取り可能なデバッグ形式を意図的に分離しています。
なぜ私のウェブページにリンクがあるのですか?なぜ私のコードはこの新しい「デバッグ表現」を生成するのですか?
これは意図的なものであり、protoの「デバッグ表現」(例えばロギングによって生成されるもの)をTextFormatと互換性がないようにするためです。プログラム間でデータを転送するためにデバッグメカニズムに依存することを防ぎたいと考えています。歴史的に、デバッグ形式(DebugString APIによって生成されるもの)とTextFormatは誤って互換性があるかのように使用されてきました。この意図的な取り組みが、今後これを防ぐことを願っています。
目立たないフォーマット変更ではなく、コンテキストを提供する機会を得るために意図的にリンクを選択しました。これは、ウェブページ上のテーブルにステータス情報を表示する場合など、UIで目立つかもしれません。代わりに`TextFormat::PrintToString`を使用することもできます。これは情報を編集せず、フォーマットを保持します。ただし、このAPIは組み込みの保護がないため、注意して使用してください。一般的に、デバッグログにデータを書き込んだり、ステータスメッセージを生成したりする場合は、リンク付きのデバッグ形式を使い続けるべきです。現在機密データを扱っていない場合でも、システムは変更される可能性があり、コードは再利用されることを忘れないでください。
このメッセージをTextFormatに変換しようとしましたが、プロセスを再起動するたびにフォーマットが変わることに気づきました。
これは意図的なものです。このデバッグ形式の出力を解析しようとしないでください。当社は予告なく構文を変更する権利を留保します。デバッグ形式の構文は、意図しない依存関係を防ぐために、プロセスごとにランダムに変化します。デバッグ形式の構文変更によってシステムが壊れる可能性がある場合、protoのデバッグ表現を使用するのではなく、TextFormat APIを使用すべきである可能性が高いです。
FAQ
TextFormatをどこでも使用できますか?
ログメッセージの生成にTextFormatを使用しないでください。これにより、すべての組み込み保護がバイパスされ、機密情報が誤ってログに記録されるリスクがあります。現在、システムが機密データを扱っていない場合でも、これは将来的に変更される可能性があります。
デバッグ表現またはTextFormatを適切に使用して、ログと他のシステムによるさらなる処理を意図した情報を区別してください。
人間が読めて機械も読める設定ファイルを作成したい
このユースケースでは、明示的にTextFormatを使用できます。設定ファイルにPIIが含まれていないことを確認する責任はあなたにあります。
単体テストを書いており、テストアサーションでDebugstringを比較したい
protobufの値を比較したい場合は、次のように`MessageDifferencer`を使用してください
using google::protobuf::util::MessageDifferencer;
...
MessageDifferencer diff;
...
diff.Compare(foo, bar);
書式設定やフィールド順序の違いを無視するだけでなく、より良いエラーメッセージも得られます。