使用憑證授權單位服務,自動管理 Cloud Service Mesh 進入閘道的 TLS 憑證

本教學課程說明平台營運人員如何使用 cert-manager 工具的憑證授權單位服務 (CA Service) 簽發者,自動管理 Cloud Service Mesh Ingress 閘道的 TLS 憑證。憑證可讓 Ingress 閘道終止來自虛擬私有雲 (VPC) 中用戶端,但位於服務網格外部的 HTTPS 和其他 TLS 與 mTLS 流量。本教學課程假設您已熟悉 Kubernetes 和 TLS 憑證的基本概念。

簡介

Cloud Service Mesh 會為服務網格中的每個工作負載佈建 TLS 憑證。 這些憑證可讓服務網格中的工作負載,透過相互驗證的 TLS (mTLS) 加密通訊。由其中一個支援的 CA 簽發及簽署憑證。

不過,Cloud Service Mesh 不會自動為進入服務網格的流量,向 Ingress 閘道佈建憑證。常見的解決方案是使用開放原始碼 cert-manager 工具,自動管理 Ingress 閘道憑證。

cert-manager 工具會向簽發者要求憑證,而簽發者代表憑證授權單位 (CA)憑證授權單位服務可讓您建立自己的私人 CA。Google Cloud cert-manager 工具可使用 CA 服務的開放原始碼外部簽發者,向 CA 服務要求憑證。

私人 CA 可以核發 TLS 憑證,驗證及加密內部網路中的流量。Cloud Service Mesh 輸入閘道通常會設定為允許來自 VPC 內部但服務網格外部的用戶端流量。如果是內部網路流量,您可以使用 CA Service 中的私有 CA,為輸入閘道核發憑證。

本教學課程說明如何設定 cert-manager 工具和 CA 服務簽發者,自動為 Ingress 閘道佈建及續訂 TLS 憑證。cert-manager 工具會將憑證佈建為TLS 類型的 Kubernetes Secret 資源。當 cert-manager 工具續購憑證時,會使用新憑證更新 Secret 資源。Ingress 閘道會執行 Envoy Proxy,並支援 Envoy 的密碼探索服務 (SDS)。SDS 可讓 Ingress 閘道開始使用新憑證,管理員不必重新啟動或重新載入程序。

網格中的 Sidecar Proxy 可以從 CA 服務或 Cloud Service Mesh 憑證授權單位取得 TLS 憑證。在本教學課程中,您會使用 CA 服務取得 Sidecar Proxy 和 Ingress Gateway 憑證。這樣一來,您就能為所有 TLS 憑證使用一個根 CA。

下圖顯示您在本教學課程中佈建的資源。您為 Ingress 閘道佈建內部直通式網路負載平衡器。內部直通式網路負載平衡器不是 Proxy,因此不會終止 TCP 連線或執行 TLS 交握。而是將連線轉送至 istio-ingressgateway 部署作業的 Pod。

hello-example-com-credential Secret 包含憑證和私密金鑰。hello 閘道會設定 istio-ingressgateway 部署作業的 Pod,使用這個憑證和私密金鑰,對主機名稱為 hello.example.com 的要求執行 TLS 握手程序。

使用 CA 服務管理 mtls

cert-manager 命名空間中 google-cas-issuer 部署作業的 Pod 會向您在 CA 服務中建立的 CA 要求憑證。您建立 Identity and Access Management 政策繫結,允許 ca-service-isser Pod 使用 Workload Identity Federation for GKE 模擬 Google 服務帳戶。您可以在 CA 集區建立 IAM 政策繫結,授予這個 Google 服務帳戶權限,向 CA 服務中的 CA 要求憑證。

目標

費用

本教學課程使用下列 Google Cloud計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator。初次使用 Google Cloud 的使用者可能符合免費試用資格。

完成本教學課程後,您可以刪除自己建立的資源,避免系統繼續計費。詳情請參閱「清理」一節。

事前準備

  1. 在 Google Cloud 控制台中,前往專案選擇器頁面,然後選取或建立專案。

  2. 請確認您已為專案 Google Cloud 啟用計費功能

  3. 前往 Google Cloud 控制台的 Cloud Shell

    Google Cloud 主控台底部會開啟 Cloud Shell 工作階段,並顯示指令列提示。您將使用 Cloud Shell 來執行本教學課程中的所有指令。

  4. 設定要用於本教學課程的 Google Cloud 控制台專案:

    gcloud config set core/project PROJECT_ID
    

    PROJECT_ID 替換為 Cloud 專案的專案 ID。

    在「授權 Cloud Shell」對話方塊中,按一下「授權」。按一下「授權」,即可允許您在 Cloud Shell 中執行的 gcloud 指令使用您的使用者憑證,向 Google API 進行驗證。

  5. 啟用 Resource Manager、GKE、GKE Fleet、Cloud Service Mesh 憑證授權單位和 CA Service API:

    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        container.googleapis.com \
        gkehub.googleapis.com \
        meshca.googleapis.com \
        privateca.googleapis.com
    

