反序列化除錯 Proto 表示

如何在 Protocol Buffers 中記錄除錯資訊。

從版本 30.x 開始,Protobuf 的 DebugString API(Message::DebugStringMessage::ShortDebugStringMessage::Utf8DebugString),額外的 Protobuf API(proto2::ShortFormatproto2::Utf8Format),Abseil 字串函式(例如 absl::StrCatabsl::StrFormatabsl::StrAppendabsl::Substitute)以及 Abseil 日誌 API 將開始自動將 proto 引數轉換為新的除錯格式。請參閱此處的相關公告。

與 Protobuf DebugString 的輸出格式不同,新的除錯格式會自動透過將其值替換為字串“[REDACTED]”(不帶引號)來編輯敏感欄位。此外,為了確保 Protobuf TextFormat 解析器無法反序列化此新輸出格式,無論底層 proto 是否包含 SPII 欄位,我們都會新增一組指向本文的隨機連結和隨機長度的空白序列。新的除錯格式如下所示:

goo.gle/debugstr
spii_field: [REDACTED]
normal_field: "value"

請注意,新的除錯格式與 DebugString 格式的輸出格式僅在兩方面不同:

  • URL 字首
  • SPII 欄位的值被替換為“[REDACTED]”(不帶引號)

新的除錯格式從不刪除任何欄位名;如果欄位被認為是敏感的,它只會將其值替換為“[REDACTED]”。如果您在輸出中沒有看到某些欄位,那是因為這些欄位在 proto 中沒有設定。

提示:如果您只看到 URL 而沒有其他內容,則您的 proto 為空!

為什麼這個 URL 會在這裡?

我們希望確保沒有人會反序列化旨在用於人類除錯系統的 protobuf 訊息的人類可讀表示。歷史上,.DebugString()TextFormat 可以互換使用,現有系統使用 DebugString 來傳輸和儲存資料。

我們希望確保敏感資料不會意外地出現在日誌中。因此,我們正在透明地編輯 protobuf 訊息中的某些欄位值,然後將其轉換為字串(“[REDACTED]”)。這降低了意外日誌記錄帶來的安全和隱私風險,但如果其他系統反序列化您的訊息,則存在資料丟失的風險。為了解決此風險,我們有意將機器可讀的 TextFormat 與用於日誌訊息的人類可讀除錯格式分開。

這是有意的,目的是使您的 proto 的“調試表示”(例如,透過日誌記錄生成)與 TextFormat 不相容。我們希望防止任何人依賴除錯機制在程式之間傳輸資料。歷史上,除錯格式(由 DebugString API 生成)和 TextFormat 已被錯誤地互換使用。我們希望這一有意的工作能夠阻止這種情況的發生。

我們特意選擇了一個連結而不是不那麼明顯的格式更改,以便有機會提供上下文。這可能會在使用者介面中顯得突出,例如,如果您在網頁表格中顯示狀態資訊。您可以改用 TextFormat::PrintToString,它不會編輯任何資訊並保留格式。但是,請謹慎使用此 API——它沒有內建的保護措施。根據經驗,如果您正在將資料寫入除錯日誌或生成狀態訊息,則應繼續使用帶有連結的除錯格式。即使您目前沒有處理敏感資料,也要記住系統可能會更改並且程式碼會被重用。

我嘗試將此訊息轉換為 TextFormat,但我注意到每次程序重啟時格式都會改變。

這是有意為之的。請勿嘗試解析此除錯格式的輸出。我們保留更改語法的權利,恕不另行通知。除錯格式的語法會隨程序隨機更改,以防止無意中產生依賴。如果除錯格式的語法更改會破壞您的系統,則您很可能應該使用 TextFormat API,而不是使用 proto 的調試表示。

常見問題解答

我可以到處都使用 TextFormat 嗎?

請勿使用 TextFormat 生成日誌訊息。這將繞過所有內建保護,您可能會意外記錄敏感資訊。即使您的系統目前沒有處理任何敏感資料,這種情況也可能在將來發生變化。

透過酌情使用調試表示或 TextFormat,將日誌與用於其他系統進一步處理的資訊區分開來。

我希望編寫既可讀又可機器讀取的配置檔案

對於此用例,您可以顯式使用 TextFormat。您有責任確保您的配置檔案不包含任何 PII。

我正在編寫單元測試,並且希望在測試斷言中比較 Debugstring

如果要比較 protobuf 值,請使用 MessageDifferencer,如下所示:

using google::protobuf::util::MessageDifferencer;
...
MessageDifferencer diff;
...
diff.Compare(foo, bar);

除了忽略格式和欄位順序的差異外,您還將獲得更好的錯誤訊息。