解決 Cloud Service Mesh 中的安全性問題

本節說明 Cloud Service Mesh with Istio API 的常見問題,以及如何解決這些問題。如需其他協助,請參閱「取得支援」。

在 Cloud Service Mesh 中,Cloud Service Mesh 憑證授權單位或 Istiod 會為網格中所有叢集的負載發放憑證。驗證 (例如 mTLS) 和授權政策 (例如允許/拒絕) 會推送至每個叢集。這些政策會決定哪些工作負載可以通訊,以及通訊方式。

TLS 問題

下列各節說明如何解決 Cloud Service Mesh 中的 TLS 相關問題。

本節範例使用 ${CTX} 變數,這是預設 Kubernetes 設定檔中用來存取叢集的內容名稱。請按照下列範例設定 ${CTX} 變數:

export CTX=gke_PROJECT_ID_CLUSTER_LOCATION_CLUSTER_NAME

驗證 TLS 強制執行狀態

如果服務需要 TLS 連線,請確認服務不允許純文字要求:

kubectl exec SOURCE_POD -n SOURCE_NAMESPACE -c \
    SOURCE_CONTAINER -- curl -v DESTINATION_URL

假設服務需要 TLS 連線,上述純文字要求應該會失敗,並產生類似下列的輸出內容:

curl: (56) Recv failure: Connection reset by peer command terminated with exit code 56

檢查 mTLS 憑證

啟用 mTLS 後,請查看 X-Forwarded-Client-Cert 標頭,檢查工作負載的 mTLS 憑證。如要這麼做,請按照下列步驟操作:

  1. 部署 httpbin 範例服務,該服務可顯示收到的標頭。

  2. 使用 curl 查看 X-Forwarded-Client-Cert 標頭:

    kubectl exec --context=${CTX} SOURCE_POD -n SOURCE_NAMESPACE -c \
    SOURCE_CONTAINER -- curl http://httpbin.sample:8000/headers -s | \
    grep X-Forwarded-Client-Cert

    X-Forwarded-Client-Cert 標頭會顯示 mTLS 憑證資訊,如下列範例所示:

    X-Forwarded-Client-Cert": "By=spiffe://lt-multicluster-t2-5-15-2020.svc.id.goog/ns/sample/sa/httpbin;Hash=0781d68adfdab85b08b6758ed502f352464e81166f065cc6acde9433337b4494;Subject=\"OU=istio_v1_cloud_workload,O=Google LLC,L=Mountain View,ST=California,C=US\";URI=spiffe://lt-multicluster-t2-5-15-2020.svc.id.goog/ns/sample/sa/sleep
  3. 或者,您也可以使用 sidecar 上的 openssl 查看完整憑證鏈結:

    kubectl debug --image istio/base --target istio-proxy -it --context=${CTX} SOURCE_POD \
    -n SOURCE_NAMESPACE -- openssl s_client -alpn istio -showcerts -connect httpbin.sample:8000

    輸出內容會顯示憑證鏈結。如果您使用 Mesh CA,請確認根憑證 CN 包含 istio_v1_cloud_workload_root-signer-...。如果使用 Istiod 做為憑證授權單位,請確認根憑證已透過 O = <var>YOUR_TRUST_DOMAIN</var> 設定。

Istiod 記錄中的 TLS bad certificate 錯誤

如果記錄中顯示 TLS 握手 bad certificate 錯誤,可能表示 Istiod 無法與服務建立 TLS 連線。

您可以使用規則運算式字串 TLS handshake error.*bad certificate 在記錄中找出這些錯誤。

這類錯誤通常是暫時性的資訊錯誤。但如果持續發生,可能表示系統有問題。

  1. 確認 istio-sidecar-injector MutatingWebhookConfiguration 具有 CA 組合。

    補充資訊注入器 Webhook (用於自動注入補充資訊) 需要 CA 組合,才能與 API 伺服器和 Istiod 建立安全連線。這個 CA 組合會由 istiod 修補到設定中,但有時可能會遭到覆寫 (例如,重新套用 Webhook 設定時)。

  2. 確認 CA 組合是否存在:

    kubectl get mutatingwebhookconfiguration -l app=sidecar-injector -o=jsonpath='{.items[0].webhooks[0].clientConfig.caBundle}'
    

    如果輸出內容不為空白,表示已設定 CA 組合。如果缺少 CA 組合,請重新啟動 istiod,讓系統重新掃描 Webhook 並重新安裝 CA 組合。