設定 CA 服務

在本節中,您將在 CA 服務中建立根 CA 和兩個下層 CA。一個從屬 CA 會將憑證核發給 Ingress 閘道,另一個從屬 CA 則會將憑證核發給網格中的 Sidecar Proxy。

為求簡單起見,在本教學課程中,您會使用同一個專案來建立 GKE 叢集,以及根 CA 和下層 CA。在您自己的環境中,可以為 GKE 叢集和 CA 使用不同的專案。

  1. 在 Cloud Shell 中,建立用於根 CA 的 CA 集區:

    gcloud privateca pools create ROOT_CA_POOL \
        --location CA_LOCATION \
        --tier enterprise
    
    • ROOT_CA_POOL 是 CA 集區的名稱。例如:root-ca-pool-tutorial
    • CA_LOCATION 是 CA 集區的位置。例如:us-central1

    您可以使用下列指令列出可用的 CA 服務位置:gcloud privateca locations list

  2. 建立並啟用根 CA:

    gcloud privateca roots create ROOT_CA \
        --auto-enable \
        --key-algorithm ec-p384-sha384 \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --subject "CN=Example Root CA, O=Example Organization" \
        --use-preset-profile root_unconstrained
    
    • ROOT_CA 是您要用於根 CA 的名稱。例如:root-ca-tutorial
  3. 建立 CA 集區,供從屬 CA 使用,以便向 Ingress 閘道核發憑證:

    gcloud privateca pools create SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --tier devops
    
    • SUBORDINATE_CA_POOL_GATEWAYS 是 CA 集區的名稱。例如:subordinate-ca-mtls-pool-gateways-tutorial
  4. 建立並啟用從屬 CA,向 Ingress 閘道核發憑證:

    gcloud privateca subordinates create SUBORDINATE_CA_GATEWAYS \
        --auto-enable \
        --issuer-location CA_LOCATION \
        --issuer-pool ROOT_CA_POOL \
        --key-algorithm ec-p256-sha256 \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_GATEWAYS \
        --subject "CN=Example Gateway mTLS CA, O=Example Organization" \
        --use-preset-profile subordinate_mtls_pathlen_0
    
    • SUBORDINATE_CA_GATEWAYS 是您要用於下層 CA 的名稱。例如:subordinate-ca-mtls-gateways-tutorial
    • --use-preset-profile 標記會將從屬 CA 設定為使用「從屬 mTLS」憑證設定檔。這個設定檔可讓下層 CA 核發用戶端和伺服器 TLS 憑證,用於 mTLS。

    如果希望 Ingress 閘道使用簡單的 TLS,而非 mTLS,則下層 CA 只需要核發伺服器 TLS 憑證。在這種情況下,您可以改用「下層伺服器 TLS」(subordinate_server_tls_pathlen_0) 憑證設定檔。

  5. 建立憑證核發政策

    cat << EOF > policy.yaml
    baselineValues:
      keyUsage:
        baseKeyUsage:
          digitalSignature: true
          keyEncipherment: true
        extendedKeyUsage:
          serverAuth: true
          clientAuth: true
      caOptions:
        isCa: false
    identityConstraints:
      allowSubjectPassthrough: false
      allowSubjectAltNamesPassthrough: true
      celExpression:
        expression: subject_alt_names.all(san, san.type == URI && san.value.startsWith("spiffe://PROJECT_ID.svc.id.goog/ns/") )
    EOF
    

    這項核發政策會限制 CA,只能為網格中的工作負載核發憑證。

  6. 建立 CA 集區,供從屬 CA 使用,向網格中的 Sidecar 代理程式核發憑證。對 CA 集區套用核發政策:

    gcloud privateca pools create SUBORDINATE_CA_POOL_SIDECARS \
     --issuance-policy policy.yaml \
     --location CA_LOCATION \
     --tier devops
    
    • SUBORDINATE_CA_POOL_SIDECARS 是 CA 集區的名稱。例如:subordinate-ca-mtls-pool-sidecars-tutorial
  7. 建立並啟用從屬 CA,向網格中的 Sidecar Proxy 核發憑證:

    gcloud privateca subordinates create SUBORDINATE_CA_SIDECARS \
        --auto-enable \
        --issuer-location CA_LOCATION \
        --issuer-pool ROOT_CA_POOL \
        --key-algorithm ec-p256-sha256 \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_SIDECARS \
        --subject "CN=Example Sidecar mTLS CA, O=Example Organization" \
        --use-preset-profile subordinate_mtls_pathlen_0
    
    • SUBORDINATE_CA_GATEWAYS 是您要用於下層 CA 的名稱。例如:subordinate-ca-mtls-sidecars-tutorial

