在 Python 2 執行階段中執行的應用程式向其他 App Engine 應用程式傳送要求時,可以使用 App Engine App Identity API 宣告自己的身分。接收要求的應用程式可以使用這個身分,判斷是否應處理要求。
如果 Python 3 應用程式在傳送要求至其他 App Engine 應用程式時,需要宣告自己的身分,您可以使用由 Google OAuth 2.0 API 核發及解碼的 OpenID Connect (OIDC) ID 權杖。
以下簡要說明如何使用 OIDC ID 權杖來斷言及驗證身分:
- 名為「App A」的 App Engine 應用程式會從 Google Cloud 執行階段環境擷取 ID 權杖。
- 應用程式 A 會在將要求傳送至 App B (另一個 App Engine 應用程式) 之前,將這個符記新增至要求標頭。
- App B 會使用 Google 的 OAuth 2.0 API 驗證權杖酬載。經解碼的酬載包含已驗證的 App A 身分,其形式為 App A 預設服務帳戶的電子郵件地址。
- App B 會將酬載中的身分與可回應的身分清單進行比較。如果要求來自已核准的應用程式,則應用程式 B 會處理要求並回應。
本指南說明如何更新 App Engine 應用程式,以便使用 OpenID Connect (OIDC) ID 權杖來宣告身分,並更新其他 App Engine 應用程式,以便在處理要求前使用 ID 權杖驗證身分。
App Identity 和 OIDC API 之間的主要差異
Python 2 執行階段中的應用程式不需要明確宣告身分。當應用程式使用
httplib
、urllib
或urllib2
Python 程式庫,或 App Engine 網址擷取服務來傳送外連要求時,執行階段會使用 App Engine 網址擷取服務提出要求。如果要求傳送至appspot.com
網域,網址擷取服務會在要求中加入X-Appengine-Inbound-Appid
標頭,自動宣告要求應用程式的身分。該標頭包含應用程式 ID (也稱為專案 ID)。Python 3 執行階段中的應用程式確實需要明確斷言身分,方法是從 Google Cloud 執行階段環境擷取 OIDC ID 權杖,然後將其新增至要求標頭。您必須更新所有傳送要求至其他 App Engine 應用程式的程式碼,讓要求包含 OIDC ID 權杖。
要求中的
X-Appengine-Inbound-Appid
標頭包含傳送要求的應用程式專案 ID。Google 的 OIDC ID 權杖酬載不會直接識別應用程式本身的專案 ID。相反地,權杖會提供服務帳戶的電子郵件地址,藉此識別應用程式執行的服務帳戶。您需要新增一些程式碼,才能從權杖酬載中擷取使用者名稱。
如果該服務帳戶是專案的應用程式層級預設 App Engine 服務帳戶,您可以在服務帳戶的電子郵件地址中找到專案 ID。地址中的使用者名稱部分與專案 ID 相同。在這種情況下,接收應用程式程式碼可以在允許要求的專案 ID 清單中查詢這項資訊。
不過,如果要求應用程式使用使用者管理的服務帳戶,而非預設的 App Engine 服務帳戶,則接收應用程式只能驗證該服務帳戶的身份,而不會定義要求應用程式的專案 ID。在這種情況下,接收應用程式必須維護允許的服務帳戶電子郵件地址清單,而非允許的專案 ID 清單。
URL Fetch API 呼叫的配額與 Google 授予憑證的 OAuth 2.0 API 配額不同。您可以在 Google Cloud 主控台的 OAuth 同意畫面中,查看每天可授予的符記數量上限。無論是 URL Fetch、App Identity API 還是 Google 的 OAuth 2.0 API,都不會產生帳單費用。
轉換程序總覽
如要將 Python 應用程式遷移至使用 OIDC API 來斷言及驗證身分,請按照下列步驟操作:
在需要向其他 App Engine 應用程式傳送要求時,應用程式必須宣告身分:
請等到應用程式在 Python 3 環境中執行,再遷移至 ID 權杖。
雖然可以在 Python 2 執行階段使用 ID 權杖,但 Python 2 中的步驟相當複雜,且只在您更新應用程式以便在 Python 3 執行階段中執行時才需要使用。
應用程式在 Python 3 中執行後,請更新應用程式,以便要求 ID 權杖,並將權杖新增至要求標頭。
在需要先驗證身分才能處理要求的應用程式中:
首先,請升級 Python 2 應用程式,同時支援 ID 權杖和 App Identity API 身分。這樣一來,應用程式就能驗證並處理來自使用 App Identity API 的 Python 2 應用程式,或使用 ID 權杖的 Python 3 應用程式的要求。
升級後的 Python 2 應用程式穩定後,請將其遷移至 Python 3 執行階段。請繼續支援 ID 權杖和 App Identity API 身分,直到您確定應用程式不再需要支援舊版應用程式的要求為止。
當您不再需要處理舊版 App Engine 應用程式的要求時,請移除用於驗證 App Identity API 身分的程式碼。
測試應用程式後,請先部署處理要求的應用程式。接著,部署更新後的 Python 3 應用程式,該應用程式會使用 ID 權杖來斷言身分。
聲明身分
等待應用程式在 Python 3 環境中執行,然後按照下列步驟升級應用程式,以便使用 ID 權杖斷言身分:
為 Python 3 應用程式安裝 google-auth
用戶端程式庫
如要讓 google-auth
用戶端程式庫可供 Python3 應用程式使用,請在 app.yaml
檔案所在的資料夾中建立 requirements.txt
檔案,然後加入下列行:
google-auth
當您部署應用程式時,App Engine 會下載 requirements.txt
檔案中定義的所有依附元件。
針對本機開發作業,建議您在 venv 等虛擬環境中安裝依附元件。
新增程式碼來斷言身分
搜尋程式碼,找出所有向其他 App Engine 應用程式傳送要求的例項。請先更新這些例項,以便在傳送要求前執行下列操作:
新增下列匯入項目:
from google.auth.transport import requests as reqs from google.oauth2 import id_token
請使用
google.oauth2.id_token.fetch_id_token(request, audience)
擷取 ID 權杖。在方法呼叫中加入下列參數:request
:傳遞您準備傳送的要求物件。audience
:傳遞您要傳送要求的應用程式網址。這麼做可將符記繫結至要求,並防止其他應用程式使用符記。為求清楚明確,即使您為應用程式使用自訂網域,我們仍建議您傳遞 App Engine 為接收要求的特定服務建立的
appspot.com
網址。
請在要求物件中設定下列標頭:
'Authorization': 'ID {}'.format(token)
例如:
測試宣告身分功能的更新
如要在本機上執行應用程式,並測試應用程式是否能成功傳送 ID 權杖,請按照下列步驟操作:
請按照下列步驟操作,在本機環境中提供預設 App Engine 服務帳戶的憑證 (Google OAuth API 需要這些憑證才能產生 ID 權杖):
輸入下列
gcloud
指令,即可擷取專案預設 App Engine 帳戶的服務帳戶金鑰:gcloud iam service-accounts keys create ~/key.json --iam-account project-ID@appspot.gserviceaccount.com
將 project-ID 替換為 Google Cloud 專案的 ID。
服務帳戶金鑰檔案現在會下載到您的電腦。您可以任意移動及重新命名此檔案。請務必妥善保存此檔案,因為此檔案可當做服務帳戶進行驗證。如果您遺失檔案,或檔案遭到未經授權的使用者存取,請刪除服務帳戶金鑰,並建立新的金鑰。
輸入下列指令:
<code>export GOOGLE_APPLICATION_CREDENTIALS=<var>service-account-key</var></code>
將 service-account-key 替換為含有您下載的服務帳戶金鑰的檔案絕對路徑。
在匯出
GOOGLE_APPLICATION_CREDENTIALS
環境變數的相同 Shell 中,啟動 Python 應用程式。從應用程式傳送要求,並確認要求成功。如果您尚未擁有可接收要求並使用 ID 權杖驗證身分的應用程式,請按照下列步驟操作:
- 下載「incoming」應用程式範例。
在範例的
main.py
檔案中,將 Google Cloud 專案的 ID 新增至allowed_app_ids
。例如:allowed_app_ids = [ '<APP_ID_1>', '<APP_ID_2>', 'my-project-id' ]
在 Python 2 本機開發伺服器中執行更新後的範例。
驗證及處理要求
如要將 Python 2 應用程式升級為在處理要求前使用 ID 權杖或 App Identity API 身分,請按照下列步驟操作:
安裝 google-auth 用戶端程式庫。
更新程式碼,執行下列操作:
如果要求包含
X-Appengine-Inbound-Appid
標頭,請使用該標頭驗證身分。在 Python 2 等舊版執行階段中執行的應用程式會包含這個標頭。如果要求不包含
X-Appengine-Inbound-Appid
標頭,請檢查 OIDC ID 權杖。如果有符記,請驗證符記酬載並檢查傳送者的身分。
測試更新內容。
為 Python 2 應用程式安裝 Google 驗證用戶端程式庫
如要讓 google-auth
用戶端程式庫可供 Python 2 應用程式使用,請按照下列步驟操作:
在
app.yaml
檔案所在的資料夾中建立requirements.txt
檔案,然後加入以下行:google-auth==1.19.2
建議您使用 1.19.2 版的 Cloud Logging 用戶端程式庫,因為它支援 Python 2.7 應用程式。
在應用程式的
app.yaml
檔案中,如果尚未指定 SSL 程式庫,請在libraries
區段中指定 SSL 程式庫:libraries: - name: ssl version: latest
建立目錄以儲存第三方程式庫,例如
lib/
。然後使用pip install
將程式庫安裝到目錄中。例如:pip install -t lib -r requirements.txt
在
app.yaml
檔案所在的資料夾中建立appengine_config.py
檔案。請將以下內容新增到appengine_config.py
檔案中:# appengine_config.py import pkg_resources from google.appengine.ext import vendor # Set path to your libraries folder. path = 'lib' # Add libraries installed in the path folder. vendor.add(path) # Add libraries to pkg_resources working set to find the distribution. pkg_resources.working_set.add_entry(path)
上述範例中的
appengine_config.py
檔案假設lib
資料夾位於目前的工作目錄。如果您無法保證lib
一律會位於目前的工作目錄中,請指定lib
資料夾的完整路徑。例如:import os path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'lib')
如果是本機開發,建議您在虛擬環境中安裝依附元件,例如 Python 2 的 virtualenv。
更新驗證要求的程式碼
搜尋程式碼,找出所有取得 X-Appengine-Inbound-Appid
標頭值的例項。更新這些例項,以便執行下列操作:
新增下列匯入項目:
from google.auth.transport import requests as reqs from google.oauth2 import id_token
如果傳入的要求不含
X-Appengine-Inbound-Appid
標頭,請尋找Authorization
標頭並擷取其值。標頭值的格式為「ID: token」。
使用
google.oauth2.id_token.verify_oauth2_token(token, request, audience)
驗證及擷取已解碼的權杖酬載。請在方法呼叫中加入下列參數:token
:傳遞從傳入要求中擷取的權杖。request
:傳遞新的google.auth.transport.Request
物件。audience
:傳遞目前應用程式 (傳送驗證要求的應用程式) 的網址。Google 授權伺服器會將這個網址與權杖最初產生時提供的網址進行比較。如果網址不相符,系統就不會驗證權杖,授權伺服器也會傳回錯誤。
verify_oauth2_token
方法會傳回已解碼的權杖酬載,其中包含多個名稱/值組合,包括產生權杖的應用程式預設服務帳戶的電子郵件地址。從權杖酬載中的電子郵件地址中擷取使用者名稱。
使用者名稱與提出要求的應用程式專案 ID 相同。這個值與先前在
X-Appengine-Inbound-Appid
標頭中傳回的值相同。如果使用者名稱/專案 ID 在允許的專案 ID 清單中,請處理要求。
例如:
測試身分驗證更新
如要測試應用程式是否能使用 ID 權杖或 X-Appengine-Inbound-Appid
標頭來驗證要求,請在 Python 2 本機開發伺服器中執行應用程式,並從使用 App Identity API 的 Python 2 應用程式和傳送 ID 權杖的 Python 3 應用程式傳送要求。
如果您尚未更新應用程式以傳送 ID 權杖:
如測試應用程式斷言更新一文所述,將服務帳戶憑證新增至本地環境。
使用標準 Python 3 指令啟動 Python 3 範例應用程式。
從範例應用程式傳送要求,並確認要求成功。
部署應用程式
準備好部署應用程式後,請執行下列操作:
如果應用程式執行時沒有發生錯誤,請使用流量分配功能,逐步增加更新後應用程式的流量。請密切監控應用程式是否有任何問題,再將更多流量導向更新版應用程式。
使用其他服務帳戶宣告身分
要求 ID 權杖時,要求預設會使用 App Engine 預設服務帳戶的身分。驗證權杖時,權杖酬載會包含預設服務帳戶的電子郵件地址,該電子郵件地址會對應至應用程式的專案 ID。
根據預設,App Engine 預設服務帳戶的權限非常高。這個帳戶可以查看及編輯整個Google Cloud 專案,因此在大多數情況下,如果應用程式需要透過 Cloud 服務進行驗證,就不適合使用這個帳戶。
不過,在宣告應用程式身分時,使用預設服務帳戶是安全的,因為您只會使用 ID 權杖來驗證傳送要求的應用程式身分。這個程序不會考量或需要服務帳戶的實際權限。
如果您仍想使用其他服務帳戶提出 ID 權杖要求,請執行下列操作:
將名為
GOOGLE_APPLICATION_CREDENTIALS
的環境變數設為包含服務帳戶憑證的 JSON 檔案路徑。請參閱安全儲存這些憑證的建議。請使用
google.oauth2.id_token.fetch_id_token(request, audience)
擷取 ID 權杖。驗證此權杖時,權杖酬載會包含新服務帳戶的電子郵件地址。