如何将 IAM 服务帐号连接到 Cloud SQL 实例

问题描述

在 Google Cloud sql 上,Postgresql 的 IAM 数据库身份验证最近已普遍可用。

所以,我仔细地遵循了此处的说明:Overview of Cloud SQL IAM database authentication

我想我已经正确配置了我的 Cloud sql 实例,因为对于用户帐户,它运行良好。简而言之:

  1. 我在自己的 Google Cloud 项目中使用了自己的用户帐户并向其添加了角色 Cloudsql Instance Viewer
  2. 我将其添加为我的 Cloudsql 实例的用户
  3. 我授予它对我的数据库中所有表的所有权限
  4. 使用此处描述的命令:https://cloud.google.com/sql/docs/postgres/iam-logins,我可以登录到我的数据库
PGPASSWORD=$(gcloud auth print-access-token) psql --host=HOSTNAME \
                                                  --username=EMAIL \
                                                  --dbname=DATABASE_NAME

太好了!

但是现在,我真正不明白的是它应该如何在我使用服务帐户运行的应用程序中工作?医生没有说太多。这是否意味着我必须以编程方式执行此 gcloud auth print-access-token 的等效操作并将其结果作为连接到我的数据库密码传递?

解决方法

为了在实例上使用 IAM 用户或 IAM 服务帐户用户身份验证,用户或 SA 电子邮件(或我们在本例中处理的 SA 电子邮件片段)在使用数据库进行身份验证时替换了传统的用户名参数。>

此外,密码组件也发生了变化,您没有为 IAM 用户设置密码,而是使用 OAuth2 访问令牌,客户端必须通过单独的 API 调用请求该令牌。这些访问令牌仅在 60 分钟内有效,之后它们就会过期——但是,一旦令牌过期,它不会断开客户端的连接,但是如果该客户端连接中断并且必须重新连接到实例,并且已经超过一个小时,那么需要在新的连接尝试中提取并提供新的访问令牌。

对于此用例,即无人参与的应用程序,服务帐户 IAM 用户是最佳选择。您的客户端实现可能希望使用 API client library(例如 java),该类提供了一个方便的类,用于通过 JSON 密钥文件(可从您的 Cloud Console 为 SA 下载)获取服务帐户凭据,即,>

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json")).createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN)).refreshIfExpired();

请注意,为了获得适当的访问令牌,必须将范围设置为 Cloud SQL Admin API - 上面的示例显示了在上述库和初始化程序的上下文中是如何工作的。请注意,必须在访问令牌 available 之前调用对“refreshIfExpired()”的调用。

拥有 GoogleCredential 实例后,您可以通过调用 getAccessToken() 从中获取访问令牌,然后可以将其作为服务帐户 IAM 用户名的密码提供给您的数据库客户端的连接参数/字符串,即,

AccessToken token = credential.getAccessToken();

您在这里需要强烈考虑的是,此流程对您的客户端应用程序是否有意义。如果您的客户端应用程序通过连接池程序或其他一些连接管理库访问数据库,这些库会自动重试或使用静态凭证建立新连接 - 由于需要生成新的连接,使用 Postgres IAM 用户身份验证可能不太适合在没有访问令牌可用(即第一次登录尝试)或访问令牌已过期的情况下,每次连接尝试时的“密码”(访问令牌)。这最终意味着在您的客户端代码中承担更多的责任来管理连接建立、在断开/关闭的连接上重新连接并牺牲旨在在更传统的静态凭据环境中执行此操作的库的许多效率和便利性。