建立 Google Kubernetes Engine 叢集

  1. 在 Cloud Shell 中建立 GKE 叢集:

    gcloud container clusters create CLUSTER_NAME \
        --enable-ip-alias \
        --num-nodes 4 \
        --release-channel regular \
        --scopes cloud-platform \
        --workload-pool PROJECT_ID.svc.id.goog \
        --zone ZONE
    

    CLUSTER_NAME 替換為您要使用的叢集名稱。例如:asm-ingress-cert-manager-ca-service

    ZONE 替換為叢集要使用的區域。例如:us-central1-f

    請注意下列指令的相關事項:

    • --release-channel 旗標會為叢集選取 GKE 發布管道
    • Cloud Service Mesh 和 cert-manager 工具的 CA 服務簽發者,都要求您在叢集節點上設定 cloud-platform 範圍。
    • --workload-pool 引數會啟用 Workload Identity Federation for GKE,讓 CA 服務簽發者 Kubernetes 服務帳戶模擬 Google 服務帳戶。這項模擬作業表示 CA 服務簽發者 Pod 可以存取 CA 服務 API,不必下載 Google 服務帳戶的金鑰檔案
  2. 叢集管理員權限授予使用者帳戶:

    kubectl create clusterrolebinding cluster-admin-binding \
        --clusterrole cluster-admin \
        --user $(gcloud config get-value core/account)
    

    您需要 Kubernetes cluster-adminClusterRole 提供的權限,才能為 Cloud Service Mesh 建立角色型存取權控管 (RBAC) 規則,以及安裝 cert-manager 工具。

安裝 Anthos 服務網格控制層

在本教學課程中,您將在 Google Cloud的 GKE 叢集上安裝代管 Cloud Service Mesh,所有資源都位於同一個專案中。在您自己的環境中,您可以透過代管 Cloud Service Mesh 或叢集內控制層,套用本文所述的解決方案。

Cloud Service Mesh 提供多種安裝選項,適用於不同情境。完成本教學課程後,建議您參閱安裝指南,選取最適合您環境的選項。

  1. 在 Cloud Shell 中,下載 asmcli 安裝工具:

    curl --location --output asmcli https://storage.googleapis.com/csm-artifacts/asm/asmcli_1.28
    
    chmod +x asmcli
    

    您可以使用 asmcli 安裝 Cloud Service Mesh 控制層。

  2. 安裝 Cloud Service Mesh 控制層:

    ./asmcli install \
        --ca gcp_cas \
        --ca_pool projects/PROJECT_ID/locations/CA_LOCATION/caPools/SUBORDINATE_CA_POOL_SIDECARS \
        --cluster_location ZONE \
        --cluster_name CLUSTER_NAME \
        --enable_all \
        --enable_registration \
        --fleet_id PROJECT_ID \
        --managed \
        --output_dir asm-files \
        --project_id PROJECT_ID \
        --verbose
    

    安裝作業需要幾分鐘才能完成。安裝完成後,畫面會顯示以下輸出內容:

    asmcli: Successfully installed ASM.
    

安裝 Ingress 閘道

  1. 在 Cloud Shell 中,為 Ingress 閘道建立 Kubernetes 命名空間:

    kubectl create namespace GATEWAY_NAMESPACE
    
    • GATEWAY_NAMESPACE 是要用於 Ingress 閘道的命名空間名稱。例如:istio-ingress
  2. 保留靜態內部 IP 位址,供 Ingress 閘道內部直通式網路負載平衡器使用:

    LOAD_BALANCER_IP=$(gcloud compute addresses create \
        asm-ingress-gateway-ilb \
        --region REGION \
        --subnet default \
        --format 'value(address)')
    
    • REGION 替換為包含 GKE 叢集節點所用區域的地區。舉例來說,如果叢集使用 us-central1-f 區域,請將 REGION 替換為 us-central1

    這個指令會從您指定的區域中,保留預設子網路的 IP 位址。

  3. 為 Ingress 閘道建立運算子資訊清單

    cat << EOF > ingressgateway-operator.yaml
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      name: ingressgateway-operator
      annotations:
        config.kubernetes.io/local-config: "true"
    spec:
      profile: empty
      revision: asm-managed
      components:
        ingressGateways:
        - name: istio-ingressgateway
          namespace: GATEWAY_NAMESPACE
          enabled: true
          k8s:
            overlays:
            - apiVersion: apps/v1
              kind: Deployment
              name: istio-ingressgateway
              patches:
              - path: spec.template.metadata.annotations
                value:
                  inject.istio.io/templates: gateway
              - path: spec.template.metadata.labels.sidecar\.istio\.io/inject
                value: "true"
              - path: spec.template.spec.containers[name:istio-proxy]
                value:
                  name: istio-proxy
                  image: auto
            service:
              loadBalancerIP: $LOAD_BALANCER_IP
            serviceAnnotations:
              networking.gke.io/load-balancer-type: Internal
              networking.gke.io/internal-load-balancer-allow-global-access: "true"
    EOF
    

    請注意下列有關運算子資訊清單的事項:

  4. 使用運算子資訊清單和 istioctl 工具 (安裝控制層時,asmcli 指令碼會下載此工具),建立 Ingress Gateway 安裝資訊清單:

    ./asm-files/istioctl manifest generate \
        --filename ingressgateway-operator.yaml \
        --output ingressgateway
    
  5. 安裝 Ingress 閘道

    kubectl apply --recursive --filename ingressgateway/
    

