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