[英]How do I create an Access Token from Service Account Credentials using REST API?
我在 Google Cloud Platform 中創建了一個服務帳戶並下載了 JSON 格式的私鑰。 我正在嘗試通過 REST API 創建計算資源。 出於身份驗證目的,我需要一個 AccessToken,需要將其設置為創建計算資源 REST API 的標頭。 是否有 REST API 從私鑰獲取訪問令牌(不使用 SDK 或 Google 客戶端)?
以下示例向您展示了在不使用 Python SDK 的情況下調用 Google Cloud API 的幾個重要步驟。 類似的代碼幾乎適用於任何語言(c#、java、php、nodejs)。
使用您的服務帳戶 Json 文件的文件名、您的 Google 區域和您的項目 ID 更改源代碼。
此示例將列出指定項目的一個區域中的實例。 通過這個示例,您將了解調用 API 來創建 GCE 實例的框架。
此代碼將向您展示如何:
Python 3.x 中的示例程序:
'''
This program lists lists the Google Compute Engine Instances in one zone
'''
# Author: John Hanley
# https://www.jhanley.com
import time
import json
import jwt
import requests
import httplib2
# Project ID for this request.
project = 'development-123456'
# The name of the zone for this request.
zone = 'us-west1-a'
# Service Account Credentials, Json format
json_filename = 'service-account.json'
# Permissions to request for Access Token
scopes = "https://www.googleapis.com/auth/cloud-platform"
# Set how long this token will be valid in seconds
expires_in = 3600 # Expires in 1 hour
def load_json_credentials(filename):
''' Load the Google Service Account Credentials from Json file '''
with open(filename, 'r') as f:
data = f.read()
return json.loads(data)
def load_private_key(json_cred):
''' Return the private key from the json credentials '''
return json_cred['private_key']
def create_signed_jwt(pkey, pkey_id, email, scope):
''' Create a Signed JWT from a service account Json credentials file
This Signed JWT will later be exchanged for an Access Token '''
# Google Endpoint for creating OAuth 2.0 Access Tokens from Signed-JWT
auth_url = "https://www.googleapis.com/oauth2/v4/token"
issued = int(time.time())
expires = issued + expires_in # expires_in is in seconds
# Note: this token expires and cannot be refreshed. The token must be recreated
# JWT Headers
additional_headers = {
'kid': pkey_id,
"alg": "RS256",
"typ": "JWT" # Google uses SHA256withRSA
}
# JWT Payload
payload = {
"iss": email, # Issuer claim
"sub": email, # Issuer claim
"aud": auth_url, # Audience claim
"iat": issued, # Issued At claim
"exp": expires, # Expire time
"scope": scope # Permissions
}
# Encode the headers and payload and sign creating a Signed JWT (JWS)
sig = jwt.encode(payload, pkey, algorithm="RS256", headers=additional_headers)
return sig
def exchangeJwtForAccessToken(signed_jwt):
'''
This function takes a Signed JWT and exchanges it for a Google OAuth Access Token
'''
auth_url = "https://www.googleapis.com/oauth2/v4/token"
params = {
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": signed_jwt
}
r = requests.post(auth_url, data=params)
if r.ok:
return(r.json()['access_token'], '')
return None, r.text
def gce_list_instances(accessToken):
'''
This functions lists the Google Compute Engine Instances in one zone
'''
# Endpoint that we will call
url = "https://www.googleapis.com/compute/v1/projects/" + project + "/zones/" + zone + "/instances"
# One of the headers is "Authorization: Bearer $TOKEN"
headers = {
"Host": "www.googleapis.com",
"Authorization": "Bearer " + accessToken,
"Content-Type": "application/json"
}
h = httplib2.Http()
resp, content = h.request(uri=url, method="GET", headers=headers)
status = int(resp.status)
if status < 200 or status >= 300:
print('Error: HTTP Request failed')
return
j = json.loads(content.decode('utf-8').replace('\n', ''))
print('Compute instances in zone', zone)
print('------------------------------------------------------------')
for item in j['items']:
print(item['name'])
if __name__ == '__main__':
cred = load_json_credentials(json_filename)
private_key = load_private_key(cred)
s_jwt = create_signed_jwt(
private_key,
cred['private_key_id'],
cred['client_email'],
scopes)
token, err = exchangeJwtForAccessToken(s_jwt)
if token is None:
print('Error:', err)
exit(1)
gce_list_instances(token)
有關詳細信息,請訪問我的博客。 我寫這樣的文章並發布源代碼,以幫助其他人了解如何為雲編寫軟件。
注意:如評論中所述,這實際上不是問題的解決方案,因為它使用 SDK。 無論如何,由於答案似乎對其他用戶有用,我沒有刪除它
有一種更簡單的方法可以使用 Google 庫從服務帳戶生成令牌
from google.auth.transport import requests
from google.oauth2 import service_account
CREDENTIAL_SCOPES = ["https://www.googleapis.com/auth/cloud-platform"]
CREDENTIALS_KEY_PATH = '/PATH/TO/SERVICE_ACCOUNT.json'
def get_service_account_token():
credentials = service_account.Credentials.from_service_account_file(
CREDENTIALS_KEY_PATH, scopes=CREDENTIAL_SCOPES)
credentials.refresh(requests.Request())
return credentials.token
或者如果你想使用默認身份驗證
import google
from google.auth.transport import requests
CREDENTIAL_SCOPES = ["https://www.googleapis.com/auth/cloud-platform"]
def get_default_token():
credentials, project_id = google.auth.default(scopes=CREDENTIAL_SCOPES)
credentials.refresh(requests.Request())
return credentials.token
創建credentials對象時,令牌為空,但在刷新credentials后,它包含可用作 API 請求標頭的訪問令牌
使用JAVA的相同解決方案
import com.google.auth.oauth2.GoogleCredentials;
import java.io.FileInputStream;
import java.io.IOException;
public class GoogleHelper {
public static String getAccessToken() throws IOException {
return GoogleCredentials
.fromStream(new FileInputStream("/PATH/TO/SERVICE_ACCOUNT.json"))
.createScoped("https://www.googleapis.com/auth/cloud-platform")
.refreshAccessToken()
.getTokenValue();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.