安裝 cert-manager 工具

  1. 在 Cloud Shell 中,下載並套用 cert-manager 工具安裝資訊清單:

    CERT_MANAGER_VERSION=v1.5.4
    
    curl --location --output cert-manager.yaml "https://github.com/jetstack/cert-manager/releases/download/${CERT_MANAGER_VERSION}/cert-manager.yaml"
    
    kubectl apply --filename cert-manager.yaml
    

    安裝 cert-manager 工具大約需要一分鐘。

安裝 CA 服務簽發者控制器

CA 服務核發者控制器可讓 cert-manager 工具使用 CA 服務要求憑證。控制器會使用 cert-manager 工具的外部簽發者擴充機制。

  1. 在 Cloud Shell 中建立 Google 服務帳戶

    gcloud iam service-accounts create CAS_ISSUER_GSA \
        --display-name "CA Service issuer for cert-manager"
    
    • CAS_ISSUER_GSA 是 Google 服務帳戶的名稱。例如:cert-manager-ca-service-issuer

    憑證授權單位服務簽發者控制器會使用這個 Google 服務帳戶,向 憑證授權單位服務 API 進行驗證。

  2. 建立身分與存取權管理政策繫結,允許憑證授權單位服務簽發者控制器 Google 服務帳戶,從包含下層 CA 的 CA 集區要求憑證:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    
  3. 下載憑證授權單位服務簽發者控制器安裝資訊清單:

    CAS_ISSUER_VERSION=v0.5.3
    
    curl --location --output ca-service-issuer.yaml "https://github.com/jetstack/google-cas-issuer/releases/download/${CAS_ISSUER_VERSION}/google-cas-issuer-${CAS_ISSUER_VERSION}.yaml"
    
  4. 建立 IAM 政策繫結,允許 cert-manager命名空間中的 ksa-google-cas-issuer Kubernetes 服務帳戶使用 Workload Identity Federation for GKE模擬 Google 服務帳戶 (GSA):

    gcloud iam service-accounts add-iam-policy-binding \
     CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[cert-manager/ksa-google-cas-issuer]" \
        --role roles/iam.workloadIdentityUser
    

    CA 服務簽發者控制器 Pod 會使用 ksa-google-cas-issuer Kubernetes 服務帳戶。

  5. 在 GKE 叢集中安裝 CA 服務簽發者控制器:

    kubectl apply --filename ca-service-issuer.yaml
    
  6. 將 Workload Identity Federation for GKE 註解 iam.gke.io/gcp-service-account 新增至 CA 服務簽發者控制器 Pod 使用的 Kubernetes 服務帳戶:

    kubectl annotate serviceaccount ksa-google-cas-issuer --namespace cert-manager \
       "iam.gke.io/gcp-service-account=CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com"
    

    這項註解會通知 GKE,Kubernetes 服務帳戶可以模擬 Google 服務帳戶,存取 Google API。

建立憑證頒發機構

  1. 在 Cloud Shell 中,建立並套用 GoogleCASIssuer 資訊清單:

    cat << EOF > gateway-cas-issuer.yaml
    apiVersion: cas-issuer.jetstack.io/v1beta1
    kind: GoogleCASIssuer
    metadata:
      name: gateway-cas-issuer
      namespace: GATEWAY_NAMESPACE
    spec:
      caPoolId: SUBORDINATE_CA_POOL_GATEWAYS
      location: CA_LOCATION
      project: PROJECT_ID
    EOF
    
    kubectl apply --filename gateway-cas-issuer.yaml
    

    核發者可讓 cert-manager 工具從 Ingress 閘道命名空間中的從屬 CA 集區佈建憑證

