如何将 IAM 服务帐户连接到 Cloud SQL 实例
How to connect an IAM service account to a Cloud SQL instance
在 Google Cloud SQL 上,PostgreSQL 的 IAM 数据库身份验证最近已普遍可用。
所以,我仔细按照这里的说明操作:Overview of Cloud SQL IAM database authentication。
我想我已经正确配置了我的 Cloud SQL 实例,因为对于用户帐户,它工作正常。简而言之:
- 我在我的 Google 云项目中使用了我自己的用户帐户,并向其中添加了角色
CloudSQL Instance Viewer
- 我将其添加为我的 CloudSQL 实例
的用户
- 我授予它对我的数据库的所有表的所有权限
- 并且使用此处描述的命令: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),它提供了一种便利 class 通过 JSON 密钥文件(可下载)提取服务帐户凭据来自您的 Cloud Console 的 SA)即
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json")).createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN)).refreshIfExpired();
请注意,为了获得适当的访问令牌,范围必须设置为 Cloud SQL Admin API - the above example shows how that works within the context of the aforementioned library and initializer. Note that the call to 'refreshIfExpired()' must be called before the access token is available。
获得 GoogleCredential 实例后,您可以通过调用 getAccessToken()
从中获取访问令牌,然后可以将其作为服务帐户的密码提供给数据库客户端的连接 parameters/string IAM 用户名,即
AccessToken token = credential.getAccessToken();
不过,您在这里需要认真考虑的是,此流程对您的客户端应用程序是否有意义。如果您的客户端应用程序通过连接池或其他一些连接管理库访问数据库,这些连接管理库会自动重试或使用静态凭证建立新连接——使用 Postgres IAM 用户身份验证可能不太合适,因为需要生成一个新的'password'(访问令牌)在没有访问令牌可用(即首次登录尝试)或访问令牌已过期的每次连接尝试中。这最终意味着在您的客户端代码中承担更多责任来管理连接建立、重新连接 dropped/closed 连接并牺牲许多库的效率和便利性,这些库旨在在更传统的静态凭证环境中执行此操作。
在 Google Cloud SQL 上,PostgreSQL 的 IAM 数据库身份验证最近已普遍可用。
所以,我仔细按照这里的说明操作:Overview of Cloud SQL IAM database authentication。
我想我已经正确配置了我的 Cloud SQL 实例,因为对于用户帐户,它工作正常。简而言之:
- 我在我的 Google 云项目中使用了我自己的用户帐户,并向其中添加了角色
CloudSQL Instance Viewer
- 我将其添加为我的 CloudSQL 实例 的用户
- 我授予它对我的数据库的所有表的所有权限
- 并且使用此处描述的命令: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),它提供了一种便利 class 通过 JSON 密钥文件(可下载)提取服务帐户凭据来自您的 Cloud Console 的 SA)即
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json")).createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN)).refreshIfExpired();
请注意,为了获得适当的访问令牌,范围必须设置为 Cloud SQL Admin API - the above example shows how that works within the context of the aforementioned library and initializer. Note that the call to 'refreshIfExpired()' must be called before the access token is available。
获得 GoogleCredential 实例后,您可以通过调用 getAccessToken()
从中获取访问令牌,然后可以将其作为服务帐户的密码提供给数据库客户端的连接 parameters/string IAM 用户名,即
AccessToken token = credential.getAccessToken();
不过,您在这里需要认真考虑的是,此流程对您的客户端应用程序是否有意义。如果您的客户端应用程序通过连接池或其他一些连接管理库访问数据库,这些连接管理库会自动重试或使用静态凭证建立新连接——使用 Postgres IAM 用户身份验证可能不太合适,因为需要生成一个新的'password'(访问令牌)在没有访问令牌可用(即首次登录尝试)或访问令牌已过期的每次连接尝试中。这最终意味着在您的客户端代码中承担更多责任来管理连接建立、重新连接 dropped/closed 连接并牺牲许多库的效率和便利性,这些库旨在在更传统的静态凭证环境中执行此操作。