將 IAP 與 Cloud Service Mesh 整合
本指南說明如何將 Identity-Aware Proxy (IAP) 與 Cloud Service Mesh 整合。透過 IAP 與 Cloud Service Mesh 整合,您就能根據 Google 的 BeyondCorp 原則安全存取服務。IAP 會驗證使用者身分和要求背景資訊,判斷是否應允許使用者存取應用程式或資源。Cloud Service Mesh 整合 IAP 後,可提供下列優點:
對 Cloud Service Mesh 執行的工作負載,進行完整的情境感知存取權控管。您可以根據原始要求的屬性 (例如使用者身分、IP 位址和裝置類型),設定精細的存取權政策。您可以結合存取政策與要求網址的主機名稱和路徑限制。
在 Cloud Service Mesh 授權中,啟用情境感知要求支援。
透過 Google Cloud 負載平衡器,以可擴充、安全且高可用性的方式存取應用程式。高效能負載平衡功能提供內建的分散式阻斷服務 (DDoS) 攻擊防護機制,並支援全球任意傳播 IP 位址。
必要條件
按照「安裝依附元件工具並驗證叢集」中的步驟操作,完成下列事項:此外,本指南假設您已具備下列條件:
設定採用 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根據預設,
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 輸入閘道服務規格,並命名為
iap_operator.yaml。將 ingress 安裝為 NodePort 服務。詳情請參閱「從 IstioOperator 遷移」。
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 負載平衡器,請執行下列指令,保留現有的 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 Proxy 插入功能,即可完成升級。詳情請參閱「部署及重新部署工作負載」。
升級完成後,請返回本指南並繼續下一個章節,設定與 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 的閘道資源 (定義於 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 Secret: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 閘道執行健康狀態檢查,以及設定 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}')健康狀態檢查 ingress 路徑:這是 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 範例的閘道資源。
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) 頁面
「狀態」欄應會顯示「正在建立輸入」訊息。請等待 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。如果多次重新整理頁面,應該會看到不同版本的評論,以輪替方式呈現:紅色星星、黑色星星、沒有星星。您也應該測試
https對 Bookinfo 的存取權。
在服務網格上啟用 RCToken 支援
根據預設,IAP 會產生範圍限定於 OAuth 用戶端的 JSON Web Token (JWT)。如果是 Cloud Service Mesh,您可以設定 IAP 產生 RequestContextToken (RCToken),這是一種 JWT,但可設定目標對象。您可以將 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