服務之間的驗證
除了驗證使用者要求,您可能也想驗證向 API 提出要求的服務 (非人類使用者)。本頁面說明如何使用服務帳戶,為人員或服務提供驗證。
總覽
為了識別傳送要求至您 API 的服務,需要使用服務帳戶。呼叫服務會使用服務帳戶的私密金鑰來簽署安全的 JSON Web Token (JWT),並將要求中的已簽署 JWT 傳送給您的 API。
在 API 和呼叫服務內進行服務帳戶驗證:
- 建立呼叫服務要使用的服務帳戶與金鑰。
- 在 API Gateway 服務的 API 設定中新增驗證支援。
將程式碼新增到呼叫服務,如此就會:
- 建立 JWT 並以服務帳戶私密金鑰簽署。
- 在要求中將已簽署的 JWT 傳送至 API。
API Gateway 會先驗證 JWT 內的憑證附加資訊是否符合 API 設定,再將要求轉送至您的 API。API Gateway 不會檢查該服務帳戶已經獲准的 Cloud Identity 權限。
必要條件
本頁假設您已具備以下條件:
使用金鑰建立服務帳戶
您會需要一個服務帳戶,這個服務帳戶需擁有呼叫服務用來簽署 JWT 的私密金鑰檔案。如果您有多個服務會向您的 API 發送要求,則可建立一個服務帳戶來代表所有的呼叫服務。如果您需要區別不同服務 (例如各服務具有的權限可能各不相同),就可以為每個呼叫服務建立服務帳戶和金鑰。
本節會示範如何使用 Google Cloud 控制台與 gcloud
指令列工具來建立服務帳戶與私密金鑰檔案,並將服務帳戶憑證建立者角色指派給服務帳戶。如要瞭解如何使用 API 進行這項工作,請參閱「建立和管理服務帳戶」。
如何使用金鑰建立服務帳戶:
Google Cloud 控制台
建立服務帳戶:
前往 Google Cloud 控制台的「建立服務帳戶」頁面。
選取專案。
在「Service account name」(服務帳戶名稱) 欄位中輸入名稱。Google Cloud 控制台會根據這個名稱填入「服務帳戶 ID」欄位。
選用:在「服務帳戶說明」欄位中輸入說明。
點選「建立」。
按一下「選取角色」欄位。
在「所有角色」下方,選取「服務帳戶」 >「服務帳戶憑證建立者」。
按一下「繼續」。
按一下「Done」(完成),即完成建立服務帳戶。
請勿關閉瀏覽器視窗。您會在下一個程序中使用此項目。
建立服務帳戶金鑰:
- 在 Google Cloud 控制台中,按一下您建立的服務帳戶電子郵件地址。
- 點選「金鑰」。
- 依序點選「新增金鑰」和「建立新的金鑰」。
- 按一下「建立」,系統會將 JSON 金鑰檔案下載至您的電腦。
- 按一下 [關閉]。
gcloud
您可以使用本機電腦上的 Google Cloud CLI 或在 Cloud Shell 內執行下列指令。
設定
gcloud
的預設帳戶。如果您有多個帳戶,請確認所選擇的帳戶位於您要使用的 Google Cloud 專案中。gcloud auth login
顯示 Google Cloud 專案的專案 ID。
gcloud projects list
設定預設專案。將
PROJECT_ID
替換為您要使用的 Google Cloud 專案 ID。gcloud config set project PROJECT_ID
建立服務帳戶。將
SA_NAME
和SA_DISPLAY_NAME
替換為您要使用的名稱和顯示名稱。gcloud iam service-accounts create SA_NAME \ --display-name "SA_DISPLAY_NAME"
顯示剛剛建立的服務帳戶的電子郵件地址。
gcloud iam service-accounts list
新增服務帳戶憑證建立者角色。將
SA_EMAIL_ADDRESS
替換成服務帳戶的電子郵件地址。gcloud projects add-iam-policy-binding PROJECT_ID \ --member serviceAccount:SA_EMAIL_ADDRESS \ --role roles/iam.serviceAccountTokenCreator
在目前的工作目錄中建立服務帳戶金鑰檔案。將
FILE_NAME
替換為您要用於金鑰檔案的名稱。根據預設,gcloud
指令會建立一個 JSON 檔案。gcloud iam service-accounts keys create FILE_NAME.json \ --iam-account SA_EMAIL_ADDRESS
如要進一步瞭解上述指令,請參閱 gcloud
參考資料。
如需私密金鑰保護措施的相關資訊,請參閱管理憑證的最佳做法。
設定 API 以支援驗證
為閘道建立 API 設定時,您會指定閘道用來與其他服務互動的服務帳戶。如要為呼叫閘道的服務啟用服務帳戶驗證,請修改 API 設定中的安全性需求物件和安全性定義物件。按照下列步驟操作,API Gateway 就能驗證呼叫服務所用已簽署 JWT 中的聲明。
在 API 設定中將服務帳戶新增為發行者。
securityDefinitions: DEFINITION_NAME: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "SA_EMAIL_ADDRESS" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/SA_EMAIL_ADDRESS"
- 將
DEFINITION_NAME
替換成可用來識別此安全性定義的字串。建議將其替換成服務帳戶名稱或是能辨別呼叫服務的名稱。 - 將
SA_EMAIL_ADDRESS
替換成服務帳戶的電子郵件地址。 - 您可以在 API 設定中定義多項安全定義,但是每項定義必須要有不同的
x-google-issuer
。如果您為每個呼叫服務建立了個別的服務帳戶,則可以再為每個服務帳戶建立安全性定義,例如:
securityDefinitions: service-1: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-1@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-1@example-project-12345.iam.gserviceaccount.com" service-2: authorizationUrl: "" flow: "implicit" type: "oauth2" x-google-issuer: "service-2@example-project-12345.iam.gserviceaccount.com" x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/service-2@example-project-12345.iam.gserviceaccount.com"
- 將
也可以將
x-google-audiences
新增至securityDefinitions
區段。如果您沒有新增x-google-audiences
,API Gateway 會要求 JWT 中的"aud"
(目標對象) 憑證附加資訊格式為https://SERVICE_NAME
,其中 SERVICE_NAME 是您的 API Gateway 服務名稱 (您已在 OpenAPI 文件的host
欄位中設定的名稱)。在檔案頂層 (非縮排或巢狀結構) 新增一個
security
區段,並套用至整個 API,或是在方法層中套用至特定方法。如果您在 API 層級和方法層級使用security
區段,方法層級的設定就會覆寫 API 層級的設定。security: - DEFINITION_NAME: []
- 將
DEFINITION_NAME
替換成您在securityDefinitions
區段中使用的名稱。 如果您在
securityDefinitions
區段中有多個定義,請將其新增至security
區段,例如:security: - service-1: [] - service-2: []
- 將
部署更新後的 API 設定。
在 API Gateway 向您的 API 轉送要求之前,API Gateway 會驗證以下項目:
- 使用公開金鑰的 JWT 簽署,位於 API 設定中
x-google-jwks_uri
欄位指定的 URI。 - JWT 中的
"iss"
(發行者) 憑證附加資訊與x-google-issuer
欄位指定的值是否相符。 - JWT 中的
"aud"
(目標對象) 憑證附加資訊是否含有您的 API Gateway 服務名稱,或是否與x-google-audiences
欄位指定的其中一個值相符。 - 使用
"exp"
(到期時間) 憑證附加資訊,確認憑證並未過期。
如要進一步瞭解 x-google-issuer
、x-google-jwks_uri
和 x-google-audiences
,請參閱 OpenAPI 擴充功能。
向 API Gateway API 發出經過驗證的要求
如要發出經過驗證的要求,呼叫服務會傳送您在 API 設定中指定的服務帳戶簽署的 JWT。呼叫服務必須:
- 建立一個 JWT,並以服務帳戶私密金鑰簽署。
- 在要求中將簽署的 JWT 傳送至 API。
以下範例程式碼示範了部分語言的這項程序。如要以其他語言提出已驗證的要求,請參閱 jwt.io,瞭解支援的程式庫清單。
- 在呼叫服務中,新增以下函式,並將以下參數傳送給函式:
Java saKeyfile
:服務帳戶私密金鑰檔案的完整路徑。saEmail
:服務帳戶的電子郵件地址。-
audience
:如果已在 API 設定中新增了x-google-audiences
欄位,請將audience
設定為您指定給x-google-audiences
的其中一個值。或是將audience
設定為https://SERVICE_NAME
,其中SERVICE_NAME
是您的 API Gateway 服務名稱。 expiryLength
:JWT 的到期時間,以秒為單位。
Python sa_keyfile
:服務帳戶私密金鑰檔案的完整路徑。sa_email
:服務帳戶的電子郵件地址。-
audience
:如果已在 API 設定中新增了x-google-audiences
欄位,請將audience
設定為您指定給x-google-audiences
的其中一個值。或是將audience
設定為https://SERVICE_NAME
,其中SERVICE_NAME
是您的 API Gateway 服務名稱。 expiry_length
:JWT 的到期時間,以秒為單位。
Go saKeyfile
:服務帳戶私密金鑰檔案的完整路徑。saEmail
:服務帳戶的電子郵件地址。-
audience
:如果已在 API 設定中新增了x-google-audiences
欄位,請將audience
設定為您指定給x-google-audiences
的其中一個值。或是將audience
設定為https://SERVICE_NAME
,其中SERVICE_NAME
是您的 API Gateway 服務名稱。 expiryLength
:JWT 的到期時間,以秒為單位。
此函式會建立一個 JWT,並使用私密金鑰檔案來簽署 JWT,然後將已簽署的 JWT 傳回。
Java Python Go - 在呼叫服務中,新增下列函式,以在要求中使用
Authorization: Bearer
標頭傳送已簽署的 JWT 給 API:Java Python Go
當您使用 JWT 傳送一項要求時,基於安全考量,建議您將驗證憑證放入 Authorization: Bearer
標頭之中。例如:
curl --request POST \ --header "Authorization: Bearer ${TOKEN}" \ "${GATEWAY_URL}/echo"
其中 GATEWAY_URL
和 TOKEN
分別是內含您已部署閘道網址和驗證憑證的環境變數。
在 API 中接收驗證結果
API Gateway 通常會轉送收到的所有標頭。不過,如果 API 設定中的 x-google-backend
指定後端位址,系統就會覆寫原始的 Authorization
標頭。
API Gateway 會將驗證結果傳送至後端 API 的 X-Apigateway-Api-Userinfo
。建議使用這個標頭,而非原始的 Authorization
標頭。此標頭是由 base64url
所編碼,並且包含 JWT 酬載。