轉換至其他 PKI 模式

Google Distributed Cloud (GDC) 氣隙隔離提供公開金鑰基礎架構 (PKI) API,可取得網頁憑證。本頁面提供從一個 PKI 憑證模式轉換至另一個模式的說明。如要進一步瞭解 PKI 模式設定類型,請參閱「Web TLS certificate configuration」(網頁 TLS 憑證設定)

事前準備

如要取得設定 PKI 預設憑證簽發機構所需的權限,請要求機構 IAM 管理員在系統命名空間中,授予您基礎架構 PKI 管理員 (infra-pki-admin) 角色。

改用自備子 CA 模式

本節提供一系列步驟,說明如何改用自備 SubCA 憑證模式。

建立自備子 CA

如要建立自有次要 CA,請將自訂資源套用至 Distributed Cloud 區域。

  1. 建立 CertificateAuthority 資源,並儲存為 YAML 檔案。在下列範例中,您會看到 CertificateAuthority 資源範例

    apiVersion: pki.security.gdc.goog/v1
    kind: CertificateAuthority
    metadata:
      name: CA_NAME
      namespace: pki-system
    spec:
      caProfile:
        commonName: COMMON_NAME
        duration: DURATION
        renewBefore: RENEW_BEFORE
      caCertificate:
        externalCA: {}
      certificateProfile:
        keyUsage:
        - digitalSignature
        - keyCertSign
        - crlSign
        extendedKeyUsage:
        - serverAuth
      secretConfig:
        secretName: SECRET_NAME
    

    請替換下列變數:

    • CA_NAME:子 CA 的名稱。
    • COMMON_NAME:CA 憑證的一般名稱。
    • DURATION:要求的 CA 憑證生命週期。
    • RENEW_BEFORE:CA 憑證到期前的輪替時間。
    • SECRET_NAME:Kubernetes Secret 的名稱,用於保存私密金鑰和已簽署的 CA 憑證。
  2. 將自訂資源套用至 Distributed Cloud 區域。

    kubectl apply -f byo-subca.yaml --kubeconfig MANAGEMENT_API_SERVER
    

    MANAGEMENT_API_SERVER 替換為 Management API 伺服器 kubeconfig 檔案。

系統會產生子 CA 的 CSR,並等待您簽署。如要簽署 CSR,請按照「簽署 BYO 子 CA 憑證」一節中的指示操作。

