go - 使用 Cloud Run 进行内部 CLI 的 Google Cloud 身份验证
问题描述
我们使用 Cloud Run 构建了多项服务。我们的目标是构建一个内部 CLI,允许我们的开发人员调用这些服务。我们无法生成id_token
与位于 Cloud Run 服务前面的 Identity Aware Proxy 一起使用的问题。
根据文档,调用 Cloud Run 服务可以通过使用gcloud
和gcloud auth print-identity-token
命令来完成。这很好用。这也避免了下载服务帐户凭据并将其传递给我们的开发人员,因为此方法利用了您的应用程序默认凭据。
我们已经尝试实现一些东西来print-identity-token
在 Go 中复制这个功能,但没有成功。生成的id_token
返回 401 给我们所有的 Cloud Run API。生成令牌的示例代码:
func GetIDToken() string {
ctx := context.Background()
tokenSource, err := google.DefaultTokenSource(ctx, "openid", "email")
if err != nil {
log.Fatal(err)
}
token, err := tokenSource.Token()
if err != nil {
log.Fatal(err)
}
return fmt.Sprintf("%v", token.Extra("id_token"))
}
这将返回一个id_token
但它不适用于 API。根据文档,范围似乎是正确的。
这给我们留下了两个问题:
- 这是为 IAP 生成 Id 令牌的正确方法吗?
- 有没有更好的方法来为我们的开发人员实现对这些内部 API 的身份验证?
解决方案
目前尚不清楚您为什么要尝试重新实现gcloud auth print-identity-token
. 我强烈建议您不要尝试这样做。
gcloud
如果您正在构建开发人员 CLI,如果您在开发机器中出现并调用此命令以检索 id_token ,您的工作会容易得多。
重新实现print-identity-token
确实很困难。因为gcloud
使用内部存储的 OAuth 令牌端点调用 OAuth 令牌端点以refresh_token
获取. (运行命令以查看更多信息,并将相关的 gcloud 配置设置为不编辑来自 req/resp 正文的令牌。)id_token
access_token
--log-http
或者,如果没有gcloud
在开发人员机器上使用 GSuite 帐户进行身份验证,您唯一的其他选择是将IAM 服务帐户密钥分发到每台开发人员机器。(另一方面,您需要确保这些密钥正确旋转并保持安全。)
您可以使用 IAM 服务帐户密钥https://www.googleapis.com/oauth2/v4/token
通过适当的字段(如 client_secret、grant_type 等)进行 POST 以获得id_token
. 我相信最简单的方法是将GOOGLE_APPLICATION_CREDENTIALS
Go 程序中的 env 变量设置为密钥文件,audience
在令牌交换请求中指定正确的参数,然后照常使用token.Extra("id_token")
。
另外:我还注意到您的身份字段在您的示例代码中未设置为 Cloud Run 服务的 URL。