題目與適用場景
設計一個面向多租戶平台的 Secrets 管理服務。Secret 可以是資料庫認證資訊、API Token、私鑰或憑證。 系統保存 2,000 萬個活躍 Secret 名稱,平均每個保留 3 個版本;值平均為 2 KiB,最大不超過 64 KiB。 尖峰流量為每秒 10 萬次讀取和 2,000 次版本寫入。Secret 所屬區域內的成功讀取 p99 應低於 50 毫秒。
每個區域跨 3 個可用區部署。所屬區域已經確認的寫入必須承受 1 個可用區故障。整個區域失效後的災難 復原目標是 RTO 15 分鐘、RPO 1 分鐘。這些規模和目標都是面試假設,不是任何商業 Secrets 產品公開的 效能上限。如果業務要求區域級故障後也不遺失任何已確認寫入,候選人必須明確採用同步跨區域共識或 等價的持久性邊界,並承擔相應的延遲與可用性代價。
威脅模型包括資料庫快照被竊、備份外洩、跨租戶授權錯誤、一般儲存層維運人員越權、明文誤入日誌,以及 單一資料面主機被攻破。系統不聲稱能阻止一個已經獲准取值的工作負載使用該值;它要縮小工作負載權限、 縮短認證資訊壽命、保留存取歸因,並限制單點失陷的爆炸半徑。
範圍包括工作負載驗證、政策評估、靜態與動態 Secret、加密、不可變版本、分階段輪替、撤銷、租約、 稽核、複寫和復原。組織身分提供者、真正接受動態認證資訊的資料庫,以及通用密碼學金鑰管理服務屬於外部 依賴。2026 年仍可存取的安全工程面試資料包含「設計 Secrets 管理服務」這一道具體系統設計題,也把微服務 Secrets 管理系統列為安全系統設計練習。這能說明題目的當前代表性,不能證明任何特定公司的出題頻率。
面試官考察重點
第一項訊號是能否定義準確的保護邊界。只說「資料庫加密」可能讓解密金鑰與密文放在同一邊界,也沒有 說明哪類失陷會被隔離。優秀答案會拆開由 HSM 或 KMS 保護的根、租戶級金鑰加密金鑰、每版本資料加密 金鑰和一般密文儲存層,並指出明文會在哪些位置短暫出現。
第二項訊號是每次請求都經過授權。租戶隔離不能依賴呼叫端提供的路徑前綴。服務應從已驗證身分推導 租戶、工作負載、環境和角色,對準確資源與動作執行版本化政策,並把這些事實寫入稽核事件。驗證、授權、 加密與稽核是四類不同控制。
第三項訊號是生命週期推理。建立新 Secret 值、更換密碼學封裝金鑰、修改外部資料庫接受的認證資訊是三種 不同操作。跨外部系統的輪替不是一筆原子資料庫交易,需要持久階段、重疊規則、冪等、驗證、補償與對帳。
第四項訊號是如實說明撤銷語意。拒絕後續讀取不能抹除程序已經複製的靜態密碼。有效的緊急撤銷還要在 真正接受認證資訊的系統中停用或輪替它。動態認證資訊可以提供更強的到期與撤銷語意,因為目標系統參與租約。
最後要平衡延遲、安全和可用性。讓每秒 10 萬次讀取逐次存取 HSM,通常會把信任根變成錯誤的瓶頸; 把明文放進共享分散式快取也不是正確補救。答案應使用金鑰階層、範圍受控的保護記憶體快取、明確的政策 陳舊上限和經過驗證的故障語意。
回答前需要釐清的問題
- 支援哪些 Secret 類型? 不透明靜態值需要版本儲存;資料庫使用者和憑證還可能支援動態簽發與目標端撤銷。
- 誰可以讀取 Secret? 優先使用工作負載身分和短時工作階段。若允許人直接查看,必須增加審批、二次驗證和獨立稽核政策。
- 撤銷承諾是什麼? 服務可以立即拒絕新讀取;讓已經複製的靜態值失效,需要下游系統輪替或停用該認證資訊。
current需要怎樣的一致性? 本方案讓所屬區域內每個 Secret 的發布與撤銷線性一致;呼叫端也可明確請求不可變版本。- 區域故障是否要求零資料遺失? 題設 DR RPO 為 1 分鐘。RPO 為零需要同步跨區域確認,會改變延遲和可用性取捨。
- 應用程式能否在服務故障時使用本機快取? 只有明確政策才可允許部分靜態 Secret 使用加密、限時的 Agent 快取,並承認即時撤銷會變弱。
- 值與版本有多大? 題設限制單值 64 KiB,平均保留 3 個版本。大型文件應進入另一套加密物件儲存設計。
- 稽核必須記錄什麼? 主體、工作負載、租戶、資源識別碼、動作、政策版本、結果、請求 ID、區域和時間,絕不記錄明文值。
- 誰能管理信任根? 需要職責分離、多人批准的緊急存取和復原演練。日常使用的萬能管理員會破壞租戶隔離。
30 秒回答框架
「我會把政策與寫入控制面和低延遲讀取資料面分開。工作負載先用短時平台身分驗證;服務從身分推導租戶, 再對準確 Secret 與動作執行版本化最小權限政策。每個不可變版本使用隨機資料金鑰和驗證式加密,資料金鑰由 租戶金鑰封裝,HSM 或 KMS 保護解封裝租戶金鑰的根;一般儲存層只能看到密文與被封裝金鑰。區域交易共識透過 比較更新,原子追加版本並移動 current 指標。輪替採用建立、安裝、驗證、發布、重疊和退役的持久工作流, 因為外部目標無法加入同一交易。動態認證資訊帶有可續期或撤銷的租約。我會快取密文,只在強化服務記憶體中 短時快取解封裝金鑰,絕不使用共享明文快取。稽核進入獨立保護的追加式管線。驗證涵蓋跨租戶拒絕、並行發布、 金鑰遺失、KMS 故障、撤銷卡住、日誌外洩和完整區域復原。」
分步深入解答
第一步:把題目轉成不變量和威脅邊界
先確定五條不變量:
1. A request can address only a tenant derived from authenticated identity.
2. Ordinary databases, queues, logs, traces, and backups never receive plaintext values or plaintext keys.
3. A published version is immutable; promotion only changes a version pointer.
4. Every allow and deny decision emits an audit event without the value.
5. Acknowledged regional writes survive one availability-zone failure.這些不變量仍然留下殘餘風險:獲准工作負載會拿到明文;資料面程序會短暫持有解封裝金鑰與明文;惡意信任根 管理員可能超越一般政策。可用短時身分、窄政策、程序隔離、停用 core dump、保護記憶體、獨立稽核、職責 分離和更小金鑰作用域降低風險。不能聲稱靜態加密解決了執行期失陷。
第二步:分開控制面和讀取資料面
控制面管理租戶、政策、Secret 中繼資料、新版本、輪替任務、審批和緊急動作。它的寫入量較低,更強調嚴格 驗證和可稽核工作流。資料面負責驗證工作負載、評估政策、解密獲准版本並透過雙向驗證 TLS 傳回,熱路徑 必須保持精簡。
每個租戶有一個所屬區域,權威 Secret 與政策寫入都在此完成。區域內跨 3 個可用區的交易共識提交中繼資料、 密文、版本指標、租約、冪等記錄與稽核 outbox。讀取節點可以水平擴充,但 current 讀取要存取強一致儲存層, 或使用已經證明讀屏障的副本;陳舊副本不得復活已撤銷版本。
身分來自平台身分提供者,例如工作負載憑證或簽名服務帳號 Token。Secrets 服務驗證簽發者、受眾、到期時間、 工作負載識別碼和通道綁定,再把可信身分對應為租戶與角色。用戶端不能透過請求標頭覆寫這個租戶。
第三步:定義精簡 API 與不可變資料模型
一組可用的核心 API 是:
POST /v1/secrets/{path}/versions
{ value, idempotencyKey, expectedCurrentVersion? }
-> { secretId, version, status: "PENDING" }
POST /v1/secrets/{path}/versions/{version}/promote
{ expectedCurrentVersion, idempotencyKey }
-> { currentVersion }
GET /v1/secrets/{path}?version=current
-> { value, version, expiresAt? }
POST /v1/dynamic/{role}/credentials
{ requestedTtl, idempotencyKey }
-> { value, leaseId, expiresAt, renewable }
POST /v1/leases/{leaseId}/renew
POST /v1/leases/{leaseId}/revoke路徑是資源名稱,不是授權證據。伺服器端只做一次正規化,拒絕歧義編碼,從身分推導租戶,並檢查動作級政策。
Secret(secret_id, tenant_id, canonical_path, state,
current_version, policy_ref, created_at)
SecretVersion(secret_id, version, status, ciphertext, nonce, auth_tag,
wrapped_dek, tenant_kek_version, content_fingerprint_hmac,
created_by, created_at)
Policy(policy_id, tenant_id, version, document, state, created_at)
Lease(lease_id, tenant_id, secret_id, principal_id, target_ref,
status, expires_at, renewable_until, last_error)
Idempotency(tenant_id, principal_id, operation, key,
request_fingerprint_hmac, result_ref, expires_at)(tenantid, canonicalpath) 與 (secret_id, version) 分別唯一。版本資料列的加密承載內容永不修改。發布 透過 current_version 條件更新完成;兩個管理員都從版本 7 發起發布時,不能互相靜默覆蓋。稽核 outbox 與每次狀態變更在同一交易提交,再匯出到獨立控制的儲存層。指紋必須使用獨立租戶金鑰計算帶金鑰 HMAC, 不能直接保存低熵認證資訊的一般雜湊,否則被竊快照可以離線猜測原值。
第四步:建立信封加密金鑰階層
每個版本產生隨機資料加密金鑰,使用驗證式加密演算法加密 Secret 值。把 tenantid、secretid、版本與 演算法識別碼作為附加驗證資料綁定,密文被移動到另一個租戶或版本時就會驗證失敗。密文、nonce、驗證 Tag 和被封裝的資料金鑰一起保存。
每個租戶擁有一個或多個版本化金鑰加密金鑰。由 HSM 或雲端 KMS 保護的根,只為獲准資料面節點解封裝這些 租戶金鑰;租戶金鑰再封裝每個版本的資料金鑰。因此一般儲存層快照缺少解密材料。單一資料面主機被竊會 暴露該程序當時持有的租戶金鑰和資料金鑰,節點放置與快取作用域必須限制它能服務多少租戶。
HSM/KMS root
-> unwrap tenant KEK version
-> unwrap per-secret-version DEK
-> AEAD-decrypt secret value with bound tenant/version metadata每次讀取都呼叫 HSM 會讓根服務成為延遲和吞吐瓶頸。資料面節點可以按租戶風險分區,在強化記憶體中短時 快取解封裝後的租戶金鑰或資料金鑰;政策或金鑰事件到達以及程序結束時清除。共享 Redis、磁碟 swap、 當機傾印、日誌與 Trace 都不能接收明文或解封裝金鑰。
更換租戶封裝金鑰時,可以重新封裝資料金鑰而無須解密每個 Secret 值。修改資料庫密碼則會建立新的 Secret 值,並與資料庫協調。兩者爆炸半徑不同,不能共用一個含糊的「輪替」按鈕。
第五步:讓授權與快取理解撤銷
政策定義 create-version、promote、read、issue-dynamic、renew、revoke 和 administer-policy 等動作, 可限制租戶、專案、環境、路徑、工作負載、網路區、時間和最大 TTL;明確拒絕優先。預設禁止人直接讀取 明文。獲准例外要記錄工單、審批者、理由和短時授權。
政策在本機評估以滿足延遲要求,但快取必須帶版本和最大壽命。撤銷政策或主體時,先提交變更,再發布失效 事件並推進租戶授權 epoch。讀取節點必須證明自己的 epoch 不低於要求。如果失效通道不可用且快取超過最大 壽命,敏感讀取應 fail closed,不能永久信任舊政策。
密文和不可變中繼資料可以廣泛快取,明文不可以。工作負載端 Agent 可以在宣告 TTL 內,把獲准值保存在自身 記憶體中,減少重複讀取。如果產品允許某些可用性關鍵的靜態 Secret 使用加密磁碟快取,就必須明確定義裝置 綁定金鑰、到期時間和較弱的撤銷承諾。控制面故障時盲目傳回舊值,不應成為通用降級方案。
第六步:把認證資訊輪替做成可復原工作流
跨目標資料庫的靜態認證資訊輪替遵循以下持久階段:
CREATED_PENDING
-> INSTALLED_AT_TARGET
-> VERIFIED
-> PROMOTED_CURRENT
-> OLD_VERSION_IN_OVERLAP
-> OLD_VERSION_REVOKED
-> COMPLETE每個轉移都有冪等 Connector 操作和已記錄證據。先建立新認證資訊,在目標端安裝,透過預期路徑驗證,再發布 新版本;若消費端需要則保留有限重疊,最終在目標端停用舊認證資訊。對帳 Worker 比較工作流和目標端狀態, 在當機後續跑。若安裝成功但回應遺失,查詢必須發現既有結果,不能再建立一份認證資訊。
若舊值疑似外洩,緊急輪替可以跳過重疊,這會造成應用程式中斷,需要事故範圍內的專用授權。只禁止讀取 儲存層中的舊版本還不夠,因為目標系統可能仍接受它。
動態 Secret 由 Connector 為工作負載建立唯一短時認證資訊並登記租約。續期要傳回實際新到期時間,它可能 短於請求值。到期或人工撤銷時,目標端必須讓認證資訊失效。若目標端無法連線,租約進入 REVOCATION_PENDING;持續重試、警示和人工 Runbook 都要保持有效。系統不能因為訊息已經進入佇列就把它 標記為撤銷成功。
第七步:計算容量並隔離熱點租戶
2,000 萬個名稱、每個保留 3 個版本、每個值 2 KiB,原始加密值約為:
20,000,000 × 3 × 2 KiB = 122,880,000,000 bytes ≈ 114 GiB如果每版本加密中繼資料平均再占 1 KiB,會增加約 57 GiB。區域內 3 副本的起始估算約為 513 GiB,尚未計算 索引、稽核、租約、冪等、備份和成長。這是題設推導出的容量基線,不是產品效能聲明。
每秒 10 萬次讀取、平均傳回 2 KiB,單是明文出口就接近 195 MiB/s,還沒有計入 TLS 與回應負擔。依穩定 租戶識別碼分片,再把異常熱點或受監管租戶放入獨立 Cell。設定租戶級並行和速率預算,避免一個被攻破的 工作負載耗盡所有解密 Worker 或稽核容量。
讀取延遲要拆成身分驗證、政策評估、中繼資料查詢、金鑰解封裝或快取、解密、稽核入列和網路時間。HSM Cache Miss 與稽核背壓應有獨立預算。不能為了保護 p99 靜默丟棄稽核;要麼使用持久本機或 outbox 邊界, 要麼在無法保留必要稽核記錄時拒絕敏感請求。
第八步:分別設計區域復原與信任根復原
把加密狀態與稽核 outbox 非同步複寫到暖備區域,並量測複寫延遲。提升暖備區域時使用 fencing epoch,避免 舊所屬區域復原後成為第二個主要寫入端。按照題設 1 分鐘 RPO,整個區域失效後,最新的部分已確認版本可能 需要重建;如果不可接受,就必須在確認前完成跨區域交易共識。
災難復原區域還需要獨立可用的信任根、工作負載身分、政策狀態和稽核出口。只複寫密文不算復原方案。要驗證 加密快照和時間點復原,並分開保護設定、啟動認證資訊和自動解封裝材料,因為即使資料快照已加密,這些設定 仍可能敏感。
信任根復原需要多人控制的緊急流程、職責分離、不可竄改證據和定期演練。遺失租戶金鑰可能永久失去該租戶 資料;外洩租戶金鑰可能暴露它封裝的全部版本,因此金鑰備份、輪替、放置和銷毀都必須有生命週期測試。
第九步:驗證安全屬性與故障語意
測試應圍繞不變量,而不只看正常延遲:
- 產生跨租戶路徑、編碼路徑、萬用字元政策和陳舊身分請求,證明全部被拒絕。
- 並行執行版本建立、發布、政策撤銷和讀取,確認陳舊節點不會傳回剛被禁止的版本。
- 掃描資料庫、佇列、日誌、Trace、當機傾印和備份中的誘餌明文與解封裝金鑰材料。
- 注入 KMS 延遲、金鑰快取清除、儲存共識遺失、稽核背壓和完整控制面故障。
- 在目標端動作前後中斷每個輪替階段,證明對帳能收斂且不會重複建立認證資訊或誤報完成。
- 讓動態 Secret 的目標端在到期時無法使用,證明租約持續顯示待撤銷,直到目標端失效完成。
- 從加密複寫與快照復原災難復原區域,驗證 fencing、身分、政策、金鑰、稽核、RTO 和實測 RPO。
- 以高度傾斜的租戶分布壓測每秒 10 萬次讀和 2,000 次寫,同時量測 p99、拒絕準確率、HSM 流量、
快取作用域和稽核完整性。
高品質示範回答
「我先明確系統防護儲存層、備份、跨租戶、日誌外洩和有限的主機失陷,但獲准工作負載仍可能濫用它拿到的值。 每個請求從短時工作負載身分開始。服務從身分推導租戶和工作負載,對準確資源與動作執行版本化政策;呼叫端 提供的路徑不能選中另一個租戶。
資料採用不可變版本。建立請求寫入待發布版本,發布透過比較預期舊版本,條件移動 Secret 的 current 指標。所屬區域跨 3 個可用區的共識,把密文、中繼資料、冪等記錄和稽核 outbox 一起提交。current 讀取 使用讀屏障,陳舊副本不能傳回已撤銷版本。
加密方面,每個版本產生隨機資料金鑰,用綁定租戶、Secret 與版本的驗證式加密處理。租戶金鑰封裝資料金鑰, HSM 或 KMS 保護的根只在獲准資料面節點解封裝租戶金鑰。一般儲存層與備份只含密文和被封裝金鑰。讀取節點 可以在依租戶隔離的強化記憶體中短時快取解封裝金鑰;明文永不進入共享快取、日誌、Trace、swap 或 core dump。
認證資訊輪替是一條狀態機:建立、在目標端安裝、驗證、發布、重疊、撤銷舊目標認證資訊、完成。每個 Connector 呼叫都冪等並參與對帳,因為外部資料庫無法加入中繼資料交易;疑似外洩時可取消重疊。動態認證 資訊按工作負載簽發並帶租約;只有目標端確認撤銷才算到期完成,否則系統保持可見待處理狀態並警示。
控制面負責政策、版本、審批和工作流;水平擴充的資料面 Cell 服務讀取。密文可以廣泛快取,政策快取有版本 與壽命,解封裝金鑰只短時保存在本機。區域失效時,加密狀態複寫到 RPO 1 分鐘的暖備區域,fencing epoch 阻止腦裂。如果需求變為 RPO 為零,我會同步跨區域提交,並接受更高延遲或更低寫入可用性。
最後驗證跨租戶和編碼路徑攻擊、並行發布與撤銷、全部觀測和備份表面的誘餌外洩、KMS 與稽核故障、輪替 每一步當機、租約撤銷卡住,以及完整災難復原。只有故障注入下的安全判斷仍正確,且每秒 10 萬次讀取仍 滿足拆解後的延遲預算,方案才算通過。」
常見錯誤
- 把一個資料庫加密金鑰放在資料庫旁邊 → 快照失陷可能同時取得密文和解密路徑 → 拆開 HSM/KMS 根、租戶封裝金鑰、每版本資料金鑰和一般儲存層。
- 信任請求裡的租戶或路徑 → 修改物件名稱就可能跨租戶存取 → 從可信身分推導租戶,只正規化一次並授權準確動作和資源。
- 為除錯記錄請求或回應正文 → 可觀測性系統會成為明文 Secret 倉庫 → 只記錄識別碼、決策與版本,並用誘餌值測試外洩。
- 每次讀取都存取 HSM → 信任根延遲與配額成為平台瓶頸 → 使用信封加密和明確爆炸半徑的限時保護記憶體快取。
- 把解密值放入 Redis → 延遲最佳化擴大了明文失陷邊界 → 廣泛快取密文,明文只進入獲准消費端的限時記憶體。
- 把輪替當成一次更新 → 目標端安裝與中繼資料提交可能一邊成功一邊失敗 → 採用持久分階段工作流、冪等 Connector、重疊規則和對帳。
- 訊息進入佇列就把租約標為已撤銷 → 下游認證資訊可能仍有效 → 在目標端確認失效前保持待處理,並對卡住撤銷警示。
- 承諾立即撤回已複製的靜態值 → 新讀取能被拒絕,既有副本仍可用 → 在接受系統輪替或停用,並優先使用短時動態認證資訊。
- 無限期使用陳舊政策並 fail open → 已移除主體可以繼續取值 → 為政策快取加版本、失效和最大壽命,超限後 fail closed。
- 複寫密文到另一個區域就宣稱完成 DR → 身分、根金鑰、政策、fencing 和稽核仍可能無法使用 → 驗證完整依賴圖並量測真實 RTO 與 RPO。
面試追問
追問一:Secrets 管理服務和 KMS 有什麼不同?
Secrets 管理服務儲存並版本化不透明認證資訊,授權取值,協調輪替,簽發租約並稽核存取。KMS 管理密碼學 金鑰,提供封裝或簽名等操作。本方案把 KMS 或 HSM 當成信任根,不把根金鑰作為一般可讀取 Secret 暴露。
追問二:應用程式可以快取 Secret 嗎?
可以,但必須有明確契約。Agent 可在有界 TTL 內把獲准值留在程序記憶體,並在到期前更新。這會降低讀取量 和可用性依賴,也會延長僅靠政策撤銷無法消除既有副本的時間窗。高風險或動態認證資訊應使用更短租約和 目標端撤銷,不能無限快取。
追問三:KMS 或 HSM 無法使用時怎麼辦?
節點只能在獲准快取壽命內繼續使用已經解封裝的金鑰。新租戶、Cache Miss 與根金鑰操作 fail closed。 監控快取涵蓋率、KMS 錯誤率與剩餘安全時間窗,在所有節點同時到期前主動限流。事故中延長金鑰壽命是需要 預先規則的安全決定,不能由重試迴圈自動完成。
追問四:怎樣在不解密每個 Secret 的情況下輪替租戶金鑰?
用舊租戶金鑰解封裝每版本資料金鑰,再用新租戶金鑰封裝;最好在可信金鑰服務內部完成,使明文資料金鑰不 離開邊界。記錄租戶金鑰版本和被封裝資料金鑰,為遷移設定檢查點,在所有參照與備份政策允許前保留舊租戶 金鑰。Secret 密文本身不需要改變。
追問五:如何阻止高權限維運讀取所有租戶 Secret?
分開政策管理、金鑰管理、基礎設施維運和稽核複核。預設關閉人類明文讀取;例外採用多人批准的短時授權; 受監管租戶使用獨立 Cell 與金鑰作用域;證據進入獨立稽核系統。任何日常角色都不應既能給自己授權,又能 在沒有外部證據時解密值。
追問六:所屬區域停機後,讀取是否應該繼續?
只有災難復原區域擁有已 fencing 的權威 epoch、足夠新的政策和加密資料、可用信任根,並且業務接受明確 RPO 時才繼續。任意陳舊副本可能復活撤銷權限。題設 RPO 1 分鐘時,依演練流程提升暖備區域;RPO 為零 需要事故前就啟用同步跨區域提交。
追問七:為什麼不只用環境變數保存 Secret?
環境變數是交付方式,不是生命週期管理。它可能透過程序檢查、當機傾印、診斷、子程序或部署設定外洩,也 缺少集中版本、目標端輪替、租約和逐次讀取歸因。若部署 Agent 注入環境變數,也要縮小範圍與壽命,並繼續 讓 Secrets 管理服務承擔政策與生命週期事實來源。