別の PKI モードへの移行

Google Distributed Cloud(GDC)エアギャップは、ウェブ証明書を取得するための公開鍵基盤(PKI)API を提供します。このページでは、ある PKI 証明書モードから別の PKI 証明書モードに移行する手順について説明します。PKI モードの構成タイプの詳細については、ウェブ TLS 証明書の構成をご覧ください。

始める前に

PKI のデフォルト証明書発行者を構成するために必要な権限を取得するには、組織の IAM 管理者に、システム Namespace の Infra PKI 管理者(infra-pki-admin)ロールの付与を依頼してください。

BYO サブ CA モードに移行する

このセクションでは、お客様所有(BYO)SubCA 証明書モードに移行する一連の手順について説明します。

BYO サブ CA を作成する

BYO サブ 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: 秘密鍵と署名付き CA 証明書を保持する Kubernetes Secret の名前。
  2. カスタム リソースを Distributed Cloud ゾーンに適用します。

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

    MANAGEMENT_API_SERVER は、Management API サーバーの kubeconfig ファイルに置き換えます。

Sub CA の CSR が生成され、署名されるのを待ちます。CSR に署名するには、BYO サブ CA 証明書に署名するの手順に沿って操作します。

BYO サブ 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. 「Basic Constraints」拡張機能で 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 証明書に SAN ではなく共通名(CN)がある場合は、証明書の 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. BYO subCA の準備状況を確認します。

    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 証明書モードへの移行

このセクションでは、BYO-cert モードに移行する一連の手順について説明します。

BYO CertificateIssuer を作成する

  1. CertificateIssuer リソースを作成し、YAML ファイル(byo-cert-issuer.yaml など)として保存します。この BYO 証明書発行者は、フォールバック CA としてマネージド default-tls-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 は、BYO-cert 発行者の名前に置き換えます。

  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"
    }
    

BYO 証明書に署名する

  1. CSR が外部で署名されるのを待機している間、BYO-cert 発行者で指定されたフォールバック CA によって BYO-cert が一時的に発行されることがあります。現在の BYO-cert 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. 証明書の Secret 名を取得します。

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

    出力は次のようになります。

    web-tls
    
  3. Secret から発行者を確認します。

    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 の example-service 証明書は、同じ証明書発行元の DNSName *.org-1.zone1.google.gdch.testdefault-wildcard-cert と一致します。example-service 証明書は、CSR が署名されるのを待っている間、次のステータスを保持できます。

    {
      "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 モードで BYO 証明書に移行する

このセクションでは、ACME モードで BYO-cert に移行する一連の手順について説明します。

ACME 構成で CertificateIssuer を作成する

  1. ACME 構成で CertificateIssuer リソースを作成し、acme-issuer.yaml などの 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 サーバーのディレクトリ エンドポイントにアクセスするための URL。
    • CA_BUNDLE: ACME サーバーによって提示された証明書チェーンを検証する PEM CA の Base64 でエンコードされたバンドル。
    • PRIVATE_KEY_SECRET_NAME: ACME アカウントの秘密鍵を含む Secret の名前。

    既存の 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 ウェブ証明書を手動で再発行するをご覧ください。