簽署自備子 CA 憑證

  1. 從 GDC 環境取得憑證簽署要求 (CSR):

    kubectl get certificateauthorities CA_NAME -n pki-system -ojson | jq -j '"echo ",
    .status.externalCA.csr, " | base64 -d > ","sub_ca.csr\n"' | bash
    

    這個指令會在目前目錄中產生 sub_ca.csr 檔案。這個檔案包含 X.509 CA 憑證的 CSR。

  2. 使用客戶根 CA 的通訊協定,為 sub_ca.csr 檔案要求簽署的 CA 憑證。

  3. 如果憑證簽署要求獲得核准,您會取得由客戶根 CA 簽署的 CA 憑證。將憑證儲存至目前目錄中的 sub_ca.crt 檔案。此外,請取得客戶的根 CA 憑證,並儲存至目前目錄中的 ca.crt 檔案。如需確切的操作說明,請與 PMO 聯絡。

  4. 請驗證下列事項,確保憑證的完整性和準確性:

    1. 確認 sub_ca.crt 符合標準 PEM 編碼憑證格式:

      -----BEGIN CERTIFICATE-----
            <Certificate>
      -----END CERTIFICATE-----
      
    2. 確認 sub_ca.crt 是「基本限制」擴充功能中的有效憑證授權單位 (CA):

      openssl x509 -text -noout -in sub_ca.crt | grep -A 1 "Basic Constraints"
      

      輸出內容必須包含 CA:TRUE,否則需要進一步調查:

      X509v3 Basic Constraints: critical
          CA:TRUE
      
    3. 驗證憑證中的主體別名 (SAN) 擴充功能:

      openssl x509 -text -noout -in sub_ca.crt | grep -A 1 "Subject Alternative Name"
      

      如果 CA 憑證具有共用名稱 (CN) 而非 SAN,請驗證憑證中的 CN

      openssl x509 -text -noout -in sub_ca.crt | grep -A 1 "Subject: CN"
      
  5. 產生規格,以修補 CertificateAuthority 資源:

     echo "spec:
    caCertificate:
      externalCA:
        signedCertificate:
          certificate: $(base64 -w0 sub_ca.crt)
          ca: $(base64 -w0 ca.crt)" > patch.txt
    

    patch.txt 檔案中的內容類似下列程式碼片段:

     spec:
      caCertificate:
       externalCA:
        signedCertificate:
         certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURSekNDQ…
         ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRVENDQ…
    
  6. 編輯 CertificateAuthority 資源的規格:

    kubectl patch certificateauthority CA_NAME -n pki-system --patch-file patch.txt --type='merge'
    
  7. 確認自備子 CA 是否已準備就緒:

    kubectl get certificateauthority CA_NAME -n pki-system -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'
    

    畫面會顯示類似以下內容的輸出:

    {
      "lastTransitionTime": "2024-04-30T22:10:50Z",
      "message": "Certificate authority is ready for use",
      "observedGeneration": 3,
      "reason": "Ready",
      "status": "True",
      "type": "Ready"
    }
    
  8. 確認簽署的 CA 憑證是否過期:

    kubectl -n pki-system get secret SECRET_NAME -ojson | jq -j '"echo ",
    .metadata.name, " $(echo ", .data["tls.crt"], "| base64 -d | openssl x509 -enddate -noout)\n"' | bash
    
  9. 建立 CertificateIssuer 資源 YAML 檔案,然後儲存檔案。例如:byo-subca-issuer.yaml

    apiVersion: pki.security.gdc.goog/v1
    kind: CertificateIssuer
    metadata:
      name: BYO_SUBCA_ISSUER
      namespace: pki-system
    spec:
      caaasConfig:
        certificateAuthorityRef:
          namespace: pki-system
          name: CA_NAME
    

    BYO_SUBCA_ISSUER 換成 BYO 子 CA 簽發者名稱。

  10. 使用 kubectl CLI,將自訂資源套用至 Management API 伺服器中的 Distributed Cloud 區域:

    kubectl apply -f byo-subca-issuer.yaml --kubeconfig MANAGEMENT_API_SERVER
    
  11. 確認新核發機構是否已準備就緒:

    kubectl -n pki-system get certificateissuer.pki.security.gdc.goog/BYO_SUBCA_ISSUER -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'
    

改用自備憑證模式

本節提供一系列步驟,說明如何轉換至自備憑證模式。

建立 BYO CertificateIssuer

  1. 建立 CertificateIssuer 資源,並儲存為 YAML 檔案,例如 byo-cert-issuer.yaml。這個自備憑證核發者會使用代管的 default-tls-ca 做為備用 CA:

    apiVersion: pki.security.gdc.goog/v1
    kind: CertificateIssuer
    metadata:
      name: BYO_CERT_ISSUER_NAME
      namespace: pki-system
    spec:
      byoCertConfig:
        fallbackCertificateAuthority:
          name: default-tls-ca
          namespace: pki-system
    

    BYO_CERT_ISSUER_NAME 替換為自有憑證簽發者的名稱。

  2. 在 Management API 伺服器中,將自訂資源套用至 Distributed Cloud 區域:

    kubectl apply -f byo-cert-issuer.yaml --kubeconfig MANAGEMENT_API_SERVER
    
  3. 確認新核發機構是否已準備就緒。

    kubectl -n pki-system get certificateissuer.pki.security.gdc.goog/BYO_CERT_ISSUER_NAME -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'
    

    輸出看起來類似以下內容:

    {
      "lastTransitionTime": "2024-05-01T22:25:20Z",
      "message": "",
      "observedGeneration": 1,
      "reason": "FallbackCAReady",
      "status": "True",
      "type": "Ready"
    }
    

