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

本教學課程將向平台操作人員說明如何使用 cert-manager 工具的憑證管理機構服務 (CA 服務) 核發者,為 Cloud Service Mesh 入口閘道自動化 TLS 憑證管理作業。憑證可讓入口閘道終止來自虛擬私有雲 (VPC) 中服務中介網外客戶的 HTTPS 和其他 TLS 和 mTLS 流量。本教學課程假設您對 Kubernetes 和 TLS 憑證有基本的瞭解。

簡介

Cloud Service Mesh 會為服務網格中的每個工作負載提供 TLS 憑證。這些憑證可在服務網格中,讓工作負載之間的通訊進行加密和雙向驗證 TLS (mTLS) 通訊。由其中一個支援的 CA 核發並簽署憑證。

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

cert-manager 工具會向發證者 (代表憑證授權單位 (CA)) 要求憑證。CA 服務是Google Cloud 服務,可讓您自行建立私人 CA。cert-manager 工具可使用開源 CA 服務的外部核發者,向 CA 服務要求憑證。

私人 CA 可以核發 TLS 憑證,驗證並加密內部網路中的流量。Cloud Service Mesh 輸入閘道通常會設為允許來自虛擬私人雲端網路內部 (但位於服務網格外) 的用戶端傳入流量。針對內部網路流量,您可以使用 CA 服務中的私人 CA 核發輸入網關的憑證。

本教學課程說明如何設定 cert-manager 工具和 CA 服務核發者,以便自動為入口網關提供和更新 TLS 憑證。cert-manager 工具會將憑證設為 類型為 TLS 的 Kubernetes 密鑰資源。當 cert-manager 工具續購憑證時,會使用新憑證更新密鑰資源。入口閘道會執行 Envoy Proxy,並支援 Envoy 的機密探索服務 (SDS)。SDS 可讓入口網關開始使用新的憑證,而不需要管理員重新啟動或重新載入程序。

屬於網格一部分的 Sidecar 代理程式可以從 CA 服務或 Cloud Service Mesh 憑證授權單位取得 TLS 憑證。在本教學課程中,您會使用 CA 服務為側邊車 Proxy 和 ingress 閘道憑證建立憑證。這樣一來,您就能為所有 TLS 憑證使用一個根 CA。

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

hello-example-com-credential 密鑰包含憑證和私密金鑰。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 容器可以使用 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」對話方塊中,按一下「授權」。按一下「Authorize」(授權),即可允許您在 Cloud Shell 中執行的 gcloud 指令使用您的使用者憑證,向 Google API 驗證。

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

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

設定 CA 服務

在本節中,您將在 CA 服務中建立根 CA 和兩個子 CA。一個從屬 CA 會向入口閘道核發憑證,另一個從屬 CA 則會向網狀結構中的側載代理程式核發憑證。

為簡化操作,本教學課程中的 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 使用:

    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. 建立並啟用向 ingress 閘道核發憑證的從屬 CA:

    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 為 mTLS 核發用戶端和伺服器 TLS 憑證。

    如果您希望入口網關使用簡易 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,為網格中的側載 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 引數可啟用 GKE 適用的工作負載身分聯盟,讓 CA 服務發布者 Kubernetes 服務帳戶模擬 Google 服務帳戶。這項模擬功能表示 CA 服務發布者 Pod 無須下載 Google 服務帳戶的金鑰檔案,即可存取 CA 服務 API。
  2. 授予使用者帳戶叢集管理員權限

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

    您需要 Kubernetes cluster-admin ClusterRole 提供的權限,才能為 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.25
    
    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.
    

安裝入口閘道

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

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

    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. 使用操作員資訊清單和 asmcli 指令碼在安裝控制層時下載的 istioctl 工具,建立入口網站閘道安裝資訊清單:

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

    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. 建立 Identity and Access Management 政策繫結,允許憑證授權單位服務核發者控制器 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. 為範例應用程式建立部署資源:

    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. 為範例應用程式建立服務資源:

    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
    

    憑證命名空間必須與入口網頁閘道命名空間相符。通常只有平台管理員可以變更這個命名空間中的資源,因為變更可能會影響整個服務中介網。cert-manager 工具會在相同命名空間中為傳輸層安全標準憑證建立 Secret 資源。也就是說,應用程式管理員不需要擁有入口網關命名空間的存取權。

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

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

    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 閘道終止前往 hello.example.com 的 TLS 流量。

    閘道資訊清單會指定相互傳輸層安全標準 (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 使用不同的命名空間。這個常見模式會限制閘道中以主機為基礎的路由變更,只有具備變更入口閘道命名空間資源權限的平台管理員才能變更。

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

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

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

驗證解決方案

在本節中,您將驗證是否可以從服務中介網外部傳送使用 mTLS 的 HTTPS 要求至範例應用程式。如要驗證,您需要建立 Compute Engine VM 執行個體,向 CA 服務要求用戶端 TLS 憑證,然後使用這張憑證驗證對範例應用程式提出的要求。

您需要透過 SSH 存取 VM 執行個體。預設網路包含允許 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. 將 Google 服務帳戶的 CA 服務憑證要求者角色指派給閘道子 CA 集區:

    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. 將入口閘道內部直通式網路負載平衡器的 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 憑證和包含內部直通式網路負載平衡器 IP 位址的 ingress 閘道檔案複製到 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 將 HTTPS 要求從 VM 執行個體傳送至範例應用程式:

    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 位址,做為通訊埠 443 上主機 hello.example.com 要求的目的。

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

      在您自己的環境中,建議您建立指向內部轉送 Network Load Balancer 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 憑證新增至 Linux Debian 發行版的信任 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 將 HTTPS 要求從 VM 執行個體傳送至範例應用程式:

    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 憑證存放區驗證入口網關的伺服器 TLS 憑證。

  6. 離開 SSH 工作階段:

    exit
    

疑難排解

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

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

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

如果您在本教學課程中遇到其他問題,建議查看下列文件:

清除所用資源

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

刪除專案

  1. 在 Cloud Shell 中刪除專案:

    gcloud projects delete PROJECT_ID
    

刪除資源

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

  1. 在 Cloud Shell 中,從 GKE Hub 取消註冊 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 集區中的 IAM 政策繫結:

    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
    

後續步驟