部署範例應用程式

在本節中,您將驗證 cert-manager 工具是否可使用 CA 服務簽發者,從 CA 服務取得憑證。如要驗證,請部署範例應用程式,其中包含要求轉送設定和輸入閘道的憑證。

  1. 在 Cloud Shell 中,為範例應用程式資源建立命名空間:

    cat << EOF > sample-app-namespace.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: APP_NAMESPACE
      annotations:
        mesh.cloud.google.com/proxy: '{"managed":"true"}'
      labels:
        istio.io/rev: asm-managed
    EOF
    
    kubectl apply --filename sample-app-namespace.yaml
    
    • APP_NAMESPACE 是範例應用程式的命名空間名稱。例如:sample-app

    註解 mesh.cloud.google.com/proxy 可為命名空間啟用受管理資料平面

    標籤 istio.io/rev: asm-managed 會在範例應用程式命名空間中,為受管理資料層選取「一般發布管道」。如果您使用快速或穩定版發布管道,請變更這個標籤的值。

  2. 為範例應用程式建立 Deployment 資源:

    cat << EOF > deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello
      namespace: APP_NAMESPACE
      labels:
        app: hello
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: hello
      template:
        metadata:
          labels:
            app: hello
        spec:
          containers:
          - image: gcr.io/google-samples/hello-app:1.0
            name: hello-app
            ports:
            - containerPort: 8080
    EOF
    
    kubectl apply --filename deployment.yaml
    
  3. 為範例應用程式建立 Service 資源:

    cat << EOF > service.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: SERVICE_NAME
      namespace: APP_NAMESPACE
    spec:
      ports:
      - name: http-hello
        port: 8080
      selector:
        app: hello
      type: ClusterIP
    EOF
    
    kubectl apply --filename service.yaml
    
    • SERVICE_NAME 是服務名稱。例如:hello
  4. 使用憑證頒發機構,為網域名稱 hello.example.com 建立憑證資源:

    cat << EOF > certificate.yaml
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: hello-example-com-certificate
      namespace: GATEWAY_NAMESPACE
    spec:
      secretName: hello-example-com-credential
      commonName: hello.example.com
      dnsNames:
      - hello.example.com
      duration: 24h
      renewBefore: 8h
      issuerRef:
        group: cas-issuer.jetstack.io
        kind: GoogleCASIssuer
        name: gateway-cas-issuer
    EOF
    
    kubectl apply --filename certificate.yaml
    

    憑證命名空間必須與 Ingress 閘道命名空間相符。 通常只有平台管理員可以變更這個命名空間中的資源,因為變更可能會影響整個服務網格。cert-manager 工具會在同一個命名空間中,為 TLS 憑證建立 Secret 資源。也就是說,應用程式管理員不需要存取 Ingress 閘道命名空間。

    您可以在「Certificate」的 dnsNames 清單中新增其他主機名稱。 這些主機名稱會以主體別名 (SAN) 形式納入憑證。

  5. 為範例應用程式建立 Gateway 資源:

    cat << EOF > gateway.yaml
    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: GATEWAY_NAME
      namespace: GATEWAY_NAMESPACE
    spec:
      selector:
        istio: ingressgateway
      servers:
      - hosts:
        - APP_NAMESPACE/hello.example.com
        port:
          name: https-hello
          number: 443
          protocol: HTTPS
        tls:
          credentialName: hello-example-com-credential
          mode: MUTUAL
    EOF
    
    kubectl apply --filename gateway.yaml
    
    • GATEWAY_NAME 是閘道名稱。例如:hello
    • Gateway 中的 credentialName 欄位與憑證中的 secretName 欄位相符。cert-manager 工具會使用 CA 服務中的 TLS 憑證建立 Kubernetes 密鑰。有了這項憑證,Ingress Gateway 就能終止傳輸層安全標準 (TLS) 流量,並將流量導向 hello.example.com

    閘道資訊清單會指定MUTUAL傳輸層安全標準 (mTLS)。如要為一般傳輸層安全標準 (TLS) 設定閘道,請將閘道的傳輸層安全標準 (TLS) 模式設為 SIMPLE

  6. 為範例應用程式建立 VirtualService 資源:

    cat << EOF > virtual-service.yaml
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: hello
      namespace: APP_NAMESPACE
    spec:
      hosts:
      - hello.example.com
      gateways:
      - GATEWAY_NAMESPACE/GATEWAY_NAME
      http:
      - route:
        - destination:
            host: SERVICE_NAME
            port:
              number: 8080
    EOF
    
    kubectl apply --filename virtual-service.yaml
    

    Gateway 和 VirtualService 使用不同的命名空間。這個常見模式會限制 Gateway 中主機型路由的變更,只有具備在 Ingress Gateway 命名空間中變更資源權限的平台管理員,才能進行這類變更。

    有權在範例應用程式命名空間中編輯 VirtualService 的應用程式管理員,可以透過其他要求欄位 (例如網址路徑) 變更路由,不必與平台管理員協調。