簽署自備憑證

  1. 等待外部簽署 CSR 時,BYO 憑證簽發者指定的備援 CA 可以暫時核發 BYO 憑證。取得目前的自備憑證狀態:default-wildcard-cert

    kubectl get certificate.pki.security.gdc.goog/default-wildcard-cert -n istio-system -o json | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'
    

    輸出看起來類似以下內容:

    {
      "lastTransitionTime": "2024-05-03T08:42:10Z",
      "message": "Certificate is issued by a fallback CA",
      "observedGeneration": 1,
      "reason": "UsingFallbackCA",
      "status": "True",
      "type": "Ready"
    }
    

    準備就緒原因會顯示 UsingFallbackCA,表示備援 CA 核發了憑證。然後儲存在密鑰中,隨時可供使用。

  2. 取得憑證密鑰名稱:

    kubectl -n istio-system get certificate.pki.security.gdc.goog/default-wildcard-cert -ojson | jq -r '.spec.secretConfig.secretName'
    

    輸出看起來類似以下內容:

    web-tls
    
  3. 檢查密鑰的簽發者:

    kubectl get secret web-tls -n istio-system -o jsonpath='{.data.tls\.crt}' |
    base64 -d | openssl x509 -text -noout | grep Issuer
    

    輸出看起來類似以下內容:

    Issuer: CN = GDC Managed ORG TLS CA
    

    自備憑證 (BYO-cert) 在等待自己的 CSR 簽章時,可以暫時使用相符的憑證。如果範例服務憑證的 dnsName 為 example-service.org-1.zone1.google.gdch.test,則來自同一憑證核發機構的 default-wildcard-cert (DNSName 為 *.org-1.zone1.google.gdch.test) 會與該憑證相符。等待簽署 CSR 時,example-service 憑證可能處於下列狀態:

    {
      "lastTransitionTime": "2024-05-03T22:30:51Z",
      "message": "Using a matched issued Certificate: default-wildcard-cert/istio-system",
      "observedGeneration": 1,
      "reason": "UsingMatchedCert",
      "status": "True",
      "type": "Ready"
    }
    
  4. 從憑證狀態取得 CSR:

    kubectl -n istio-system get certificate.pki.security.gdc.goog/default-wildcard-cert -ojson | jq -r ' .status.byoCertStatus.csrStatus'
    

    輸出看起來類似以下內容:

    {
      "conditions": [
        {
          "lastTransitionTime": "2024-05-03T18:14:19Z",
          "message": "",
          "observedGeneration": 1,
          "reason": "WaitingForSigning",
          "status": "False",
          "type": "Ready"
        }
      ],
      "csr": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSB..."
    }
    
  5. 根據外部 CA 設定,簽署 CSR 的方法有所不同。簽署時,請使用 CSR 中的 SAN。例如:

    function signCert() {
       certName=$1
       ns=$2
    
       # Download the CSR from the certificate
       kubectl get certificate.pki.security.gdc.goog $certName -n $ns -o jsonpath='{.status.byoCertStatus.csrStatus.csr}' | base64 -d > $certName.csr
    
       # Get SAN from the csr
       san=$(openssl req -in $certName.csr -noout -text | grep 'DNS:' | sed -s 's/^[ ]*//')
    
       # Save SAN to extension config
       cat <<EOF >$certName-csr.ext
     keyUsage=digitalSignature,keyEncipherment
     extendedKeyUsage=serverAuth,clientAuth
     subjectAltName=${san}
     EOF
    
       # Sign the CSR with an external CA. You need to prepare the external CA cert and key
       openssl x509 -req -in $certName.csr -days 365 -CA ext-ca.crt -CAkey ext-ca.key -CAcreateserial -extfile $certName-csr.ext -out $certName-signed.crt
       openssl x509 -in $certName-signed.crt -text -noout
    
       # Upload the externally signed certificate by patching.
       echo "spec:
         byoCertificate:
            certificate: $(base64 -w0 $certName-signed.crt)
            ca: $(base64 -w0 ext-ca.crt)" > patch.txt
    
       kubectl patch certificate.pki.security.gdc.goog $certName -n $ns --patch-file patch.txt --type='merge'
     }
    
     # Use the function to sign the default-wildcard-cert in the istio-system namespace
     signCert default-wildcard-cert istio-system
    
  6. 請確認下列詳細資料:

    • 憑證的 CSR 狀態為「Ready
    kubectl -n istio-system get certificate.pki.security.gdc.goog/default-wildcard-cert -ojson | jq -r ' .status.byoCertStatus.csrStatus.conditions'
    
    [
       {
          "lastTransitionTime": "2024-05-03T21:56:25Z",
          "message": "",
          "observedGeneration": 2,
          "reason": "Signed",
          "status": "True",
          "type": "Ready"
       }
    ]
    
    • 憑證已Ready,原因為Issued
    kubectl get certificate.pki.security.gdc.goog/default-wildcard-cert -n istio-system -o json | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'
    

    輸出看起來類似以下內容:

    {
      "lastTransitionTime": "2024-05-03T08:42:10Z",
      "message": "Certificate is issued",
      "observedGeneration": 2,
      "reason": "Issued",
      "status": "True",
      "type": "Ready"
    }
    
    • 密鑰已更新:
    kubectl get secret web-tls -n istio-system -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout | grep Issuer
    

    輸出看起來類似以下內容:

            Issuer: CN = external-ca
    

