新消息:在TwitterMastodon取得專案更新

常見問題 (FAQ)

在本頁面中,您將找到關於 cert-manager 的一些常見問題的解答。

術語

公開信任自我簽署 是什麼意思?

這些術語定義在 TLS 術語頁面中。

術語 中繼 憑證是什麼意思?

這些術語定義在 TLS 術語頁面中。

憑證

我可以隨時從 cert-manager 觸發續簽嗎?

這是從 v0.16 開始,使用 cmctl CLI 的 cert-manager 中的一項功能。更多資訊可以在 續簽命令頁面上找到

憑證何時會重新發行?

為了判斷是否需要重新發行憑證,cert-manager 會查看 Certificate 資源的規格和最新的 CertificateRequest,以及包含 X.509 憑證的 Secret 中的資料。

如果發生以下情況,將始終觸發發行過程

  • Certificate 的規格上命名的 Secret 不存在、缺少私鑰或憑證資料或包含損毀的資料
  • 儲存在 Secret 中的私鑰與 Certificate 上的私鑰規格不符
  • 已簽發憑證的公鑰與儲存在 Secret 中的私鑰不符
  • Secret 上的 cert-manager 簽發者註解與 Certificate 上指定的簽發者不符
  • 已簽發憑證上的 DNS 名稱、IP 位址、URL 或電子郵件地址與 Certificate 規格上的不符
  • 憑證需要續簽(因為它已過期,或者續簽時間是現在或過去)
  • 憑證已手動標記為續簽 使用 cmctl

此外,如果找到 Certificate 的最新 CertificateRequest,如果發生以下情況,cert-manager 也會重新發行

  • CertificateRequest 上找到的 CSR 上的通用名稱與 Certificate 規格上的不符
  • CertificateRequest 上找到的 CSR 上的主體欄位與 Certificate 規格的主體欄位不符
  • CertificateRequest 上的持續時間與 Certificate 規格上的持續時間不符
  • Certificate 規格上的 isCA 欄位值與 CertificateRequest 上的不符
  • CertificateRequest 規格上的 DNS 名稱、IP 位址、URL 或電子郵件地址與 Certificate 規格上的不符
  • CertificateRequest 規格上的金鑰用法與 Certificate 規格上的不符

請注意,對於某些欄位,只有當 cert-manager 可以用來判斷自上次發行以來 Certificate 的規格是否已變更時,才會觸發變更時重新發行。這是因為某些簽發者可能不尊重這些欄位的要求值,因此我們無法依賴已簽發 X.509 憑證中的值。其中一個欄位是 .spec.duration - 只有當有 CertificateRequest 可供比較時,對此欄位的變更才會觸發重新發行。如果您需要重新發行,但由於沒有 CertificateRequest(例如在備份和還原之後),而未自動觸發重新發行,則可以使用 cmctl renew 來手動觸發。

為什麼我的根憑證不在我已簽發的 Secret 的 tls.crt 中?

有時,人們會使用在 TLS 鏈方面做出錯誤選擇的系統。TLS 規格在 TLS 交握的「伺服器憑證」區段中具有以下內容

這是一連串 (鏈) 憑證。寄件者的憑證必須在清單中第一個出現。每個後續憑證都必須直接證明其前一個憑證。由於憑證驗證需要獨立分發根金鑰,因此指定根憑證授權單位的自我簽署憑證可以從鏈中省略,前提是假設遠端端點必須已經擁有它才能在任何情況下驗證它。

在標準、安全且正確設定的 TLS 環境中,幾乎總是沒有必要且浪費地將根憑證新增到鏈中。

憑證可以透過兩種方式信任

  • 透過將其包含在信任儲存區中來明確信任。
  • 透過簽名,透過追蹤憑證的鏈回到明確信任的憑證。

至關重要的是,根憑證根據定義是自我簽署的,並且無法透過簽名進行驗證。

