【问题标题】:GCP - Get ID token in environment-independent wayGCP - 以独立于环境的方式获取 ID 令牌
【发布时间】:2019-08-06 17:34:57
【问题描述】:

我有一个必须验证调用者身份的应用程序。为此,我需要每个调用服务的客户端的 ID 令牌(来自 Google OpenID Connect 实现的 JWT)。

我想编写在本地使用默认用户凭据(用于测试和开发)以及在生产中的 Compute Engine 实例上运行的客户端代码。 official Python auth SDK 通常可以很好地处理这些情况并省去我检查环境的麻烦,例如我可以打电话给google.auth.default,它会知道从哪里获取凭据。

然而google.auth 包似乎只能在与环境无关的情况下给我 auth 令牌,而不是 ID 令牌方式。这是我尝试过的:

import google.auth
from google.auth.transport import requests

credentials, project = google.auth.default(scopes=["openid"])
req = requests.Request()
credentials.refresh(req)

print(credentials.id_token)

这可以在我的笔记本电脑上使用我的默认凭据,但在 Compute Engine 实例上却收到错误 AttributeError: 'Credentials' object has no attribute 'id_token'

根据this page in the docs,您应该通过从元数据服务器请求实例来获取实例的 ID 令牌...

import requests

audience = 'service_identifier'
metadata_server_token_url = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience='
token_request_url = metadata_server_token_url + audience
token_request_headers = {'Metadata-Flavor': 'Google'}

token_response = requests.get(token_request_url, headers=token_request_headers)
jwt = token_response.content.decode("utf-8")
print(jwt)

我不想那样做。我不想手动检查环境。 SDK 应该为我处理这种复杂性。难道不应该有办法利用google-auth SDK 以独立于环境的方式生成 ID 令牌吗?

编辑 1:为什么我需要这个

该应用程序基于 Cloud Functions,它返回高度敏感的数据。只有一组特定的主题——一些受信任的开发人员和服务——应该能够访问这些数据。因此,云函数必须使用 Google 签名的 ID 令牌验证调用者(用户或服务帐户)的 ID。具体来说,我需要知道 sub 声明,即 JWT 中的“主题”。这实际上是 IAM 功能旨在解决的同一问题,记录在 here。但是,我不能使用它们,因为它们仍处于 beta 中。所以,我暂时将身份检查手动写入云函数中。

【问题讨论】:

  • 我已经更新了更多细节。基本上,我需要 JWT 中的 sub 声明来识别调用者。我看到JWT的构造是由aud参数化的,从元数据服务器获取ID令牌时必须传递它。如果 SDK 当前无法处理此问题,这似乎是一个明智的功能请求:一种采用受众参数并返回 ID 令牌的新方法...
  • 你找到办法了吗,安迪?
  • @AndyCarlson 你找到办法了吗?

标签: google-cloud-platform google-compute-engine google-authentication


【解决方案1】:

我想我有这个问题的答案。我总是可以让它在本地或云中工作,诀窍是找到一种将两者结合起来的方法。我的同事实际上向我展示了如何做到这一点,我只是想与其他正在寻找解决方案的人分享。

import google.auth
from   google.auth.transport.requests import AuthorizedSession, Request
from   google.oauth2.id_token import fetch_id_token
import requests

def GetIdToken(audience):
  credentials, _ = google.auth.default()
  session = AuthorizedSession(credentials)
  request = Request(session)
  credentials.refresh(request)
  if hasattr(credentials, "id_token"):
    return credentials.id_token
  return fetch_id_token(request, audience)

def ProcessPayload(url, payload):
  # Get the ID Token
  id_token = GetIdToken(url)
  # Process post request
  headers        = {'Authorization': f'Bearer {id_token}'}
  response       = requests.post(url, json=payload, headers=headers)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-30
    • 2019-04-27
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2021-05-10
    相关资源
    最近更新 更多