改用 ACME 模式的自備憑證

本節提供一系列步驟,說明如何使用 ACME 模式轉換為自備憑證。

使用 ACME 設定建立 CertificateIssuer

  1. 使用 ACME 設定建立 CertificateIssuer 資源,並儲存為 YAML 檔案,例如 acme-issuer.yaml

    apiVersion: pki.security.gdc.goog/v1
    kind: CertificateIssuer
    metadata:
      name: ACME_ISSUER_NAME
      namespace: pki-system
    spec:
         acmeConfig:
           rootCACertificate: ROOT_CA_CERTIFICATE
           acme:
             server: ACME_SERVER_URL
             caBundle: CA_BUNDLE
             privateKeySecretRef:
               name: PRIVATE_KEY_SECRET_NAME
    

    請替換下列變數:

    • ACME_ISSUER_NAME:ACME 核發機構的名稱。
    • ROOT_CA_CERTIFICATE:ACME 伺服器核發憑證的根 CA 資料。
    • ACME_SERVER_URL:用來存取 ACME 伺服器目錄端點的網址。
    • CA_BUNDLE:以 Base64 編碼的 PEM CA 套裝組合,用於驗證 ACME 伺服器提供的憑證鏈結。
    • PRIVATE_KEY_SECRET_NAME:包含 ACME 帳戶私密金鑰的密碼名稱。

    如要使用現有的 ACME 帳戶私密金鑰,請確認保存該金鑰的密鑰使用與 ACME 簽發者相同的命名空間,且名稱為 PRIVATE_KEY_SECRET_NAME。如果您未提供這個密碼,系統會自動產生同名的新密碼,用於儲存 ACME 帳戶私密金鑰。

  2. 將自訂資源套用至 Distributed Cloud 區域:

    kubectl apply -f acme-issuer.yaml --kubeconfig MANAGEMENT_API_SERVER
    
  3. 確認新核發機構是否已準備就緒:

    kubectl --kubeconfig MANAGEMENT_API_SERVER -n pki-system get certificateissuer.pki.security.gdc.goog/ACME_ISSUER_NAME -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'
    

    畫面會顯示類似以下內容的輸出:

    {
      "lastTransitionTime": "2024-05-01T18:32:17Z",
      "message": "",
      "observedGeneration": 1,
      "reason": "ACMEClientReady",
      "status": "True",
      "type": "Ready"
    }
    

重新核發憑證

如要將預設簽發機構切換為新的 ACME 簽發機構,請參閱「變更預設憑證簽發機構」一文。

如要立即使用新的預設簽發者重新核發憑證,請參閱「手動重新核發 PKI 網頁憑證」。