因此,如果我們有一個客戶端試圖驗證伺服器傳送的憑證鏈,客戶端必須在連線開始之前就已擁有根。如果客戶端已經擁有根,則伺服器傳送它就沒有意義了!

伺服器在嘗試驗證用戶端憑證時,不傳送根憑證的邏輯也適用;TLS RFC 中提供了相同的理由。

為什麼我發行的 Secret 的 ca.crt 中沒有我的憑證鏈?

使用者經常詢問我們關於變更 ca.crt 以包含更多憑證或不同憑證的問題。我們通常會拒絕這些請求,原因很簡單,我們認為 ca.crt 對於任何使用者來說,通常都是一個風險。

ca.crt 由 cert-manager 填入發行 CA 的「最佳猜測」。重要的是,cert-manager 通常只能猜測;如果發行者沒有提供包含根憑證的完整鏈,cert-manager 可能無法知道鏈的根是什麼。在這種情況下,cert-manager 會盡力嘗試使用鏈中最深層的發行者。

這種「盡力而為」的嘗試是 ca.crt 可能有風險的原因之一;它可能不正確,並且即使 cert-manager 中沒有任何變更,當發行者變更時,它也可能會變更。

ca.crt 的另一個根本問題是 - 它會在憑證更新時更新。有些使用者可能會想要將 ca.crt 用於信任目的,但安全地輪換信任的憑證,需要能夠同時信任舊的和新的 CA 憑證。

透過直接從您的 Secret 取用 CA,這變得不可能;ca.crt 將永遠只包含目前憑證的 CA 的最佳猜測,並且永遠不會包含較舊或新的 CA。

cert-manager 會將所有事件發佈到 Kubernetes 事件機制,您可以使用 kubectl describe <資源> <名稱> 來取得特定資源的事件。

由於 Kubernetes 事件機制的性質,這些事件會在一段時間後被清除。如果您使用專用的日誌記錄系統,它可能能夠或已經在儲存 Kubernetes 事件。

如果發行失敗會發生什麼事?會重試嗎?

cert-manager 將會重試失敗的發行,除了少數需要手動介入的極端情況之外。

如果發生網路連線錯誤等暫時性故障,我們的目標是在短暫延遲後重試,而在發生「終端」故障後,則以較長且呈指數級增加的延遲重試。

如果 CertificateIssuing 條件設定為 false 並且設定了 status.lastFailureTime,您可以觀察到最新的發行已終端失敗。在這種情況下,將會在經過指數級增加的延遲(1 到 32 小時)後,透過建立新的 CertficateRequest 來重試發行。您可以使用 cmctl renew 命令觸發立即更新。如果發行者將 CertificateRequest 設定為失敗(例如,如果 CA 因為達到速率限制而拒絕請求),或者無效,或者如果 CertificateRequest 被核准者拒絕,就會發生終端失敗。

暫時性故障會導致在短暫延遲(最多 5 分鐘)後重新同步相同的 CertificateRequest。通常只能在 cert-manager 控制器日誌中觀察到它們。

如果發行看起來卡住了,而且 cmctl renew 無法運作,您可以刪除最新的 CertificateRequest。這大多是一個無害的動作(最壞的情況是,如果有一個可能成功的發行正在進行中,則會重複發行),但我們的目標是讓這不要成為使用者流程的一部分 - 如果您認為您發現了可以改進流程的情況,請與我們聯繫。

是否支援 ECC(橢圓曲線密碼學)?

cert-manager 支援 ECDSA 金鑰對!您可以在 Certificate 資源的 privateKey 部分中,將您的憑證設定為使用 ECDSA。

例如

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ecdsa
spec:
secretName: ecdsa-cert
isCA: false
privateKey:
algorithm: ECDSA
size: 256
dnsNames:
- ecdsa.example.com
issuerRef:
[...]

如果未定義 renewBeforeduration,預設值會是什麼?

