目标:
我已经建立了一个Google网关。API的后端是一个云函数(用python编写)。云功能应该从Google BigQuery (BQ)查询数据。要做到这一点,我想要创建一个烧烤客户端(google.cloud.bigquery.Client()
)。不同的应用程序应该使用不同的服务帐户访问API。服务帐户有权只访问项目中的特定数据集。因此,服务帐户/应用程序应该只能查询它们具有权限的数据集。因此,云函数中的BQ客户端应该使用发送请求到API的服务帐户进行初始化。
我尝试了什么:
API使用以下OpenAPI定义进行了保护,因此需要一个由服务帐户SA-EMAIL签名的JWT才能在那里发送请求:
securityDefinitions:
sec-def1:
authorizationUrl: ""
flow: "implicit"
type: "oauth2"
x-google-issuer: "SA-EMAIL"
x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/SA-EMAIL"
x-google-audiences: "SERVICE"
对于使用我的云功能的路径,我使用以下后端配置:
x-google-backend:
address: https://PROJECT-ID.cloudfunctions.net/CLOUD-FUNCTION
path_translation: CONSTANT_ADDRESS
因此,在云函数本身中,我将转发的JWT作为X-Forwarded-Authorization
,并从already获得已验证的base64url编码的JWT有效载荷为X-Apigateway-Api-Userinfo
。
我尝试使用X-Forwarded-Authorization
中的JWT来获得凭据:
bearer_token = request.headers.get('X-Forwarded-Authorization')
token = bearer_token.split(" ")[1]
cred = google.auth.credentials.Credentials(token)
起初,这似乎是可行的,因为cred.valid
返回True
,但是当尝试使用google.cloud.bigquery.Client(credentials=cred)
创建客户机时,它会在日志中返回以下错误:
google.auth.exceptions.RefreshError: The credentials do not contain
the necessary fields need to refresh the access token. You must
specify refresh_token, token_uri, client_id, and client_secret.
我对auth/oauth没有太多的经验,但我认为我没有必要的标记/属性,错误说在我的云功能中缺少这些标记/属性。而且,我也不太清楚为什么会有RefreshError
,因为我不想刷新令牌(也不要显式地这样做),只需要再次使用它(可能是错误的做法吗?)。
问题:
是否有可能以我尝试过的方式或以任何其他方式实现我的目标?
发布于 2021-10-01 19:54:19
您的目标是捕获名为API的凭据,并在云函数中重用它以调用BigQuery。
遗憾的是,你不能。为什么?因为API阻止您实现这一目标(出于安全原因,这是一个好消息)。JWT令牌被正确地转发到云函数,但是签名部分已经被删除(您只接收到JWT令牌的头和正文)。
安全验证已经由API网关完成,您必须依赖于该身份验证。
,解决方案是什么?
我的解决方案如下:在您收到的截断JWT中,您可以获得主体和服务帐户电子邮件。从那里,您可以使用云函数服务帐户,模拟您收到的服务帐户电子邮件。
就像这样,Cloud服务帐户只需要模拟这些服务帐户的权限,并且保留在原始服务帐户上提供的权限。
我看不出其他解决办法来解决你的问题。
发布于 2021-10-01 22:50:11
您从API接收到的JWT不是OAuth访问令牌。因此,JWT部分不是您可以用于BigQuery客户端授权的凭据。
正如@guillaume 所指出的,有效载荷包含身份的电子邮件地址。如果标识是服务帐户,则可以实现该标识的模拟。如果您使用API网关的多个身份,这可能是一个很好的解决方案。如果标识是用户帐户,则需要实现域范围的委托.
我建议只使用分配给云函数的服务帐户,并分配适当的角色来初始化BigQuery客户端。如果API网关提供访问云功能的授权,则不需要额外的模拟层。
另一种选择是将匹配的服务帐户JSON密钥文件存储在秘密管理器中,并在需要时提取它以创建BigQuery客户端。
https://stackoverflow.com/questions/69407879
复制相似问题