ACME
ACME 簽發者類型代表在自動憑證管理環境 (ACME) 憑證授權伺服器上註冊的單一帳戶。當您建立新的 ACME Issuer
時,cert-manager 將會產生一個私鑰,用於在 ACME 伺服器上識別您的身分。
由公共 ACME 伺服器簽發的憑證通常預設受到客戶端電腦的信任。這表示,例如,瀏覽一個由為該 URL 簽發的 ACME 憑證所支援的網站,預設會被大多數客戶端的網頁瀏覽器信任。ACME 憑證通常是免費的。
解決挑戰
為了讓 ACME CA 伺服器驗證客戶端是否擁有網域,或正在請求憑證的網域,客戶端必須完成「挑戰」。這是為了確保客戶端無法為他們不擁有的網域請求憑證,並因此欺詐性地偽裝成其他人的網站。如 RFC8555 中詳述,cert-manager 提供兩種挑戰驗證方式 - HTTP01 和 DNS01 挑戰。
HTTP01 挑戰是透過呈現一個計算出的金鑰來完成的,該金鑰應該存在於 HTTP URL 端點,並且可以透過網際網路路由。此 URL 將使用為憑證請求的網域名稱。一旦 ACME 伺服器能夠從網際網路上的此 URL 取得此金鑰,ACME 伺服器就可以驗證您是此網域的所有者。當建立 HTTP01 挑戰時,cert-manager 將自動配置您的叢集入口 (ingress),以將此 URL 的流量路由到一個小的 Web 伺服器,該伺服器會呈現此金鑰。
DNS01 挑戰是透過提供一個計算出的金鑰來完成的,該金鑰存在於 DNS TXT 記錄中。一旦此 TXT 記錄已在網際網路上傳播,ACME 伺服器就可以透過 DNS 查詢成功檢索此金鑰,並且可以驗證客戶端擁有請求憑證的網域。憑藉正確的權限,cert-manager 將會自動為您指定的 DNS 提供者呈現此 TXT 記錄。
設定
建立基本的 ACME 簽發者
所有 ACME Issuers
都遵循類似的設定結構 - 客戶端的 email
、server
URL、privateKeySecretRef
以及一個或多個 solvers
。以下是一個簡單 ACME 簽發者的範例
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec:acme:# You must replace this email address with your own.# Let's Encrypt will use this to contact you about expiring# certificates, and issues related to your account.email: user@example.comserver: https://acme-staging-v02.api.letsencrypt.org/directoryprivateKeySecretRef:# Secret resource that will be used to store the account's private key.name: example-issuer-account-key# Add a single challenge solver, HTTP01 using nginxsolvers:- http01:ingress:ingressClassName: nginx
解題器以 dns01
和 http01
段落的形式出現。有關如何設定這些解題器類型的更多資訊,請參閱其各自的文件 - DNS01、HTTP01。
外部帳戶綁定
cert-manager 支援將外部帳戶綁定與您的 ACME 帳戶一起使用。外部帳戶綁定用於將您的 ACME 帳戶與外部帳戶(例如 CA 自訂資料庫)建立關聯。除非您明確知道需要它,否則大多數 cert-manager 使用者通常不需要此功能。
外部帳戶綁定在 ACME Issuer
上需要兩個欄位,代表您的 ACME 帳戶。這些欄位是
keyID
- 您的外部帳戶綁定依外部帳戶管理員建立索引的金鑰 ID 或帳戶 IDkeySecretRef
- 包含您的外部帳戶對稱 MAC 金鑰的 base 64 編碼 URL 字串的 Secret 名稱和金鑰
注意:在大多數情況下,MAC 金鑰必須以
base64URL
編碼。以下命令會對金鑰進行 base64 編碼並將其轉換為base64URL
$ echo 'my-secret-key' | base64 -w0 | sed -e 's/+/-/g' -e 's/\//_/g' -e 's/=//g'然後您可以使用以下程式碼建立 Secret 資源
$ kubectl create secret generic eab-secret --from-literal \secret={base64 encoded secret key}
以下是一個具有外部帳戶綁定的 ACME 簽發者範例。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: my-acme-server-with-eabspec:acme:email: user@example.comserver: https://my-acme-server-with-eab.com/directoryexternalAccountBinding:keyID: my-keyID-1keySecretRef:name: eab-secretkey: secretprivateKeySecretRef:name: example-issuer-account-keysolvers:- http01:ingress:ingressClassName: nginx
注意:cert-manager
v1.3.0
之前的版本也要求使用者透過設定Issuer.spec.acme.externalAccountBinding.keyAlgorithm
欄位來指定 EAB 的 MAC 演算法。此欄位現在已棄用,因為上游 Gox/crypto
函式庫將演算法硬式編碼為HS256
。(請參閱上游的相關討論CL#41430
)。
重複使用 ACME 帳戶
您可能希望在多個叢集中重複使用單一 ACME 帳戶。當使用 EAB 時,這可能特別有用。如果設定 disableAccountKeyGeneration
欄位,cert-manager 將不會建立新的 ACME 帳戶,並且會使用 privateKeySecretRef
中指定的現有金鑰。請注意,Issuer
/ClusterIssuer
將不會就緒,並且會持續重試,直到提供 Secret
。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: my-acme-server-with-existing-acme-accountspec:acme:email: user@example.comdisableAccountKeyGeneration: trueprivateKeySecretRef:name: example-issuer-account-key
新增多種解題器類型
您可能希望對不同的入口控制器使用不同類型的挑戰解題器設定,例如,如果您想使用 DNS01
發出萬用字元憑證,同時使用 HTTP01
驗證其他憑證。
solvers
段落有一個選用的 selector
欄位,可用於指定哪些 Certificates
,進一步來說,這些 Certificates
上的哪些 DNS 名稱應該用於解決挑戰。
可以使用三種選取器類型來形成 Certificate
必須滿足的要求,才能被選取為解題器 - matchLabels
、dnsNames
和 dnsZones
。您可以在單一解題器上使用這三種選取器的任意數量。
符合標籤
matchLabel
選擇器要求所有的 Certificates
必須匹配該段落字串映射列表中定義的所有標籤。例如,以下的 Issuer
只會匹配具有標籤 "user-cloudflare-solver": "true"
和 "email": "user@example.com"
的 Certificates
。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec:acme:...solvers:- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector:matchLabels:"use-cloudflare-solver": "true""email": "user@example.com"
DNS 名稱
dnsNames
選擇器是一個應映射到解析器的確切 DNS 名稱列表。這表示將會選取包含任何這些 DNS 名稱的 Certificates
。如果找到匹配項,則 dnsNames
選擇器將優先於 dnsZones
選擇器。如果有多個解析器與相同的 dnsNames
值匹配,則將選擇在 matchLabels
中具有最多匹配標籤的解析器。如果兩者都沒有更多匹配項,則將選擇列表中較早定義的解析器。
以下範例將為具有 DNS 名稱 example.com
和 *.example.com
的 Certificates
解決這些網域的挑戰。
注意:
dnsNames
採用完全匹配,且不解析萬用字元,這表示以下的Issuer
*將不會* 為諸如foo.example.com
等 DNS 名稱進行解析。請使用dnsZones
選擇器類型來匹配區域內的所有子網域。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec:acme:...solvers:- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector:dnsNames:- 'example.com'- '*.example.com'
DNS 區域
dnsZones
段落定義了此解析器可以解決的 DNS 區域列表。如果 DNS 名稱是完全匹配,或是任何指定 dnsZones
的子網域,則將使用此解析器,除非配置了更明確的 dnsNames
匹配項。這表示對於網域 www.sys.example.com
,將選取指定 sys.example.com
的解析器,而非指定 example.com
的解析器。如果有多個解析器與相同的 dnsZones
值匹配,則將選擇在 matchLabels
中具有最多匹配標籤的解析器。如果兩者都沒有更多匹配項,則將選擇列表中較早定義的解析器。
在以下範例中,此解析器將為網域 example.com
及其所有子網域 *.example.com
解決挑戰。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec:acme:...solvers:- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector:dnsZones:- 'example.com'
全部一起
每個解析器都可以定義任何數量的三種選擇器類型。在以下範例中,將使用 CloudFlare 的 DNS01
解析器來為包含 DNS 名稱 a.example.com
和 b.example.com
的 Certificates
解決網域的挑戰。將使用 Google CloudDNS 的 DNS01
解析器來為 DNS 名稱與區域 test.example.com
及其所有子網域(例如 foo.test.example.com
)匹配的 Certificates
解決挑戰。
對於所有其他挑戰,*只有*在 Certificate
也包含標籤 "use-http01-solver": "true"
的情況下,才會使用 HTTP01
解析器。
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-stagingspec:acme:...solvers:- http01:ingress:ingressClassName: nginxselector:matchLabels:"use-http01-solver": "true"- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector:dnsNames:- 'a.example.com'- 'b.example.com'- dns01:cloudDNS:project: my-project-idhostedZoneName: 'test-example.com'serviceAccountSecretRef:key: saname: gcp-sa-secretselector:dnsZones:- 'test.example.com' # This should be the DNS name of the zone
每個單獨的選擇器區塊可以包含多個選擇器類型,例如
solvers:- dns01:cloudflare:email: user@example.comapiKeySecretRef:name: cloudflare-apikey-secretkey: apikeyselector:matchLabels:'email': 'user@example.com''solver': 'cloudflare'dnsZones:- 'test.example.com'- 'example.dev'
在這種情況下,只有當 Certificate
具有來自 matchLabels
的標籤*且* DNS 名稱與來自 dnsZones
的區域匹配時,才會使用 Cloudflare 的 DNS01
解析器來解決 DNS 名稱的挑戰。
私人 ACME 伺服器
只要符合 ACME 規範,cert-manager 也應與私有或自行託管的 ACME 伺服器搭配使用。
如果您的 ACME 伺服器不使用公開信任的憑證,您可以從 cert-manager 1.11 開始,傳遞一個受信任的 CA,以在建立簽發者時使用
apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: my-acme-server-issuerspec:acme:server: https://my-acme-server.example.comcaBundle: <base64 encoded CA Bundle in PEM format>...
替代憑證鏈
從 ACME 伺服器取得憑證時,可以選擇替代憑證鏈。這讓簽發者可以在轉換期間順利地將使用者轉移到新的根憑證;最著名的例子是 Let's Encrypt 的 「ISRG Root」變更。
此功能並非 Let's Encrypt 專屬;如果您的 ACME 伺服器支援由多個 CA 簽署,您可以使用 preferredChain
以及您想要在憑證的簽發者部分中使用的鏈的通用名稱值。如果通用名稱與不同的鏈匹配,則伺服器可以選擇使用並傳回該新鏈。
如果 preferredChain
未與憑證匹配,則伺服器將傳回其認為的預設憑證。
舉例來說,以下是使用者在(現在已完成)「ISRG Root」變更之前如何要求替代鏈,但請注意,由於此變更已發生,因此不再需要 Let's Encrypt 的此做法
apiVersion: cert-manager.io/v1kind: Issuermetadata:name: letsencryptspec:acme:server: https://acme-v02.api.letsencrypt.org/directorypreferredChain: "ISRG Root X1"