明確設定 SNI

在外部服務中使用 SNI 轉送流量時,如要使用 TLS 來源建立 TLS 連線,請在 DestinationRule 中明確指定 ClientTLSSettings.sni 的 SNI。例如,假設使用者要求系統 將文字從英文翻譯成法文

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: my-external-service-dr
spec:
  host: external.example.com # The host for which this DestinationRule applies
  trafficPolicy:
    tls:
      mode: SIMPLE # Or MUTUAL, if mTLS is required
      sni: specific-sni.example.com # The SNI value to set for outbound TLS connections

授權政策拒絕記錄

如要瞭解授權政策拒絕記錄,請參閱「拒絕記錄」。

未強制執行授權政策

如果發現授權政策未強制執行,請使用下列指令進行驗證:

kubectl exec --context=${CTX} -it SOURCE_POD -n SOURCE_NAMESPACE \
    -c SOURCE_CONTAINER -- curl DESTINATION_URL

在輸出內容中,access denied 訊息表示授權政策已正確強制執行,如下所示:

RBAC: access denied

如果確認授權政策未強制執行,請拒絕存取命名空間。以下範例會拒絕存取名為 authz-ns 的命名空間:

kubectl apply --context=${CTX} -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-authz-ns
  namespace: authz-ns
spec:
  {}
EOF

Istiod 記錄中出現「customresourcedefinitions.apiextensions.k8s.io is forbidden」錯誤

您可能會看到類似下列的錯誤:

error failed to list CRDs: customresourcedefinitions.apiextensions.k8s.io is forbidden: User "system:serviceaccount:istio-system:istiod-service-account" cannot list resource "customresourcedefinitions" in API group "apiextensions.k8s.io" at the cluster scope

您可以使用規則運算式字串 /error.*cannot list resource/,在記錄中找出這些錯誤。

如果 Istiod 部署作業缺少正確的 IAM 繫結,或是 RBAC 權限不足而無法讀取自訂資源,就可能會發生這項錯誤。

  1. 檢查帳戶中是否缺少 IAM 繫結。首先,請確認您已正確設定憑證和權限。 然後使用下列指令,確認 IAM 繫結是否存在。在本範例中,PROJECT_ID 是 gcloud config get-value project 的輸出內容,PROJECT_NUMBER 則是 gcloud projects list --filter="project_id=${PROJECT_ID}" --format="value(project_number)" 的輸出內容:

    gcloud projects add-iam-policy-binding ${PROJECT_ID} --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-meshdataplane.iam.gserviceaccount.com" --role "roles/meshdataplane.serviceAgent"
  2. 確認 RBAC 規則已正確安裝。

  3. 如果 RBAC 規則遺失,請重新執行 asmcli install 重新建立規則。

  4. 如果 RBAC 規則存在,但錯誤仍持續發生,請檢查 ClusterRoleBindingsRoleBindings 是否將 RBAC 規則附加至正確的 Kubernetes 服務帳戶。此外,請確認 istiod 部署作業是否使用指定的服務帳戶。

Istiod 記錄中的 serverca 個程序錯誤

您可能會看到類似下列的錯誤:

Authentication failed: Authenticator ClientCertAuthenticator at index 0 got error

您可以使用規則運算式字串 /serverca.*Authentication failed:.*JWT/,在記錄中找出這些錯誤。

如果 JWT 簽發者設定錯誤、用戶端使用過期權杖,或有其他安全性問題導致連線無法正確向 istiod 驗證,就可能發生這個錯誤。

Ingress 閘道 TLS 的憑證和私密金鑰更新速度緩慢

如果叢集使用TRAFFIC_DIRECTOR控制層實作,且 Ingress 閘道使用未掛接憑證的部署,憑證更新最多可能需要 60 分鐘。

如要讓新憑證立即生效,可以重新啟動 Ingress 閘道 Pod,或按照最佳化部署作業的操作說明進行。