我的目标是在不依赖gcloud二进制文件的情况下复制/复制
我正在尝试使用Python根据https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address中有关保留静态外部IP地址的文档对googleapis计算终端进行POST身份验证。
但是我的POST每次都返回401。
我已经从google.auth.jwt Python模块创建了一个JWT,当我解码它时,JWT中嵌入了我期望出现的所有字符串。
我还尝试了包括以下OAuth范围的组合: - "https://www.googleapis.com/auth/userinfo.email" - "https://www.googleapis.com/auth/compute" - "https://www.googleapis.com/auth/cloud-platform"
这是我获取JWT的函数,使用我的服务帐户JSON密钥文件中的信息。
一旦我获得JWT,然后进行以下POST请求失败,返回401错误。
无论我在JWT中使用了多少个范围组合或为我的服务帐户提供了多少权限,我都收到了401错误。我做错了什么吗?
编辑:非常感谢@JohnHanley指出我在GCP的身份验证序列中缺少下一个/第二个POST到https://www.googleapis.com/oauth2/v4/token URL。因此,您会获得一个JWT来获取“访问令牌”。
我已更改我的调用,使用python jwt模块而不是google.auth.jwt模块和google.auth.crypt.RSASigner结合使用。所以代码有点简单,我将其放在一个方法中。
gcloud compute addresses create
的功能。我正在尝试使用Python根据https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address中有关保留静态外部IP地址的文档对googleapis计算终端进行POST身份验证。
但是我的POST每次都返回401。
我已经从google.auth.jwt Python模块创建了一个JWT,当我解码它时,JWT中嵌入了我期望出现的所有字符串。
我还尝试了包括以下OAuth范围的组合: - "https://www.googleapis.com/auth/userinfo.email" - "https://www.googleapis.com/auth/compute" - "https://www.googleapis.com/auth/cloud-platform"
这是我获取JWT的函数,使用我的服务帐户JSON密钥文件中的信息。
def _generate_jwt( tokenPath, expiry_length=3600 ):
now = int(time.time())
tokenData = load_json_data( tokenPath )
sa_email = tokenData['client_email']
payload = {
'iat': now,
# expires after 'expiry_length' seconds.
"exp": now + expiry_length,
'iss': sa_email,
"scope": " ".join( [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/userinfo.email"
] ),
'aud': "https://www.googleapis.com/oauth2/v4/token",
'email': sa_email
}
# sign with keyfile
signer = google.auth.crypt.RSASigner.from_service_account_file( tokenPath )
jwt = google.auth.jwt.encode(signer, payload)
return jwt
一旦我获得JWT,然后进行以下POST请求失败,返回401错误。
gapiURL = 'https://www.googleapis.com/compute/v1/projects/' + projectID + '/regions/' + region + '/addresses'
jwtToken = _generate_jwt( servicetoken )
headers = {
'Authorization': 'Bearer {}'.format( jwtToken ),
'content-type' : 'application/json',
}
post = requests.post( url=gapiURL, headers=headers, data=data )
post.raise_for_status()
return post.text
无论我在JWT中使用了多少个范围组合或为我的服务帐户提供了多少权限,我都收到了401错误。我做错了什么吗?
编辑:非常感谢@JohnHanley指出我在GCP的身份验证序列中缺少下一个/第二个POST到https://www.googleapis.com/oauth2/v4/token URL。因此,您会获得一个JWT来获取“访问令牌”。
我已更改我的调用,使用python jwt模块而不是google.auth.jwt模块和google.auth.crypt.RSASigner结合使用。所以代码有点简单,我将其放在一个方法中。
## serviceAccount auth sequence for google :: JWT -> accessToken
def gke_get_token( serviceKeyDict, expiry_seconds=3600 ):
epoch_time = int(time.time())
# Generate a claim from the service account file.
claim = {
"iss": serviceKeyDict["client_email"],
"scope": " ".join([
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email"
]),
"aud": "https://www.googleapis.com/oauth2/v4/token",
"exp": epoch_time + expiry_seconds,
"iat": epoch_time
}
# Sign claim with JWT.
assertion = jwt.encode( claim, serviceKeyDict["private_key"], algorithm='RS256' ).decode()
data = urllib.urlencode( {
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": assertion
} )
# Request the access token.
result = requests.post(
url="https://www.googleapis.com/oauth2/v4/token",
headers={
"Content-Type": "application/x-www-form-urlencoded"
},
data=data
)
result.raise_for_status()
return loadJsonData(result.text)["access_token"]