應用程式傳送機密資訊至虛擬機器 (VM) 執行個體前,可透過 Google 簽署的執行個體識別憑證驗證執行個體的識別資訊。每個執行個體都有專屬的 JSON Web Token (JWT),提供包含執行個體的詳細資料以及 Google 的 RS256 簽名。 應用程式可藉由 Google 的公用 Oauth2 憑證驗證簽章,確認已連線的執行個體識別資訊。
只有在執行個體透過執行個體中繼資料提出要求時,Compute Engine 才會產生已簽署的執行個體憑證。執行個體只能存取自己的專屬憑證,無法存取其他執行個體的憑證。
您可能會想要在下列情境中驗證執行個體的識別資訊:
- 當您初次啟動執行個體時,您的應用程式可能需要先確保連線的執行個體具備有效的識別資訊,然後才可傳送機密資訊至執行個體。
- 當政策要求您將憑證儲存至 Compute Engine 環境以外的位置,而您需要將這些憑證定期傳送至執行個體以供暫時使用時,您的應用程式會在每次需要傳送憑證時確認執行個體的識別資訊。
Google 的執行個體驗證方法具有以下優勢:
- Compute Engine 會在執行個體每次提出要求時產生專屬憑證,且每個憑證都會在一小時內過期。您可將應用程式設為僅接受一次執行個體的識別憑證,藉此降低未經授權的系統重複使用憑證的風險。
- 經過簽署的中繼資料憑證採用 RFC 7519 開放業界標準與 OpenID Connect 1.0 識別層級,如此現有的工具與程式庫才能順暢地使用識別憑證。
事前準備
- 瞭解如何擷取執行個體中繼資料值。
- 認識 JSON Web Token 概念,如此才能在應用程式中加以運用。
- 瞭解如何在執行個體上建立並啟用服務帳戶。執行個體必須擁有相關聯的服務帳戶,如此才可擷取其識別憑證。服務帳戶無需任何身分與存取權管理權限,就能擷取這些識別憑證。
-
如果尚未設定,請先設定驗證機制。「驗證」是指驗證身分,以便存取 Google Cloud 服務和 API 的程序。如要從本機開發環境執行程式碼或範例,請選取下列任一選項,以便對 Compute Engine 進行驗證:
如要在本機開發環境中使用本頁面上的 Python 範例,請先安裝並初始化 gcloud CLI,然後使用您的使用者憑證設定應用程式預設憑證。
-
Install the Google Cloud CLI.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
If you're using a local shell, then create local authentication credentials for your user account:
gcloud auth application-default login
You don't need to do this if you're using Cloud Shell.
If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.
詳情請參閱 Set up authentication for a local development environment。
驗證執行個體的識別資訊
在某些情況下,您的應用程式必須先驗證在 Compute Engine 上執行之執行個體的識別資訊,才能傳送機密資料到執行個體。某種常見的案例情況是,有個在 Compute Engine 以外的位置執行的系統,稱為「Host1」,另外有個 Compute Engine 執行個體,稱為「VM1」。VM1 可透過下列程序連線至 Host1,並驗證這個執行個體的識別資訊:
VM1 會透過您選擇的安全連線通訊協定 (例如 HTTPS),建立與 Host1 的安全連線。
VM1 會向中繼資料伺服器要求專屬的識別憑證,並指定憑證的目標對象。在這個範例中,Host1 的目標對象值為 URI。向中繼資料伺服器提出的要求包含目標對象的 URI,如此 Host1 之後才可在憑證驗證步驟期間檢查這個值。
Google 會產生 JWT 格式的新專屬執行個體識別憑證並提供給 VM1。憑證酬載包含執行個體的多項相關詳細資料,另外也包含目標對象 URI。如需完整的憑證內容說明,請參閱憑證內容。
VM1 會透過現有的安全連線傳送識別憑證至 Host1。
Host1 會將識別憑證解碼,以取得憑證標頭與酬載值。
Host1 會檢查目標對象值並依據公用 Google 憑證驗證憑證簽名,以確認憑證由 Google 簽署。
如為有效憑證,Host1 會繼續傳送,並在完成後關閉連線。對於後續與 VM1 的任何連線,Host1 與任何其他系統應要求新憑證。
取得執行個體識別憑證
當虛擬機器執行個體收到提供相關識別憑證的要求時,執行個體會透過取得執行個體中繼資料的一般程序,向中繼資料伺服器要求憑證。 舉例來說,您可能會採用下列其中一種方法:
cURL
建立 curl
要求並在 audience
參數中加入值。
您也可以加入參數 format
,以指定是否要在酬載中加入專案和執行個體詳細資料。如果使用格式 full
,則可以加入 licenses
參數,以指定是否要在酬載中包含授權碼。
curl -H "Metadata-Flavor: Google" \ 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=AUDIENCE&format=FORMAT&licenses=LICENSES'
更改下列內容:
AUDIENCE
:執行個體和驗證執行個體識別資訊的系統雙方共同協議的專屬 URI。舉例來說,目標對象可以是兩個系統之間的連線網址。FORMAT
:選用參數,指定專案和執行個體詳細資料是否包含在酬載中。指定full
以在酬載中引入或standard
省略這項資訊。預設值為standard
。詳情請參閱「身分權杖格式」。LICENSES
:選用參數,用於指定是否要在酬載中包含與此執行個體相關聯的映像檔的授權碼。指定TRUE
可在酬載中包含這項資訊,指定FALSE
則可從酬載中省略這項資訊。預設值為FALSE
。除非format
是為full
,否則將沒有效果。
中繼資料伺服器會透過使用 RS256 演算法簽署的 JSON Web Token 回應這項要求。 憑證的酬載中會包含 Google 簽名及其他資訊。您可以將這個憑證傳送至其他系統與應用程式,讓這些系統與應用程式驗證憑證,並確認執行個體的識別資訊。
Python
您可以使用 Python requests
函式庫中的方法,從執行個體向中繼資料伺服器送出一個簡單的請求。以下範例會要求並列印執行個體識別憑證,該憑證專屬於提出這項要求的執行個體。
中繼資料伺服器會透過使用 RS256 演算法簽署的 JSON Web Token 回應這項要求。 憑證的酬載中會包含 Google 簽名及其他資訊。您可以將這個憑證傳送至其他系統與應用程式,讓這些系統與應用程式驗證憑證,並確認執行個體的識別資訊。
驗證憑證
應用程式收到來自 Compute Engine 執行個體的識別憑證後,就會透過下列程序驗證憑證。
接收來自虛擬機器執行個體的憑證,使用 RS256 JWT 解碼器將其解碼後,讀取標頭的內容以取得
kid
資料值。依據公用 Google 憑證檢查憑證,確認憑證經過簽署。 每個公開憑證中都有一個
kid
值,與符記標頭中的kid
值相對應。如為有效憑證,請比較酬載內容與預期值。如果符記酬載含有關於執行個體及專案的詳細資訊,則您的應用程式可以檢查
instance_id
、project_id
以及zone
資料值。這些是全域唯一的數值組合,可確認應用程式正在跟目標專案中的正確執行個體通訊。
您可以自行選擇任何工具將憑證解碼並驗證憑證,但一般的做法是使用所選語言的程式庫。舉例來說,您可以使用 Google OAuth 2.0 Python 函式庫中的verify_token
方法。verify_token
方法會將kid
資料值與適當的憑證進行比對,驗證簽章,檢查目標裝置發出的聲明,並回傳符記酬載內容。
在應用程式驗證憑證及相關內容後,就可透過安全連線繼續與這個執行個體連線,並在完成後關閉連線。如要再次連線,請向執行個體要求新的憑證,然後重新驗證執行個體的識別資訊。
憑證內容
執行個體識別憑證可分為三大部分:
標頭
標頭中含有kid
資料值,以識別哪些公開 Oauth2 憑證必需用來驗證簽章,標頭中包含alg
值,以確認由 RS256 演算法所產生的簽章。
{
"alg": "RS256",
"kid": "511a3e85d2452aee960ed557e2666a8c5cedd8ae",
}
酬載
酬載包含aud
目標對象的聲明。如果執行個體在要求憑證時指定了format=full
,則所發出請求的符記酬載中,也會包含虛擬機器執行個體及其專案的聲明。
在請求一完整格式的符記時,指定licenses=TRUE
將會包含與該執行個體相關聯的授權聲明。
{
"iss": "[TOKEN_ISSUER]",
"iat": [ISSUED_TIME],
"exp": [EXPIRED_TIME],
"aud": "[AUDIENCE]",
"sub": "[SUBJECT]",
"azp": "[AUTHORIZED_PARTY]",
"google": {
"compute_engine": {
"project_id": "[PROJECT_ID]",
"project_number": [PROJECT_NUMBER],
"zone": "[ZONE]",
"instance_id": "[INSTANCE_ID]",
"instance_name": "[INSTANCE_NAME]",
"instance_creation_timestamp": [CREATION_TIMESTAMP],
"instance_confidentiality": [INSTANCE_CONFIDENTIALITY],
"license_id": [
"[LICENSE_1]",
...
"[LICENSE_N]"
]
}
}
}
其中:
[TOKEN_ISSUER]
:可識別憑證核發者的網址。對於 Compute Engine,此值為https://accounts.google.com
。[ISSUED_TIME]
:表示憑證核發時間的 Unix 時間戳記。每當執行個體向中繼資料伺服器要求憑證時,這個值就會更新。[EXPIRED_TIME]
:表示憑證到期時間的 Unix 時間戳記。[AUDIENCE]
:執行個體和驗證執行個體識別資訊的系統雙方共同協議的專屬 URI。舉例來說,目標對象可以是兩個系統之間的連線網址。[SUBJECT]
:憑證的主體,也就是與執行個體相關聯的服務帳戶專屬 ID。[AUTHORIZED_PARTY]
:核發 ID 權杖的對象,也就是您與執行個體連結的服務帳戶專屬 ID。[PROJECT_ID]
:您建立執行個體的專案 ID。[PROJECT_NUMBER]
:您建立執行個體之專案的專屬編號。[ZONE]
:執行個體所在的區域。[INSTANCE_ID]
:這個符記所屬執行個體的專屬 ID。這個 ID 在專案和區域中是唯一的。[INSTANCE_NAME]
:這個符記所屬執行個體的名稱。如果您的專案使用區域 DNS,這個名稱可以在各區域重複使用,因此請使用project_id
、zone
和instance_id
值的組合來識別不重複的執行個體 ID。啟用全域 DNS 的專案會在專案中使用不重複的執行個體名稱。[CREATION_TIMESTAMP]
:表示建立執行個體時間的 Unix 時間戳記。[INSTANCE_CONFIDENTIALITY]
:如果執行個體是機密 VM,則為1
。[LICENSE_1]
到[LICENSE_N]
:與此執行個體相關聯的授權碼。
您的酬載可能類似以下範例:
{
"iss": "https://accounts.google.com",
"iat": 1496953245,
"exp": 1496956845,
"aud": "https://www.example.com",
"sub": "107517467455664443765",
"azp": "107517467455664443765",
"google": {
"compute_engine": {
"project_id": "my-project",
"project_number": 739419398126,
"zone": "us-west1-a",
"instance_id": "152986662232938449",
"instance_name": "example",
"instance_creation_timestamp": 1496952205,
"instance_confidentiality": 1,
"license_id": [
"1000204"
]
}
}
}
簽名
Google 會產生將標頭與酬載編碼並連結兩個值的 base64url 簽名。您可以透過公用 Oauth2 憑證檢查這個值以驗證憑證。