預設的 duration90 天。如果未設定 renewBeforeCertificate 將會在其實際期限的 2/3 時更新。

為什麼 JKS 或 PKCS#12 檔案上的密碼沒有幫助?

這個問題有很多種形式,包括

  • 「為什麼可以將這些密碼硬編碼?」
  • 「我需要保護這些密碼嗎?」
  • 「這些密碼是以安全的方式使用嗎?」

具體來說,這個常見問題解答討論的是 PKCS#12 和 JKS「金鑰儲存區」的密碼。

簡單的答案

PKCS#12 或 JKS 檔案上的「密碼」幾乎總是安全性的虛晃一招,它們只是為了支援無法解析這些檔案無密碼版本的應用程式所需要的。即使您為這些檔案使用安全密碼(這很少見),弱加密演算法和基礎資料的管理通常會使安全密碼失效。

我們建議您將這些密碼視為舊版實作細節,並且在您被迫使用密碼時,對這些密碼使用簡短的硬編碼字串。不要花時間嘗試為這些檔案產生或處理「安全」密碼 - 只需選擇一個常數,例如 changeitnotapassword123,並將其用於您產生的每個 PKCS#12 或 JKS 組合。

更長的答案

很多人在處理 JKS 或 PKCS#12 組合時看到「密碼」這個詞,他們很自然地得出結論,認為這是一個有價值的安全資源,需要小心處理。

一般來說,情況並非如此 - 這些密碼不僅不是真正的密碼,而且它們也極不可能對任何類型的安全有意義。

大多數情況下,這些密碼的存在只是因為某些應用程式需要設定一些密碼。這個需求是 cert-manager 及其子專案支援在這些類型的組合上設定密碼的唯一原因。

我們不認為這些密碼對安全至關重要,主要有幾個原因

  1. 大多數使用這些密碼的應用程式都會在與使用該密碼的組合相同的權限和存取控制下,以純文字格式將包含密碼的檔案掛載在旁邊。這會使即使是最安全的密碼也完全失去作為安全措施的意義。
  2. 大多數加密的 PKCS#12 和 JKS 組合都使用極其老舊且基本上不安全的加密演算法。
  3. 「密碼」這個詞會讓人們想到人類可記憶的密碼,這不適合這種加密。這表示在此環境中使用的密碼本身通常是不安全的。
  4. 當我們產生 PKCS#12 或 JKS 檔案時,它們幾乎總是和未加密的私鑰一起存在於同一個 Secret 中!

若沒有非常詳盡的威脅模型,並且極度偏執地花費大量時間在系統架構上,那麼花時間處理這些「密碼」將會是浪費時間且幾乎沒有回報的誤導。您幾乎總是能透過其他方法來更好地保護系統。

請參閱上方「簡單解答」以取得這些「密碼」的使用指南。

雜項

Kubernetes 內建 CertificateSigningRequest API。為什麼不使用它?

Kubernetes 具有 憑證簽署請求 API,以及一個 kubectl certificates 命令,可讓您核准憑證簽署請求,並由 Kubernetes 叢集的憑證授權單位 (CA) 簽署。

這個 API 和 CLI 偶爾會被誤用來簽署非控制平面 Pod 使用的憑證,但這是錯誤的。為了 Kubernetes 叢集的安全,限制對 Kubernetes 憑證授權單位的存取非常重要,而且您不應使用該憑證授權單位來簽署在控制平面之外使用的憑證,因為此類憑證會增加攻擊 Kubernetes API 伺服器的機會。

在 Kubernetes 1.19 中,憑證簽署請求 API 已達到 V1 版本,並且可以通過遵循(或自動化)請求簽署流程來更廣泛地使用。

cert-manager 目前對此資源提供一些有限的實驗性支援

如何寫「cert-manager」

cert-manager 應始終以小寫形式書寫。即使在標題或句子開頭等通常會大寫的地方也一樣。單字之間應始終使用連字號,不要將其替換為空格,也不要刪除它。