如何使用工作负载身份通过 Google Cloud .NET SDK 访问 Google Kubernetes Engine 中的 ESP?

How to use Workload identity to access ESP in the Google Kubernetes Engine with the Google Cloud .NET SDK?

背景

在 Google Kubernetes Engine 上,我们一直在使用云端点和可扩展服务代理 (v2) 进行 service-to-service 身份验证。

服务通过在 HTTP 请求的 Authorization header 中包含持有者 JWT 令牌来验证自己。

服务的标识已通过 GCP 服务帐户进行维护,并且在部署期间,Json 服务帐户密钥被安装到容器中的预定义位置,该位置设置为值GOOGLE_APPLICATION_CREDENTIALS 环境变量

这些服务是用 ASP.NET 核心在 C# 中实现的,为了生成实际的 JWT 令牌,我们使用 Google Cloud SDK (https://github.com/googleapis/google-cloud-dotnet, and https://github.com/googleapis/google-api-dotnet-client),我们调用以下代码方法:

var credentials = GoogleCredential.GetApplicationDefault();

如果 GOOGLE_APPLICATION_CREDENTIALS 正确设置为服务帐户密钥的路径,则此 return 是一个 ServiceAccountCredential object,我们可以在其上调用 GetAccessTokenForRequestAsync() 方法,它 return 是实际的 JWT 令牌。

var jwtToken = await credentials.GetAccessTokenForRequestAsync("https://other-service.example.com/");
var authHeader = $"Bearer {jwtToken}";

此过程一直在正常运行,没有任何问题。

情况是我们正在从使用手动维护的服务帐户密钥迁移到使用 Workload Identity,我不知道如何正确使用 Google Cloud SDK在这种情况下生成必要的 JWT 令牌。

问题

当我们在容器中启用 Workload Identity,并且不挂载服务帐户密钥文件,也不设置 GOOGLE_APPLICATION_CREDENTIALS env var 时,GoogleCredential.GetApplicationDefault() 调用 returns a ComputeCredential 而不是 ServiceAccountCredential.
如果我们调用 GetAccessTokenForRequestAsync() 方法,那么 return 是一个非 JWT 格式的标记。

我检查了实现,令牌似乎是从元数据服务器中检索到的,其预期的响应格式似乎是标准的 OAuth 2.0 模型(在 this model class 中表示):

{
  "access_token": "foo",
  "id_token": "bar",
  "token_type": "Bearer",
  ...
}

GetAccessTokenForRequestAsync() 方法 return 是 access_token 的值。但据我所知,这不是 JWT 令牌,事实上,当我尝试使用它对 ESP 进行身份验证时,它的响应是

{
 "code": 16,
 "message": "JWT validation failed: Bad JWT format: Invalid JSON in header",
 ..
}

据我了解,通常 id_token 包含 JWT 令牌,应该可以通过 IdToken 属性 的 TokenResponse object],它也可以通过 SDK 访问,我试过这样访问它:

var jwtToken = ((ComputeCredential)creds.UnderlyingCredential).Token.IdToken;

但是这个 returns null,所以显然元数据服务器在 id_token 字段中没有 return 任何东西。

问题

在 GKE 中使用 Workload Identity 时,使用 .NET Google Cloud SDK 获取 JWT 令牌以访问 ESP 的正确方法是什么?

要获取附加服务帐户的 IdToken,您可以使用 GoogleCredential.GetApplicationDefault().GetOidcTokenAsync(...)