如要瞭解其他設定選項,請參閱 CertificateGatewayVirtualService 資源的 API 說明文件。

您可以對透過輸入閘道進入服務網格的流量套用驗證和授權政策。如要這麼做,請參閱 Istio PeerAuthenticationAuthorizationPolicy API 的說明文件。

檢查問題是否已經順利解決

在本節中,您將驗證是否能從服務網格外部,使用 mTLS 將 HTTPS 要求傳送至範例應用程式。如要驗證,請建立 Compute Engine VM 執行個體、向 CA 服務要求用戶端 TLS 憑證,並使用這個憑證向範例應用程式驗證要求。

您需要 VM 執行個體的 SSH 存取權。預設網路包含允許 SSH 存取的防火牆規則。如果無法透過 SSH 存取,請參閱防火牆規則說明文件,建立允許通訊埠 22 上連入 TCP 連線的防火牆規則。

  1. 在 Cloud Shell 中建立 Google 服務帳戶:

    gcloud iam service-accounts create CLIENT_VM_GSA \
        --display-name "CA Service tutorial VM instance service account"
    
    • CLIENT_VM_GSA 是 Google 服務帳戶的名稱。例如:cas-tutorial-client

    您會將這個 Google 服務帳戶指派給 Compute Engine VM 執行個體。

  2. 將閘道從屬 CA 集區的 CA Service Certificate Requester 角色指派給 Google 服務帳戶:

    gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    

    這個角色提供向 CA 集區要求憑證的權限。

  3. 在與 GKE 叢集相同的 VPC 中建立 Compute Engine VM 執行個體:

    gcloud compute instances create cas-tutorial-client \
        --scopes cloud-platform \
        --service-account CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --zone ZONE
    

    VM 執行個體需要 cloud-platform 範圍,才能存取 CA Service API

  4. 將 Ingress 閘道內部直通式網路負載平衡器的 IP 位址儲存至檔案:

    kubectl get services istio-ingressgateway \
       --namespace GATEWAY_NAMESPACE \
       --output jsonpath='{.status.loadBalancer.ingress[0].ip}' > ilb-ip.txt
    
  5. 將根 CA 的公用金鑰憑證儲存至檔案:

    gcloud privateca roots describe ROOT_CA \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --format 'value(pemCaCertificates)' > root-ca-cert.pem
    
  6. 將根 CA 憑證和包含 Ingress 閘道內部直通網路負載平衡器 IP 位址的檔案複製到 VM 執行個體:

    gcloud compute scp root-ca-cert.pem ilb-ip.txt cas-tutorial-client:~ \
       --zone ZONE
    
  7. 使用 SSH 連線至 VM 執行個體:

    gcloud compute ssh cas-tutorial-client --zone ZONE
    

    請透過 SSH 工作階段執行本節中的其餘指令。

  8. 安裝 ca-certificatescoreutils 套件,以及 curlopenssljq 指令列工具:

    sudo apt-get update --yes
    
    sudo apt-get install --yes ca-certificates coreutils curl jq openssl
    
  9. 建立用戶端 TLS 憑證的金鑰組:

    openssl genrsa -out private-key.pem 2048
    
    openssl rsa -in private-key.pem -pubout -out public-key.pem
    
  10. 查詢中繼資料伺服器,取得附加至 VM 執行個體的 Google 服務帳戶身分電子郵件地址:

    GSA_EMAIL=$(curl --silent --header "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email)
    
  11. 建立 JSON 檔案,在向憑證授權單位服務 API 要求用戶端 TLS 憑證時,將該檔案做為要求主體:

    cat << EOF > request.json
    {
      "config": {
        "publicKey": {
          "format": "PEM",
          "key": "$(base64 --wrap 0 public-key.pem)"
        },
        "subjectConfig": {
          "subject": {
            "commonName": "$(hostname --short)",
            "organization": "Example Organization"
          },
          "subjectAltName": {
            "dnsNames": [
              "$(hostname --fqdn)"
            ],
            "emailAddresses": [
              "$GSA_EMAIL"
            ]
          }
        },
        "x509Config": {
          "caOptions": {
            "isCa": false
          },
          "keyUsage": {
            "baseKeyUsage": {
              "digitalSignature": true,
              "keyEncipherment": true
            },
            "extendedKeyUsage": {
              "clientAuth": true
            }
          }
        }
      },
      "lifetime": "86400s"
    }
    EOF
    

    如要進一步瞭解設定部分的欄位,請參閱 CA Service API 說明文件中的CertificateConfig型別。

  12. 中繼資料伺服器要求 OAuth 2.0 存取權杖

    TOKEN=$(curl --silent --header "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token | jq --raw-output ".access_token")
    

    這個存取權杖會提供授予 VM 執行個體所連結 Google 服務帳戶的權限。

  13. 透過 CA 服務 API 要求用戶端 TLS 憑證,並將回應主體儲存在檔案中:

    curl --silent --request POST \
        --header "Authorization: Bearer $TOKEN" \
        --header "Content-Type: application/json" \
        --data @request.json \
        --output response.json \
        "https://privateca.googleapis.com/v1/projects/PROJECT_ID/locations/CA_LOCATION/caPools/SUBORDINATE_CA_POOL_GATEWAYS/certificates"
    

    這項指令會使用存取權杖驗證 API 要求。

  14. 將用戶端憑證和憑證鏈結儲存至檔案:

    jq --raw-output --join-output ".pemCertificate , .pemCertificateChain[]" response.json > client-cert-chain.pem
    
  15. 使用 curl 從 VM 執行個體傳送 HTTPS 要求至範例應用程式:

    curl --cert client-cert-chain.pem --key private-key.pem \
        --cacert root-ca-cert.pem \
        --resolve hello.example.com:443:$(cat ilb-ip.txt) \
        --silent https://hello.example.com | head -n1
    

    輸出如下所示:

    Hello, world!
    

    這項回應表示 curl 已使用 mTLS 成功傳送 HTTPS 要求。範例應用程式會回覆您在終端機輸出內容中看到的訊息。

    curl 指令會執行下列動作:

    • --cert--key 旗標會指示 curl 使用用戶端 TLS 憑證和私密金鑰驗證要求。用戶端憑證檔案包含完整憑證鏈結,從用戶端憑證到根 CA。

    • --cacert 旗標會指示 curl 驗證伺服器憑證是否由您在本教學課程中建立的根 CA 或其從屬 CA 核發。

      如果省略這個旗標,curl 會嘗試使用作業系統的預設 CA 組合驗證伺服器憑證,例如 Debian 上的 ca-certificates 套件。驗證失敗,因為預設的 CA 組合不包含您在本教學課程中建立的根 CA。

    • --resolve 旗標會指示 curl 使用內部直通式網路負載平衡器 IP 位址,做為傳送至主機 hello.example.com (位於 443 埠) 的要求目的地。

      如果省略這個標記,curl 會嘗試使用 DNS 解析 hello.example.com 主機名稱。由於這個主機名稱沒有 DNS 項目,因此 DNS 解析失敗。

      在您自己的環境中,建議您建立指向內部直通網路負載平衡器 IP 位址 ($LOAD_BALANCER_IP) 的 DNS A 記錄。請使用 Cloud DNS 建立這項記錄,並按照管理記錄的說明文件操作。

    • --silent 標記會禁止在終端機輸出內容中回報回應下載進度。

    • 這個指令會將 curl 輸出內容透過管道傳送至 head -n1。結果是終端機中的輸出內容只會包含回應主體的第一行。

  16. 離開 SSH 工作階段:

    exit
    

在本節中,您直接透過 CA 服務 API 要求用戶端 TLS 憑證。如果用戶端是另一個 Kubernetes 叢集中服務網格的出站閘道,您可以使用 cert-manager 工具和憑證授權單位服務簽發者,透過相同的根 CA 為出站閘道提供用戶端憑證。

在其他情況下,您可以使用 Hashicorp Vault、Terraform 或 gcloud 等工具,為服務網格外部的工作負載要求用戶端 TLS 憑證。詳情請參閱 CA Service 範例解決方案說明文件,以及 CA Service 的gcloud說明文件。

(選用) 將 CA 憑證新增至信任存放區

這個選用章節說明如何將 CA 憑證新增至 Debian Linux 發行版本的信任 CA 憑證存放區。這些操作說明也適用於衍生自 Debian 的發行版本,例如 Ubuntu。

將 CA 憑證新增至這個儲存庫後,使用 curl、Python、Go 和 Ruby 傳送 HTTPS 要求時,就不需要指定信任的 CA 憑證位置。

  1. 使用 SSH 連線至 VM 執行個體:

    gcloud compute ssh cas-tutorial-client --zone ZONE
    

    請透過 SSH 工作階段執行本節中的其餘指令。

  2. 將根 CA 憑證複製到 /usr/local/share/ca-certificates 目錄,並確認檔案的副檔名為 .crt

    sudo cp root-ca-cert.pem /usr/local/share/ca-certificates/cas-rootca.crt
    
  3. 設定檔案權限,讓所有使用者都能讀取根 CA 憑證檔案:

    sudo chmod 644 /usr/local/share/ca-certificates/cas-rootca.crt
    
  4. 執行 update-ca-certificates 指令碼:

    sudo update-ca-certificates
    

    這個指令碼會將憑證新增至 /etc/ssl/certs 目錄中的一組信任憑證,以及 /etc/ssl/certs/ca-certificates.crt 檔案。

    輸出內容如下:

    Updating certificates in /etc/ssl/certs...
    1 added, 0 removed; done.
    Running hooks in /etc/ca-certificates/update.d...
    done.
    
  5. 使用 curl 從 VM 執行個體傳送 HTTPS 要求至範例應用程式:

    curl --cert client-cert-chain.pem --key private-key.pem \
       --resolve hello.example.com:443:$(cat ilb-ip.txt) \
       --silent https://hello.example.com | head -n1
    

    輸出如下所示:

    Hello, world!
    

    這項回應表示 curl 成功使用 mTLS 傳送 HTTPS 要求,並使用預設 CA 憑證存放區,驗證來自 Ingress 閘道的伺服器 TLS 憑證。

  6. 離開 SSH 工作階段:

    exit
    

疑難排解

如果 CA 服務簽發者控制器未建立 TLS 憑證密鑰,請查看 CA 服務簽發者控制器的記錄:

kubectl logs deployment/google-cas-issuer --namespace cert-manager

如果安裝 Cloud Service Mesh 時發生問題,請執行 asmcli 工具來驗證雲端專案和 GKE 叢集

如果您在使用本教學課程時發生其他問題,建議查看下列文件:

清除所用資源

如要避免系統持續向您的 Google Cloud 帳戶收取本教學課程所用資源的費用,請刪除專案或個別資源。

刪除專案

  1. 在 Cloud Shell 中刪除專案:

    gcloud projects delete PROJECT_ID
    

刪除資源

如要保留您在本教學課程中使用的 Google Cloud 專案,請刪除個別的資源:

  1. 在 Cloud Shell 中,取消註冊 GKE 叢集與 GKE 機群:

    gcloud container hub memberships unregister CLUSTER_NAME \
        --gke-cluster ZONE/CLUSTER_NAME
    
  2. 刪除 GKE 叢集:

    gcloud container clusters delete CLUSTER_NAME \
        --zone ZONE --async --quiet
    
  3. 刪除下層 CA 集區的身分與存取權管理政策繫結:

    gcloud privateca pools remove-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    
    gcloud privateca pools remove-iam-policy-binding SUBORDINATE_CA_POOL_GATEWAYS \
        --location CA_LOCATION \
        --member "serviceAccount:CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/privateca.certificateRequester
    
  4. 停用並安排刪除從屬 CA 和根 CA:

    gcloud privateca subordinates disable SUBORDINATE_CA_GATEWAYS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_GATEWAYS \
        --quiet
    
    gcloud privateca subordinates delete SUBORDINATE_CA_GATEWAYS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_GATEWAYS \
        --ignore-active-certificates \
        --quiet
    
    gcloud privateca subordinates disable SUBORDINATE_CA_SIDECARS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_SIDECARS \
        --quiet
    
    gcloud privateca subordinates delete SUBORDINATE_CA_SIDECARS \
        --location CA_LOCATION \
        --pool SUBORDINATE_CA_POOL_SIDECARS \
        --ignore-active-certificates \
        --quiet
    
    gcloud privateca roots disable ROOT_CA \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --quiet
    
    gcloud privateca roots delete ROOT_CA \
        --location CA_LOCATION \
        --pool ROOT_CA_POOL \
        --ignore-active-certificates \
        --quiet
    
  5. 刪除 CA 服務簽發者控制器 Google 服務帳戶的 IAM 政策繫結:

    gcloud iam service-accounts remove-iam-policy-binding \
        CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[cert-manager/ksa-google-cas-issuer]" \
        --role roles/iam.workloadIdentityUser
    
  6. 刪除 Google 服務帳戶:

    gcloud iam service-accounts delete --quiet \
        CAS_ISSUER_GSA@PROJECT_ID.iam.gserviceaccount.com
    
    gcloud iam service-accounts delete --quiet \
        CLIENT_VM_GSA@PROJECT_ID.iam.gserviceaccount.com
    
  7. 刪除預留的負載平衡器 IP 位址:

    gcloud compute addresses delete asm-ingress-gateway-ilb \
        --region REGION --quiet
    
  8. 刪除 Compute Engine VM 執行個體:

    gcloud compute instances delete cas-tutorial-client \
        --zone ZONE --quiet
    

後續步驟