本文說明如何使用 X.509 憑證,為 Workload Identity Federation 設定憑證型存取權。
憑證型存取權會使用相互傳輸層安全標準 (mTLS),在 TLS 握手期間驗證用戶端和伺服器。在這個程序中,mTLS 繫結會根據傳輸情境納入政策,並使用 TLS 工作階段中的用戶端憑證狀態,做出授權決策。
如果是 X.509 Workload Identity Federation,mTLS 繫結可確保整個驗證流程安全地繫結至信任的工作負載。系統會將驗證繫結至特定、受信任的端點,降低憑證遭竊的風險。
Workload Identity Federation 設定的憑證型存取權總覽
以下概略說明為 Workload Identity Federation 設定憑證型存取權的程序:
設定 X.509 憑證信任錨點的信任關係,建立 Workload Identity Federation。
建立以憑證為基礎的存取層級。
將存取層級新增至強制執行 mTLS 繫結的情境感知存取權政策。
事前準備
確認您符合下列必要條件:
最新版本 Google Cloud CLI。
如要更新至最新版本 gcloud CLI,請執行下列指令:
gcloud components update如需安裝 gcloud CLI,請參閱「安裝 gcloud CLI」。
使用 X.509 憑證信任錨點的 Workload Identity Federation 設定。
如要使用這項功能,請填寫許可清單申請表單,要求存取權。
建立憑證的存取層級
建立 mTLS 存取層級。mTLS 存取層級會在判斷資源存取權時驗證憑證。
控制台
在 Access Context Manager 中建立自訂存取層級,然後在「CEL expression」(CEL 運算式) 欄位中輸入下列運算式:
request.auth.matchesMtlsTokens(origin) == true。gcloud
如要建立自訂存取層級,請執行下列指令:
gcloud access-context-manager levels create ACCESS_LEVEL_NAME \ --title=TITLE \ --custom-level-spec=FILE \ --description=DESCRIPTION \ --policy=POLICY_NAME
更改下列內容:
ACCESS_LEVEL_NAME:存取層級的名稱。TITLE:存取層級的名稱。FILE:包含以下內容的 YAML 檔案:expression: "request.auth.matchesMtlsTokens(origin) == true"。DESCRIPTION:存取層級的說明。POLICY_NAME:存取權政策的名稱。
將您建立的存取層級匯出至環境變數,以便在後續步驟中使用:
export ACCESS_LEVEL_ID=ACCESS_LEVEL_ID
將
ACCESS_LEVEL_ID替換為存取層級名稱,例如accessPolicies/12345/accessLevels/acl_1。
為 workload identity pool 建立情境感知存取權繫結
請設定下列環境變數:
export ORG_ID=ORG_ID export CALLER_PROJECT_ID=CALLER_PROJECT_ID export FEDERATED_PRINCIPAL=FEDERATED_PRINCIPAL
更改下列內容:
ORG_ID:組織 ID。CALLER_PROJECT_ID:用於呼叫 API 的專案 ID。FEDERATED_PRINCIPAL:workload identity pool 中,遵守情境感知存取權政策的身分主體名稱。您可以使用下列其中一種方式:- 單一身分:
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE - 集區中的所有身分:
principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*
- 單一身分:
gcloud
gcloud alpha access-context-manager cloud-bindings create \ --organization=
ORG_ID\ --federated-principal=FEDERATED_PRINCIPAL\ --level=ACCESS_LEVEL_ID\ --dry-run-level=DRY_RUN_ACCESS_LEVEL_ID更改下列內容:
ACCESS_LEVEL_ID:存取層級名稱。DRY_RUN_ACCESS_LEVEL_ID:模擬測試存取層級名稱。建議您先啟用模擬測試政策繫結,瞭解對現有流量的潛在影響。
curl
建立含有情境感知存取權繫結的 JSON 檔案:
即使欄位重複,您也只能在要求中提供一個存取層級。您可以使用下列類型的聯合主體:
- 單一身分:
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT_ATTRIBUTE_VALUE - 集區中的所有身分:
principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*
cat <<EOF > request.json { "principal": { "federatedPrincipal": "${FEDERATED_PRINCIPAL:?}" }, "accessLevels": ["${ACCESS_LEVEL_ID:?}"] } EOF- 單一身分:
使用
curl傳送下列 HTTP 要求:curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X POST \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ -d @request.json \ "https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings"
使用 Google Cloud 用戶端程式庫進行授權
如要使用Google Cloud 用戶端程式庫授權 Workload Identity Federation 工作負載,請完成下列步驟:
建立為 Workload Identity Federation 驗證設定的應用程式預設憑證 (ADC) 檔案:
gcloud iam workload-identity-pools create-cred-config IDENTITY_POOL_ID \ --credential-cert-path WORKLOAD_CERTIFICATE_PATH \ --credential-cert-private-key-path WORKLOAD_KEY_PATH \ --output-file ADC_FILE_OUTPUT_PATH
更改下列內容:
IDENTITY_POOL_ID:workload identity pool 的 ID。WORKLOAD_CERTIFICATE_PATH:工作負載憑證檔案的路徑。WORKLOAD_KEY_PATH:工作負載私密金鑰檔案的路徑。ADC_FILE_OUTPUT_PATH:ADC 檔案的輸出路徑。
這個指令也會在 gcloud CLI 預設設定目錄中,產生憑證設定檔。憑證設定檔支援初始驗證,並為後續對 Google Cloud 資源的要求建立 mTLS 握手。
設定環境變數,指向 ADC 檔案,讓 Google 用戶端程式庫可找到憑證:
export GOOGLE_APPLICATION_CREDENTIALS=ADC_FILE_OUTPUT_PATH
如果您在產生 ADC 檔案時省略
--output-file引數,則可略過這個步驟。如果省略引數,gcloud CLI 會從 gcloud CLI 預設設定目錄建立及讀取 ADC 檔案。這項功能支援 Go、Python 和 Java 的用戶端程式庫。您必須設定環境變數,才能為 Python 和 Java 啟用 mTLS。
如要快速建立及測試 Google Cloud API 的 mTLS 存取權,可以使用下列程式碼範例:
Go
請參考下列範例建立 Go 檔案,例如
golang_test.go:package golang_test import ( "io" "log" "testing" "cloud.google.com/go/auth/credentials" "cloud.google.com/go/auth/httptransport" ) func TestGoExample(t *testing.T) { scopes := []string{ "https://www.googleapis.com/auth/pubsub", // Scope for Pub/Sub access // Add other scopes as needed } dopts := credentials.DetectOptions{ Scopes: scopes, } // Create httptransport.Options with the scopes opts := &httptransport.Options{ DetectOpts: &dopts, } hc, err := httptransport.NewClient(opts) if err != nil { t.Fatalf("NewHTTPClient: %v", err) } resp, err := hc.Get("https://pubsub.mtls.googleapis.com/v1/projects/PROJECT_ID/topics") if err != nil { t.Fatalf("Get: %v", err) } t.Logf("Status: %s", resp.Status) t.Cleanup(func() { resp.Body.Close() }) b, err := io.ReadAll(resp.Body) if err != nil { t.Fatal(err) } log.Println(string(b)) }將
PROJECT_ID替換為Google Cloud 專案 ID。如要在 Compute Engine VM 上執行測試,請使用下列指令:
go mod init example.com go mod tidy go test -v golang_test.go --count=1Python
請參考以下範例建立測試檔案,例如
python_test.py:import google.auth import google.auth.transport.requests import requests def test_python_example(): # Define the required scopes for your application scopes = [ "https://www.googleapis.com/auth/pubsub", # Scope for Pub/Sub access # Add other scopes as needed ] # Obtain Application Default Credentials (ADC) with the specified scopes credentials, _ = google.auth.default(scopes=scopes) # Create an authorized HTTP session using the ADC credentials authed_session = google.auth.transport.requests.AuthorizedSession(credentials) try: # Make a GET request to the Pub/Sub API endpoint response = authed_session.get( "https://pubsub.mtls.googleapis.com/v1/projects/PROJECT_ID/topics" ) # Check if the request was successful response.raise_for_status() # Raise an exception for error statuses # Log the response status and content print(f"Status: {response.status_code}") print(response.text) except requests.exceptions.RequestException as e: print(f"Error making the request: {e}") if __name__ == "__main__": test_python_example()將
PROJECT_ID替換為Google Cloud 專案 ID。如要在 Compute Engine VM 上執行測試,請完成下列步驟:
- 設定 Python 虛擬環境。
安裝必要的程式庫:
pip install google-auth google-auth-httplib2 requests執行測試:
python3 python_test.py
使用一般 HTTP 要求進行授權
如要使用純 HTTP 要求授權 Workload Identity Federation 工作負載,請完成下列步驟:
透過標準 mTLS 握手,從 Google Cloud Security Token Service 取得憑證繫結存取權杖。
使用從 Security Token Service 取得的存取權杖呼叫 Google Cloud 服務。這個範例會查詢 Cloud Storage:
curl --key WORKLOAD_KEY_PATH --cert WORKLOAD_CERTIFICATE_PATH \ -X GET "https://storage.mtls.googleapis.com/RESOURCE_PATH" \ -H "Authorization: Bearer $ACCESS_TOKEN"
mTLS 繫結會強制使用 mTLS。執行下列指令,確認非 mTLS 連線失敗,並顯示未授權錯誤:
curl -X GET "https://storage.googleapis.com/RESOURCE_PATH" \ -H "Authorization: Bearer $ACCESS_TOKEN"
列出政策繫結
如要列出 Workload Identity Federation 的政策繫結,請執行下列指令:
gcloud
下列指令會列出特定組織中的特定繫結,並篩選出適用於聯合主體的繫結:
gcloud alpha access-context-manager cloud-bindings list \
--organization=ORG_ID \
--filter='principal:federatedPrincipal'
curl
curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings?filter=principal%3Afederated_principal"
更新政策繫結
如要更新政策繫結,請完成下列步驟:
gcloud
gcloud alpha access-context-manager cloud-bindings update \ --binding=BINDING_ID\ --organization=ORG_ID\ --level=NEW_ACCESS_LEVEL_ID
curl
將新的存取層級新增至 request.json 檔案,然後執行下列指令:
curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X PATCH \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings/${BINDING_ID:?}?updateMask=access_levels"
刪除政策繫結
如要刪除政策繫結,請執行下列指令:
gcloud
gcloud alpha access-context-manager cloud-bindings delete \ --binding=BINDING_ID\ --organization=ORG_ID
curl
curl -H "X-Goog-User-Project: ${CALLER_PROJECT_ID:?}" -X DELETE \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://accesscontextmanager.googleapis.com/v1alpha/organizations/${ORG_ID:?}/gcpUserAccessBindings/${BINDING_ID:?}"