在 GCR 上获取当前服务帐户

Get current service account on GCR

问题

我是 运行 GCR 上的 ASP 核心应用程序,需要检索当前的 ServiceAccountCredential 才能签署网址。显而易见的方法是:

var credential = GoogleCredential.GetApplicationDefault();
var serviceCred = (ServiceAccountCredential)credential.UnderlyingCredential;
var urlSigner = UrlSigner.FromServiceAccountCredential(serviceCred);

出乎我的意料,GoogleCredential.GetApplicationDefault 返回的 UnderlyingCredential 是一个实例 ComputeCredential(即使 GCR 服务是 运行 在我的服务帐户上专门为此目的创建)。

结果是引发 InvalidCastException,错误消息为:Unable to cast object of type 'Google.Apis.Auth.OAuth2.ComputeCredential' to type 'Google.Apis.Auth.OAuth2.ServiceAccountCredential'.

解决方法

作为一种变通方法,我为服务帐户创建了一个密钥,将其存储在秘密管理器中,现在正在使用它:

var credential = GoogleCredential.FromJson(credJson);
var serviceCred = (ServiceAccountCredential)credential.UnderlyingCredential;
var urlSigner = UrlSigner.FromServiceAccountCredential(serviceCred);

解决方案?

虽然解决方法有效,但我宁愿根本不创建密钥,只是为了避免密钥散落在各处。有没有合适的解决方案可以用来检索当前的 ServiceAccountCredential?或者,否则,使用 ComputeCredential?

对 url 进行签名

应用程序默认凭据是一种获取凭据的方法。在您的例子中,GCR 服务有一个分配给它的服务帐户。计算功能由 Compute Engine 提供,这就是您将 ComputeEngine 视为凭据类型的原因。这些凭据由附加到 Compute Engine 实例的元数据服务创建。

元数据服务提供令牌 - OAuth 2.0 访问和身份令牌。元数据服务器不提供签署数据 (URL) 所需的服务帐户 私钥。因此,您不能使用元数据服务器创建的凭据对 Google 调用 blobs.

的数据进行签名

您有两个选择:

  1. 使用您的方法并将现有服务帐户 JSON 密钥文件存储在 Secret Manager 中。这是一种安全且推荐的方法。此方法需要添加 IAM 角色以访问存储在 Secret Manager 中的机密。您是正确的,因为您有一个额外的任务来管理服务帐户 JSON 安全和部署密钥文件。

  2. 使用 IAM 签名。由于元数据服务器不提供对私钥的访问,Google 提供了一个 API 来签署数据。这种方法也很安全,值得推荐。此方法需要添加 IAM 权限 iam.serviceAccounts.signBlob,该权限包含在 Service Account Token Creator (roles/iam 等角色中。 serviceAccountTokenCreator).

以下 API 已弃用。我将它包括在内是因为有一个很好的 C# 示例展示了如何使用 API。类似的方法适用于新的 API。此 API 与新 API 之间的主要区别在于添加了您不需要的 delegates。委托是涉及模拟(委托)的身份。

Method: projects.serviceAccounts.signBlob

新的API:

Method: projects.serviceAccounts.signBlob