整合 IAP 與 Cloud Service Mesh
本指南說明如何整合Identity-Aware Proxy (IAP) 與 Cloud Service Mesh。透過 IAP 與 Cloud Service Mesh 整合,您就能根據 Google 的 BeyondCorp 原則安全存取服務。IAP 會驗證使用者身分和要求內容,判斷是否授予應用程式或資源的存取權。將 IAP 與 Cloud Service Mesh 整合,可享有下列優點:
針對在 Cloud Service Mesh 上執行的工作負載,完成情境感知存取權控制。您可以根據原始要求的屬性 (例如使用者身分、IP 位址和裝置類型),設定精細的存取政策。您可以將存取政策與要求網址的主機名稱和路徑限制結合使用。
在 Cloud Service Mesh 授權中啟用情境感知聲明支援功能。
透過 Google Cloud 負載平衡器,以可擴充、安全且高可用性的方式存取應用程式。高效能負載平衡功能內建分散式阻斷服務 (DDoS) 攻擊防護機制,並支援全域任播 IP 位址。
必要條件
按照「安裝依附工具並驗證叢集」中的步驟操作, 完成下列事項:此外,本指南假設您已具備下列條件:
設定採用 Cloud Service Mesh 的叢集
本節說明如何為 Cloud Service Mesh 的新安裝作業和升級作業,設定 IAP 整合功能。
新安裝次數
啟用
iap.googleapis.com。在下列指令中,將PROJECT_ID替換為要安裝 Cloud Service Mesh 的專案:gcloud services enable \ --project=PROJECT_ID \ iap.googleapis.com要更新的叢集必須設定
--addons=HttpLoadBalancing選項。HttpLoadBalancing外掛程式可為叢集啟用 HTTP (L7) 負載平衡控制器。執行下列指令,使用 Cloud Service Mesh 必要的選項更新叢集。除非已設定預設區域或地區,否則您必須在指令中提供區域 (--region=REGION) 或可用區 (--zone=ZONE)。gcloud container clusters update CLUSTER_NAME \ --project=PROJECT_ID \ --update-addons=HttpLoadBalancing=ENABLED根據預設,
iap-operator.yaml檔案會將通訊埠 31223 設為狀態通訊埠,並將通訊埠 31224 設為 HTTP 通訊埠。如果叢集已使用通訊埠 31223,請執行下列指令設定其他狀態通訊埠:kpt cfg set asm gcloud.container.cluster.ingress.statusPort STATUS_PORT如果叢集已使用通訊埠 31224,請執行下列指令來設定其他 HTTP 通訊埠:
kpt cfg set asm gcloud.container.cluster.ingress.httpPort HTTP_PORT按照「安裝預設功能和 Mesh CA」中的步驟操作,使用 Google 提供的指令碼安裝 Cloud Service Mesh。執行指令碼時,請加入下列選項:
--option iap-operator例如:
./asmcli install \ --project_id "PROJECT_ID" \ --cluster_name "CLUSTER_NAME" \ --cluster_location "CLUSTER_LOCATION" \ --fleet_id FLEET_PROJECT_ID \ --output_dir DIR_PATH \ --enable_all \ --option iap-operator安裝 Cloud Service Mesh 時,
iap-operator.yaml檔案會將istio-ingressgateway服務的type欄位設為NodePort,將閘道設定為在服務網格上開啟特定連接埠。這樣一來,您就能設定負載平衡器,將傳送至網域名稱的流量導向這個連接埠。如要安裝代管 Cloud Service Mesh,請完成下列步驟:
將修訂版本標籤新增至
istio-system命名空間。下載 IAP 適用的 Istio Ingress 閘道服務規格,並命名為
iap_operator.yaml。將 Ingress 安裝為 NodePort 服務。
asmcli experimental mcp-migrate-check -f iap_operator.yaml istioctl install -f /asm-generated-configs/gateways-istiooperator/"GATEWAY_NAME".yaml
安裝 Cloud Service Mesh 後,請返回本指南並繼續下一個章節,設定與 IAP 的整合。
升級
本節涵蓋下列升級用途:
您已設定 IAP 整合功能,並要升級 Cloud Service Mesh。在本例中,您已在專案中啟用
iap.googleapis.com,並在叢集中啟用HttpLoadBalancing外掛程式。跳至步驟 3,下載asm套件並升級 Cloud Service Mesh。您要升級 Cloud Service Mesh,並首次設定與 IAP 的整合。在這種情況下,您需要完成下列所有步驟、升級 Cloud Service Mesh,並在升級後返回本指南,完成整合程序。
啟用
iap.googleapis.com。在下列指令中,將PROJECT_ID替換為要安裝 Cloud Service Mesh 的專案。gcloud services enable \ --project=PROJECT_ID \ iap.googleapis.com要更新的叢集必須設定
--addons=HttpLoadBalancing選項。HttpLoadBalancing外掛程式可為叢集啟用 HTTP (L7) 負載平衡控制器。執行下列指令,使用 Cloud Service Mesh 必要的選項更新叢集。除非已設定預設區域或地區,否則您必須在指令中提供區域 (--region=REGION) 或可用區 (--zone=ZONE)。gcloud container clusters update CLUSTER_NAME \ --project=PROJECT_ID --update-addons=HttpLoadBalancing=ENABLED如要更新現有的 HTTP Cloud Load Balancer,請執行下列指令,保留現有的 HTTP 和狀態埠:
kpt cfg set asm gcloud.container.cluster.ingress.httpPort $(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')kpt cfg set asm gcloud.container.cluster.ingress.statusPort $(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="status-port")].nodePort}')按照「升級 Cloud Service Mesh」中的步驟操作,使用 Google 提供的指令碼升級 Cloud Service Mesh。
升級 Cloud Service Mesh 時,
iap-operator.yaml檔案會將istio-ingressgateway服務的type欄位設為NodePort,將閘道設定為開啟服務網格上的特定通訊埠。這樣一來,您就能設定負載平衡器,將傳送至網域名稱的流量轉送至這個通訊埠。根據預設,
iap-operator.yaml檔案會將通訊埠 31223 設為狀態通訊埠,並將通訊埠 31224 設為 HTTP 通訊埠。執行指令碼時,請加入下列選項:
--option iap-operator例如:
./asmcli install \ --project_id "PROJECT_ID" \ --cluster_name "CLUSTER_NAME" \ --cluster_location "CLUSTER_LOCATION" \ --fleet_id FLEET_PROJECT_ID \ --output_dir DIR_PATH \ --enable_all \ --option iap-operator在工作負載上觸發自動 Sidecar 代理程式插入作業,即可完成升級。詳情請參閱「部署及重新部署工作負載」。
升級完成後,請返回本指南並繼續下一個章節,設定與 IAP 的整合。
保留靜態 IP 位址並設定 DNS
如要整合 Identity-Aware Proxy 與 Cloud Service Mesh,您必須設定Google Cloud HTTP(S) 負載平衡器,這需要指向靜態 IP 位址的網域名稱。您可以保留靜態外部 IP 位址,進而將位址無期限地指派給專案,直到明確釋放該位址為止。
預留靜態外部 IP 位址:
gcloud compute addresses create example-static-ip --global取得靜態 IP 位址:
gcloud compute addresses describe example-static-ip --global在網域名稱註冊機構中,使用靜態 IP 位址設定完整網域名稱 (FQDN)。通常您會在 DNS 設定中新增
A記錄。為 FQDN 新增A記錄的設定步驟和術語,會因網域名稱註冊商而異。DNS 設定最多可能需要 24 到 48 小時才會生效。您可以繼續按照本指南設定所有項目,但 DNS 設定傳播完畢後,才能測試設定。
部署範例應用程式
啟用 IAP 前,您需要先在 GKE 叢集上執行應用程式,以便驗證所有要求是否都有身分。本指南使用 Bookinfo 範例,說明如何設定 HTTP(S) 負載平衡器及啟用 IAP。
請按照步驟部署 Bookinfo。部署負載平衡器之前,您無法從 GKE 叢集外部存取 Bookinfo 應用程式 (例如從瀏覽器)。
外部要求
Bookinfo 的 Gateway 資源 (定義於 samples/bookinfo/networking/bookinfo-gateway.yaml) 使用預先設定的 istio-ingressgateway。回想一下,部署 Cloud Service Mesh 時,您為 istio-ingressgateway 指定了 NodePort,這會在服務網格上開啟特定連接埠。雖然叢集中的節點具有外部 IP 位址,但 Google Cloud 防火牆規則會封鎖來自叢集外部的要求。使用 IAP 時,將應用程式公開發布至網際網路的正確方式是使用負載平衡器。請勿使用防火牆規則公開節點位址,否則會略過 IAP。
如要將要求轉送至 Bookinfo,請在Google Cloud 專案中設定 HTTP(S) 負載平衡器。由於負載平衡器位於專案中,因此會受到防火牆保護,並可存取叢集中的節點。使用靜態 IP 位址和網域名稱設定負載平衡器後,您可以將要求傳送至網域名稱,負載平衡器會將要求轉送至叢集中的節點。
啟用 IAP
下列步驟說明如何啟用 IAP。
設定同意畫面
使用 list 指令,確認是否已有現有品牌。每個專案只能有一個品牌。
gcloud iap oauth-brands list
如果品牌存在,gcloud 回應範例如下:
name: projects/[PROJECT_NUMBER]/brands/[BRAND_ID] applicationTitle: [APPLICATION_TITLE] supportEmail: [SUPPORT_EMAIL] orgInternalOnly: true如果沒有品牌,請使用 create 指令:
gcloud iap oauth-brands create --application_title=APPLICATION_TITLE --support_email=SUPPORT_EMAIL
supportEmail:OAuth 同意畫面上顯示的支援電子郵件地址。 這個電子郵件地址可以是使用者的地址,也可以是 Google 網路論壇別名。 服務帳戶也有電子郵件地址,但並非實際有效的電子郵件地址,因此無法用於建立品牌。不過,服務帳戶可以成為 Google 群組的擁有者。建立新的 Google 群組,或設定現有群組,並將所需服務帳戶設為群組擁有者。applicationTitle:OAuth 同意畫面上顯示的應用程式名稱。
回應包含下列欄位:
name: projects/[PROJECT_NUMBER]/brands/[BRAND_ID] applicationTitle: [APPLICATION_TITLE] supportEmail: [SUPPORT_EMAIL] orgInternalOnly: true
建立 IAP OAuth 用戶端
使用 create 指令建立用戶端。使用上一個步驟中的品牌
name。gcloud iap oauth-clients create projects/PROJECT_NUMBER/brands/BRAND-ID --display_name=NAME
回應包含下列欄位:
name: projects/[PROJECT_NUMBER]/brands/[BRAND_NAME]/identityAwareProxyClients/[CLIENT_ID] secret: [CLIENT_SECRET] displayName: [NAME]使用用戶端 ID (上一步中的
CLIENT_ID) 和CLIENT_SECRET啟用 IAP。使用 OAuth 用戶端的資料建立 Kubernetes 密鑰:kubectl create secret generic -n istio-system my-secret --from-literal=client_id=CLIENT_ID \ --from-literal=client_secret=CLIENT_SECRET
部署負載平衡器
您可以使用 Ingress 資源建立 HTTP(S) 負載平衡器,並自動設定 SSL 憑證。系統會針對您的網域佈建、更新及管理代管的 SSL 憑證。
建立 ManagedCertificate 資源。該資源可以指定 SSL 憑證的網域。
spec.domains清單只能包含一個網域。 系統不支援萬用字元網域。在下列 YAML 中,將DOMAIN_NAME替換為您為外部靜態 IP 位址設定的網域名稱。cat <<EOF | kubectl apply -f - apiVersion: networking.gke.io/v1 kind: ManagedCertificate metadata: name: example-certificate namespace: istio-system spec: domains: - DOMAIN_NAME EOF建立 BackendConfig 資源。這項資源會指示 GCLB 如何對 Ingress Gateway 執行健康狀態檢查,以及如何設定 Identity-Aware Proxy。首先,從 Ingress Gateway 收集有關健康狀態檢查的幾個值:
健康狀態檢查 Ingress 通訊埠:這是 istio-ingress 的健康狀態檢查通訊埠。
export HC_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="status-port")].nodePort}')健康狀態檢查輸入路徑:這是 istio-ingress 的健康狀態檢查路徑。
export HC_INGRESS_PATH=$(kubectl get pods -n istio-system -l app=istio-ingressgateway -o jsonpath='{.items[0].spec.containers[?(@.name=="istio-proxy")].readinessProbe.httpGet.path}')
cat <<EOF | kubectl apply -n istio-system -f - apiVersion: cloud.google.com/v1 kind: BackendConfig metadata: name: http-hc-config spec: healthCheck: checkIntervalSec: 2 timeoutSec: 1 healthyThreshold: 1 unhealthyThreshold: 10 port: ${HC_INGRESS_PORT} type: HTTP requestPath: ${HC_INGRESS_PATH} iap: enabled: true oauthclientCredentials: secretName: my-secret EOF使用 BackendConfig 為 Ingress 服務加上註解。
kubectl annotate -n istio-system service/istio-ingressgateway --overwrite \ cloud.google.com/backend-config='{"default": "http-hc-config"}' \ cloud.google.com/neg='{"ingress":false}'定義 Ingress 資源,建立負載平衡器。
將
networking.gke.io/managed-certificates註解設為您在上一步中建立的憑證名稱example-certificate。將
kubernetes.io/ingress.global-static-ip-name註解設為您保留的靜態 IP 位址名稱,即example-static-ip。將
serviceName設為istio-ingressgateway,這會用於 Bookinfo 範例的 Gateway 資源。
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress namespace: istio-system annotations: kubernetes.io/ingress.global-static-ip-name: example-static-ip networking.gke.io/managed-certificates: example-certificate spec: defaultBackend: service: name: istio-ingressgateway port: number: 80 EOF在 Google Cloud 控制台中,前往「Kubernetes Engine」 >「Services & Ingress」(服務和 Ingress) 頁面。
前往「Services & Ingress」(Service 與 Ingress) 頁面
您應該會在「狀態」欄中看到「正在建立 Ingress」訊息。 請等待 GKE 完整佈建 Ingress,再繼續操作。請每隔幾分鐘重新整理頁面,查看 Ingress 的最新狀態。Ingress 佈建完成後,您可能會看到「Ok」狀態,或是「All backend services are in UNHEALTHY state」(所有後端服務都處於不正常狀態) 錯誤。GKE 佈建的資源之一是預設健康狀態檢查。如果看到錯誤訊息,表示 Ingress 已佈建,且預設健康狀態檢查已執行。看到「Ok」狀態或錯誤訊息後,請繼續下一個部分,設定負載平衡器的健康狀態檢查。
設定 IAP 存取權清單
將使用者新增至 IAP 的存取權政策:
gcloud beta iap web add-iam-policy-binding \
--member=user:EMAIL_ADDRESS \
--role=roles/iap.httpsResourceAccessor其中 EMAIL_ADDRESS 是使用者的完整電子郵件地址,例如 alice@example.com。
測試負載平衡器。將瀏覽器指向:
http://DOMAIN_NAME/productpage
其中
DOMAIN_NAME是您使用外部靜態 IP 位址設定的網域名稱。您應該會看到 Bookinfo 應用程式的
productpage。請重新整理頁面幾次,您應該會看到不同版本的評論,以循環配置方式呈現:紅色星號、黑色星號、無星號。您也應該測試對 Bookinfo 的
https存取權。
在服務網格上啟用 RCToken 支援
根據預設,IAP 會產生範圍限定於 OAuth 用戶端的 JSON Web Token (JWT)。如果是 Cloud Service Mesh,您可以設定 IAP 產生 RequestContextToken (RCToken),這是一種 JWT,但可設定對象。您可以透過 RCToken 將 JWT 的目標對象設定為任意字串,用於 Cloud Service Mesh 政策,進行精細的授權。
如要設定 RCToken,請按照下列步驟操作:
為 RCToken 目標對象建立環境變數。可以是任何字串。
export RCTOKEN_AUD="your-rctoken-aud"選用:下列步驟需要使用
BACKEND_SERVICE_ID。如要找出BACKEND_SERVICE_ID,請執行下列指令:kubectl -n istio-system get Ingress example-ingress -o json | jq \ '.metadata.annotations."ingress.kubernetes.io/backends"'預期的輸出內容類似於
"{\"BACKEND_SERVICE_ID\":\"HEALTHY\"}"。 例如:"ingress.kubernetes.io/backends": "{\"k8s-be-31224--51f3b55cd1457fb6\":\"HEALTHY\"}"。 在本範例中,BACKEND_SERVICE_ID為k8s-be-31224--51f3b55cd1457fb6。擷取現有的 IAP 設定。
gcloud iap settings get --format json \ --project=${PROJECT_ID} --resource-type=compute --service=BACKEND_SERVICE_ID > iapSettings.json使用 RCToken 目標對象更新
IapSettings。cat iapSettings.json | jq --arg RCTOKEN_AUD_STR $RCTOKEN_AUD \ '. + {applicationSettings: {csmSettings: {rctokenAud: $RCTOKEN_AUD_STR}}}' \ > updatedIapSettings.jsongcloud iap settings set updatedIapSettings.json --format json \ --project=${PROJECT_ID} --resource-type=compute --service=BACKEND_SERVICE_ID在 Istio Ingress 閘道上啟用 RCToken 驗證。
cat <<EOF | kubectl apply -f - apiVersion: "security.istio.io/v1beta1" kind: "RequestAuthentication" metadata: name: "ingressgateway-jwt-policy" namespace: "istio-system" spec: selector: matchLabels: app: istio-ingressgateway jwtRules: - issuer: "https://cloud.google.com/iap" jwksUri: "https://www.gstatic.com/iap/verify/public_key-jwk" audiences: - $RCTOKEN_AUD fromHeaders: - name: ingress-authorization prefix: "Istio " outputPayloadToHeader: "verified-jwt" forwardOriginalToken: true EOF選用:確保系統拒絕沒有有效 JWT 的要求:
cat <<EOF | kubectl apply -f - apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: iap-gateway-require-jwt namespace: istio-system spec: selector: matchLabels: app: istio-iap-ingressgateway action: DENY rules: - from: - source: notRequestPrincipals: ["*"] EOF確認對 Bookinfo
productpage的要求仍可成功:http://DOMAIN_NAME/productpage
如要測試政策,請按照下列步驟操作:
建立
IapSettings要求物件,但將rctokenAud設為不同的字串:cat iapSettings.json | jq --arg RCTOKEN_AUD_STR wrong-rctoken-aud \ '. + {applicationSettings: {csmSettings: {rctokenAud: $RCTOKEN_AUD_STR}}}' \ > wrongIapSettings.json呼叫
IapSettingsAPI,設定 RCtoken 目標對象。gcloud beta iap settings set wrongIapSettings.json --project=PROJECT_ID --resource-type=compute --service=BACKEND_SERVICE
向 Bookinfo
productpage發出要求,應該會失敗:http://DOMAIN_NAME/productpage
正在清除所用資源
完成本教學課程後,請移除下列資源,以免您的帳戶產生不必要的費用:
刪除代管憑證:
kubectl delete managedcertificates example-certificate
刪除 Ingress,這會取消分配負載平衡資源:
kubectl -n istio-system delete ingress example-ingress
刪除靜態 IP 位址:
gcloud compute addresses delete example-static-ip --global
如果這麼做,請務必從網域註冊商刪除 IP 位址。
刪除叢集,這會一併刪除組成叢集的資源,例如運算執行個體、磁碟和網路資源:
gcloud container clusters delete CLUSTER_NAME