身分識別代理 (IAP) 簡介
Identity-Aware Proxy (IAP) 是 Google Cloud 託管的應用層存取控制平台。與其將內部應用程式包進企業 VPN 邊界內,IAP 在每一個受保護資源前方放置一個由 Google 營運的反向代理,並在每一個獨立 HTTPS 或 TCP 請求上,判定呼叫者的身分與背景資訊是否符合你的政策。代理在 Google Front End (GFE) 處終止連線,評估 IAM 繫結與選用的 Access Context Manager 規則,通過後才把請求轉發到 App Engine、Cloud Run、GKE、Compute Engine VM 或甚至地端後端。
IAP 是 Google 自己於 2011 至 2017 年間採用的 BeyondCorp 模型的標準實作。PCD 考試經常測試四種情境:(1) 以 IAP 取代 VPN 集中器來保護 SaaS 風格的網頁應用程式,(2) 透過 IAP TCP 轉發為堡壘主機 (bastion) 移除公用 IP 以提供 SSH/RDP,(3) 在 IAM 之上疊加 Access Levels(公司網段 CIDR、作業系統版本、瀏覽器版本),(4) 透過跑在 GKE 上的 IAP Connector 將 IAP 延伸到地端工作負載。
身分識別代理 (Identity-Aware Proxy, IAP): 一項 Google Cloud 服務,透過 Google Sign-In 或外部 IdP 驗證使用者,再以 IAM 角色 roles/iap.httpsResourceAccessor (網頁應用程式) 或 roles/iap.tunnelResourceAccessor (TCP) 進行授權,並透過 Global External Application Load Balancer 或私有 TCP 通道將通過驗證的請求轉發到後端,全程不暴露後端 IP 位址。
IAP 如何保護 HTTPS 網頁應用程式
當 IAP 在 Global External Application Load Balancer 的 backend service 上啟用後,每一個 HTTP 請求都會在 GFE 被攔截。未驗證的呼叫者會被重新導向至 accounts.google.com 登入;已驗證的呼叫者必須再滿足 iap.webServiceVersions.accessViaIAP 權限,該權限透過 roles/iap.httpsResourceAccessor 授予。兩項檢查都通過後,IAP 才會把請求連同兩個簽署標頭一起轉發到後端。
兩個關鍵簽署標頭
x-goog-authenticated-user-email 攜帶經驗證的使用者身分,格式為 accounts.google.com:[email protected]。x-goog-authenticated-user-id 攜帶穩定的數值使用者 ID。這兩個標頭本身並未加密簽署——它們是便利標頭,會從任何外來請求中剝除,因此在 GFE 處無法被偽造。然而,若攻擊者繞過負載平衡器(例如直接打 VM 的外部 IP),就可能注入偽造值。這正是為何 IAP 還會發出 x-goog-iap-jwt-assertion,一個你的應用程式在每個請求都必須驗證的加密簽署 JWT。
JWT audience 與簽章驗證
x-goog-iap-jwt-assertion JWT 使用 ES256 演算法簽署,金鑰來自 https://www.gstatic.com/iap/verify/public_key-jwk。你的應用程式必須 (1) 驗證 ES256 簽章,(2) 確認 iss claim 等於 https://cloud.google.com/iap,(3) 確認 aud claim 符合資源專屬的 audience 字串。App Engine 的 audience 為 /projects/PROJECT_NUMBER/apps/PROJECT_ID;Compute Engine / GKE 則是 /projects/PROJECT_NUMBER/global/backendServices/BACKEND_SERVICE_ID。audience 比對錯誤是最常見的實作 bug——它會默默接受發給其他後端的 JWT。
務必在伺服器端用資源專屬的 audience 驗證 x-goog-iap-jwt-assertion。使用者電子郵件簽署標頭 (x-goog-authenticated-user-email) 雖然方便,但與你的後端並無加密綁定——只有 JWT assertion 是。請把電子郵件標頭當作顯示用資料,授權判斷的真相來源只能是 JWT。
IAP TCP 轉發:無需堡壘主機的 SSH 與 RDP
IAP 的第二大用法是把任意 TCP 流量隧道化到 VM 的內部 IP,徹底免除公用 IP 位址、跳板主機或 VPN 的需求。使用者執行 gcloud compute ssh INSTANCE --tunnel-through-iap,會開啟一條 WebSocket 連線到 tunnel.cloudproxy.app:443,以使用者的 gcloud OAuth 權杖驗證,並透過 Google 網路把 TCP 位元組代理到 VM。RDP 的做法相同:gcloud compute start-iap-tunnel INSTANCE_NAME --local-host-port=localhost:3389 --instance-port=3389。
IAP TCP 範圍的防火牆規則
VM 不需要外部 IP,但其防火牆必須允許來自 IAP 來源範圍 35.235.240.0/20 的 TCP 流量。典型規則:gcloud compute firewall-rules create allow-iap-ssh --direction=INGRESS --action=allow --rules=tcp:22 --source-ranges=35.235.240.0/20。沒有這條規則的話,通道會完成 OAuth 握手,但 SYN 封包會在 VPC 防火牆被丟棄。
TCP 通道所需角色
通道使用者需要範圍綁定到專案、folder 或特定 instance 的 roles/iap.tunnelResourceAccessor。為了最小權限,請以 IAM 條件把角色限制到單一 VM:--condition='expression=resource.name=="projects/PROJECT/zones/ZONE/instances/INSTANCE"'。若希望 gcloud 透過 OS Login 產生 SSH 金鑰,使用者還需要 roles/compute.instanceAdmin.v1 或 roles/iam.serviceAccountUser。
把 IAP TCP 轉發與 OS Login 和 Google 帳戶兩步驟驗證搭配,就能得到完整稽核、MFA 保護的 SSH 路徑且零公用 IP。Cloud Audit Logs 在 audit.googleapis.com/data_access 下記錄每一次通道工作階段,包含使用者電子郵件、來源 IP 與目標 instance——比自管堡壘主機更完整的鑑識證據。
OAuth Consent Screen:必備前置條件
在能為網頁應用程式啟用 IAP 之前,專案必須先在 Google Auth Platform(舊稱「API 和服務 → OAuth 同意畫面」)配置好 OAuth Consent Screen。IAP 用內部 OAuth 用戶端來代理登入流程,而在 consent screen 設好應用程式名稱、支援電子郵件與授權網域之前,Google 拒絕建立該用戶端。
Internal 與 External 使用者類型
若工作負載只應被你的 Workspace 組織存取,將 consent screen 使用者類型設為 Internal——只有 cloudidentity.googleapis.com 組織內的帳戶能登入,應用程式不需要走 Google 的審核流程。External 類型允許任何 @gmail.com 帳戶或外部 Workspace,且超過 100 位使用者就會觸發應用程式審核。多數企業級 PCD 情境使用 Internal。
授權網域與品牌
Consent screen 必須列出任何 redirect URI 的頂級網域(例如 example.com)。IAP 會自動產生形如 https://iap.googleapis.com/v1/oauth/clientIds/CLIENT_ID:handleRedirect 的 redirect URI 並由 Google 管理——你不需要編輯它們。授權網域配置錯誤會在首次登入時導致 redirect_uri_mismatch 錯誤。
IAP 的 IAM 角色與權限
IAP 授權建立在兩個預定義 IAM 角色上,兩者都必須繫結在 IAP 保護的資源(或任一上層)上,而非底層 backend service。
roles/iap.httpsResourceAccessor
此角色僅含一個權限 iap.webServiceVersions.accessViaIAP,是終端使用者進入 IAP 保護網頁應用程式所需的唯一角色。繫結點可以是 App Engine service、負載平衡器的 backend service 或階層中更高的層級。授予 roles/owner 或 roles/editor 並不會自動含有此權限——IAP 角色刻意與專案層級的管理角色分開。
roles/iap.tunnelResourceAccessor
TCP 對應角色。含有 iap.tunnelInstances.accessViaIAP,授予開啟 IAP 通道至特定 Compute Engine VM 的能力。與 HTTPS 角色相同,必須繫結在 instance、zone、專案或上層 folder/組織。
管理角色
roles/iap.admin 允許啟用/停用 IAP 並管理設定。roles/iap.settingsAdmin 是更窄的角色,僅能管理 IAP 設定 (CORS、access token),不授予終端使用者存取權。iap.googleapis.com API 本身必須在專案中啟用。
網頁使用者需要 roles/iap.httpsResourceAccessor。SSH/RDP 使用者需要 roles/iap.tunnelResourceAccessor。管理員需要 roles/iap.admin。TCP 轉發的防火牆規則來源範圍是 35.235.240.0/20。JWT 標頭是 x-goog-iap-jwt-assertion,以 ES256 簽署。這五點涵蓋約 80% 的 IAP 考題。
與 Global External Application Load Balancer 的整合
針對 Compute Engine 與 GKE 工作負載,IAP 需要 Global External Application Load Balancer(前稱「HTTP(S) Load Balancer」)。Regional load balancer 與 Network Load Balancer 不支援 IAP——這是常見陷阱。流程為:客戶端 → DNS → anycast VIP → GFE → IAP 檢查 → backend service → instance group / NEG。
在 backend service 上啟用 IAP
gcloud compute backend-services update BACKEND_SERVICE --global --iap=enabled,oauth2-client-id=CLIENT_ID,oauth2-client-secret=SECRET。OAuth 用戶端必須是同專案內建立的「Web application」類型。啟用後,IAP 會自動改寫負載平衡器的 URL map 來插入代理。
防火牆與健康檢查考量
後端 instance 必須允許來自 130.211.0.0/22 與 35.191.0.0/16(負載平衡器健康檢查範圍)的 ingress。IAP 的 JWT 驗證步驟發生在 GFE,但後端仍需回應未驗證的健康檢查——透過 path-based routing 將 /healthz 或 /_ah/health 排除在 IAP 外,或信任健康檢查來自 LB 範圍。
Cloud Armor 與 IAP 的疊加
Cloud Armor 安全政策在 IAP 之前執行,因此你可以在不消耗 IAP 配額的情況下封鎖地理位置或已知惡意 ASN。Armor 放行後,IAP 才執行身分與 Access Level 檢查。兩項服務乾淨組合:Armor 處理 L7 DDoS 與地理封鎖、IAP 處理使用者身分。
透過 Access Levels 實現背景資訊感知存取
Access Context Manager 讓你能表達條件式存取政策——「只允許來自公司網段」、「只在裝置 OS 已修補時」、「只從受管 Chrome 瀏覽器」。Access Levels 再透過 accessPolicy 與 accessLevels 欄位附加到 IAP IAM 繫結。
定義 Access Level
gcloud access-context-manager levels create corp_network --policy=POLICY_ID --title="Corp Network" --basic-level-spec=corp.yaml,其中 corp.yaml 宣告條件如 ipSubnetworks: ["203.0.113.0/24"]、requiredAccessLevels: []、devicePolicy.requireScreenlock: true、devicePolicy.osConstraints.osType: DESKTOP_MAC。單一「basic」區塊內多個條件以 AND 結合;跨區塊則以 OR 結合。
BeyondCorp Enterprise 與 Endpoint Verification
裝置感知條件 (OS 版本、螢幕鎖、加密狀態) 需要 Endpoint Verification——一個 Chrome 擴充功能或 Workspace 受管代理程式,會回報裝置態勢給 Google。配上 BeyondCorp Enterprise 授權,還能取得瀏覽器內的資料外洩防護、威脅防護,以及限制存取到於管理控制台註冊的公司擁有裝置之 requireCorpOwned 條件。
將 Access Level 繫結到 IAP
在 Console 中:IAP → 選取資源 → Access Levels → 選擇 corp_network。以程式碼操作:gcloud iap web set-iam-policy 並在繫結加上 condition: { expression: "request.auth.access_levels.contains('accessPolicies/POLICY/accessLevels/corp_network')" }。滿足 IAM 但未通過 Access Level 的使用者會看到 403 頁面,並說明哪個條件失敗。
Access Levels 是在 IAM 之上評估,並非取代 IAM。沒有 roles/iap.httpsResourceAccessor 的使用者即使裝置完美仍無法存取資源;反之,擁有角色但坐在未受管筆電前的使用者會被封鎖。設計政策時,IAM 定義「誰有可能存取」,Access Levels 定義「在什麼條件下存取」。
IAP 搭配 Cloud Identity 與外部 IdP
IAP 預設驗證 Google 身分——任何 Cloud Identity、Google Workspace 帳戶,或當 consent screen 允許 External 時的 @gmail.com 帳戶。對已採用 Okta、Azure AD 或 Ping 為主要 IdP 的組織,存在兩種整合模式。
模式 A:Workforce Identity Federation
Workforce Identity Federation 讓使用者以企業 SAML/OIDC IdP 驗證,並取得短期有效的 Google 認證,無需建立影子 Google 帳戶。使用者透過 https://auth.cloud.google.com/signin/locations/global/workforcePools/POOL_ID/providers/PROVIDER_ID 登入,取得形如 principal://iam.googleapis.com/locations/global/workforcePools/POOL_ID/subject/SUBJECT 的聯合主體,IAP 即把對方視為一般身分進行 IAM 繫結。
模式 B:Identity Platform (External Identities)
對於允許 Google、Facebook、GitHub、OIDC、SAML、電話或密碼登入的消費者導向應用程式,請在 IAP 設定中啟用「External Identities」並以 Identity Platform(前身 Firebase Authentication)為後端。IAP 會把使用者導向 Identity Platform 託管的可自訂登入頁;成功後就會以聯合身分作為 email claim 鑄造標準 JWT assertion。這是讓非 Google 使用者能存取 IAP 保護應用程式的唯一方式,且無需給對方 Workspace 帳戶。
何時不該以 IAP 做 SSO
若你的應用程式已原生整合 Okta 或 Azure AD(例如一個 SaaS 產品),就不要再把 IAP 放在前面——那會做兩次身分驗證。IAP 最適合的情境是底層應用程式驗證機制薄弱或完全沒有驗證,而你希望在不改寫程式碼的前提下加上企業 SSO。
透過 IAP Connector 將 IAP 延伸至地端應用程式
常見誤解是 IAP 只適用於 Google Cloud 上的工作負載。IAP Connector 是一套參考架構(可從 github.com/GoogleCloudPlatform/iap-connector 以 Terraform 部署),在 GKE 上跑 Ambassador-based 反向代理,於 GCP 邊緣終止 IAP,並透過 Cloud Interconnect 或 Cloud VPN 把請求轉發到地端網頁伺服器。
架構
瀏覽器 → 公開 DNS → External Application Load Balancer(已啟用 IAP)→ GKE Ingress → Ambassador pod → Cloud VPN 通道 → 地端應用程式 10.0.0.5:443。地端應用程式看到的請求來源是 GKE pod 的 IP,並信任 Ambassador pod 原封轉發的 x-goog-iap-jwt-assertion 標頭來取得使用者身分。
為何能取代傳統 VPN
在 IAP Connector 出現前,要把地端 SharePoint 或 Confluence 暴露給遠端員工,意味著架設企業 VPN 終端、分發 SSL VPN 用戶端並管理憑證。IAP Connector 用一次 Google 登入取代全部:使用者在瀏覽器打開 confluence.corp.example.com、登入一次,IAP 即套用與雲原生應用程式相同的 Access Level(裝置態勢、地理位置)。這就是 BeyondCorp 模型在混合環境中的實際落地。
不要混淆 IAP Connector 與 Identity-Aware Proxy 本身。IAP 是 GCP 服務;IAP Connector 是一套使用 IAP 來前置地端應用程式的開源 GKE 部署樣板。考題有時會問「把 IAP 延伸到地端」——答案是在 GKE 上部署 Connector,而不是在 IAP 控制台切換某個開關。
記錄、監控與營運
IAP 會送兩條紀錄串到 Cloud Logging。cloudaudit.googleapis.com/data_access 紀錄每一次授權判定 (allow/deny),含主體電子郵件、來源 IP、資源路徑;你必須明確啟用 Data Access logs,因為 IAP 預設未開。cloudaudit.googleapis.com/activity 紀錄管理操作,例如啟用 IAP 或編輯 OAuth 用戶端。
實用紀錄查詢
找出所有被拒存取嘗試:resource.type="iap_web" AND protoPayload.authorizationInfo.granted=false。稽核過去 24 小時誰存取了特定後端:resource.type="iap_web" AND resource.labels.service_id="BACKEND_ID"。透過 log sink 把這些紀錄送進 BigQuery 做長期分析,或送進 Pub/Sub 給 SOC 觸發告警。
Cloud Monitoring 中的指標
iam.googleapis.com/iap/request_count 指標依 response_code (200、401、403) 分項統計請求量。403 暴增通常代表 Access Level 配置錯誤或工作階段 Cookie 過期。為 403 比率設定告警政策,可在數分鐘內捕捉政策回歸。
工作階段長度調整
IAP 發出的工作階段 Cookie 有效期等同 consent screen 的設定(Workspace 預設 3 小時、最高 24 小時)。對高安全性應用程式請在管理控制台 → 安全 → Google Cloud 工作階段控制中下調。Cookie 屬性為 HttpOnly、Secure,並 scope 至 .cloud.google.com 與你的自訂網域。
白話文解釋
類比 1:地下酒吧門口的保鑣
想像一間禁酒令時期的地下酒吧,藏在一扇沒有招牌的門後面。沒有大型霓虹燈(沒有公用 IP),電話簿也找不到地址(VM 沒有外部 IP)。要進去,你要在一個小窗口前敲門,由保鑣(IAP)檢查兩件事:你低聲說出的暗號(Google OAuth 登入)和你是否戴對帽子(Access Level:裝置態勢、來源 IP)。兩項都符合賓客名單(IAM 繫結 roles/iap.httpsResourceAccessor),保鑣就會把門滑開讓你直接走進吧台。沒有挖到建築物底下的地道(沒有 VPN),沒有會員卡(沒有 VPN 用戶端),只有保鑣在每一次敲門時做出判斷。
類比 2:飯店禮賓加上密封信封
當你請飯店禮賓送一個包裹到 1207 號房,禮賓會在防拆信封(x-goog-iap-jwt-assertion JWT)上寫「已驗證:1207 號房的陳先生」,並用飯店的火漆封印(ES256 簽章)封好。客房服務人員(你的後端)打開信封後,拿封印與飯店的主印章(gstatic.com 上的 JWK 公鑰)對照,確認到底是誰寄來的。如果有人從門縫塞進一張手寫紙條自稱是陳先生(繞過負載平衡器者偽造的 x-goog-authenticated-user-email 標頭),客房服務會直接忽略,因為沒有密封信封。這就是 audience 驗證為何重要——是別人無法偽造的封印。
類比 3:百貨公司氣動傳送管
舊式百貨公司在櫃台與收銀辦公室之間用氣動傳送管把現金與收據咻地送過去。IAP TCP 轉發就是雲端版本:與其讓你的 SSH 封包走公開網際網路(正門),不如把它們塞進密封的圓筒,從 Google 的私有氣動管直接射到 VM 的內部 IP。圓筒上標著你的 gcloud OAuth 權杖;名字若在核可名單上(roles/iap.tunnelResourceAccessor),管路會送達。若不在,圓筒會在入口被銷毀——而你連 VM 的位址都沒看到,更別說開放的 port。
考試技巧、常見陷阱與成本考量
陷阱:GCE/GKE 上沒有負載平衡器就用 IAP
針對 Compute Engine VM 的 IAP 需要在前方加上 HTTP(S) Load Balancer。沒有任何辦法可直接在單一 VM 的外部 IP 為網頁流量啟用 IAP。對 GKE 而言,這代表要使用 Ingress 資源並加上 kubernetes.io/ingress.class: gce annotation,而不是會產生 Network LB 的 type LoadBalancer Service。
陷阱:忘記為 IAP TCP 範圍開防火牆
TCP 轉發需要 35.235.240.0/20 範圍。若你的預設拒絕防火牆封鎖了它,gcloud compute ssh --tunnel-through-iap 會卡住並回 Connection failed: 4003 'failed to connect to backend'。允許這個範圍並不會把 VM 暴露到公開網際網路——只有通過驗證的 IAP 通道會從中發起。
陷阱:把 IAP 當成防火牆
IAP 不是封包過濾器。它執行的是應用層驗證;網路層過濾仍由防火牆規則與 Cloud Armor 處理。授權失敗的請求會在 TCP 握手與 TLS 終止之後才被以 HTTP 403 拒絕——不像被防火牆拒絕的 SYN 能省下網路頻寬。
成本考量
IAP 本身免費——不對每個請求收取代理費用。你只要付底層負載平衡器(轉發規則、資料處理)、OAuth Consent Screen 審核(免費),以及若使用進階裝置態勢條件所需的 BeyondCorp Enterprise 授權。把每月 500 美元的 VPN 集中器換成 IAP,通常能省下 VPN 授權費、集中器硬體/VM 與管理用戶端軟體的營運繁瑣。
常見問題
Q1:IAP 可以取代防火牆或 VPC 防火牆規則嗎?
不行。IAP 對 HTTPS 或 TCP 轉發的流量做應用層的驗證與授權。你仍需要 VPC 防火牆規則來 (a) 允許 130.211.0.0/22 與 35.191.0.0/16 的負載平衡器健康檢查,以及 (b) TCP 轉發時允許 35.235.240.0/20。將防火牆設成拒絕直接打到後端的入站流量,使用者就無法直接打 VM IP 來繞過 IAP。
Q2:IAP 可以給非 Google 使用者(消費者、合作夥伴)用嗎?
可以,透過 Identity Platform External Identities 整合。在 IAP 設定中啟用 External Identities、配置提供者 (Google、Facebook、GitHub、通用 OIDC、SAML、電子郵件/密碼、電話),IAP 就會把未驗證使用者導向 Identity Platform 託管的可自訂登入頁。產出的 JWT 仍使用 x-goog-iap-jwt-assertion,只是 email claim 現在會帶聯合身分。
Q3:x-goog-authenticated-user-email 與 x-goog-iap-jwt-assertion 差在哪?
x-goog-authenticated-user-email 是一個便利標頭,內含明文使用者電子郵件。它只在請求確實走過 IAP 時可信(後端若有公用 IP 你就無法保證這點)。x-goog-iap-jwt-assertion 是加密簽署的 JWT——驗證其 ES256 簽章與 aud claim 可證明此請求是針對你特定後端走過 IAP。任何授權判斷都要驗證 JWT;電子郵件標頭只當顯示資料用。
Q4:要怎麼用 IAP SSH 到一台沒有外部 IP 的 VM?
請確保 VM 所在專案啟用了 iap.googleapis.com、你的使用者在該 instance 上擁有 roles/iap.tunnelResourceAccessor,並且有一條防火牆規則允許來自 35.235.240.0/20 的 TCP:22。接著執行 gcloud compute ssh INSTANCE_NAME --tunnel-through-iap --zone=ZONE。gcloud CLI 會處理 OAuth 流程、開啟一條到 tunnel.cloudproxy.app:443 的 WebSocket,並透過 Google 網路將 SSH 位元組代理到 VM 的內部 IP。
Q5:IAP 能強制裝置態勢(例如「只允許已修補筆電」)嗎?
可以,透過 Access Context Manager Access Levels 搭配 Endpoint Verification (一個 Chrome 擴充功能或 Workspace 受管代理程式)。定義一個含 devicePolicy.osConstraints (最低 OS 版本)、devicePolicy.requireScreenlock 或 devicePolicy.requireCorpOwned (BeyondCorp Enterprise) 的 Access Level,再把它繫結到 IAP IAM 政策。不合規裝置上的使用者會看到 403 頁面,並說明失敗的條件。
Q6:IAP 適用於 regional load balancer 還是只能用 global?
IAP for HTTPS 需要 Global External Application Load Balancer。Regional External Application Load Balancer、Internal Application Load Balancer、Network Load Balancer 與 TCP Proxy Load Balancer 皆不支援網頁應用程式的 IAP。對僅限內部使用的工作負載,典型作法是「global LB + IAP + 限制公司 IP 範圍的 Access Level」——以強身分保證達到等同「僅內部」的結果。
Q7:要怎麼把 IAP 延伸到跑在地端的應用程式?
在 GKE 上部署 IAP Connector 參考架構:它跑 Ambassador-based 反向代理,在 GCP 邊緣終止 IAP,並透過 Cloud Interconnect 或 Cloud VPN 把通過驗證的請求轉發到你的地端網頁伺服器。地端應用程式收到的是原始 x-goog-iap-jwt-assertion 標頭,可用與雲原生應用程式完全相同的方式驗證。此樣板是混合環境落實 BeyondCorp 模型的標準作法,文件在 cloud.google.com/iap/docs/enabling-on-prem-howto。