使用 IAM 用户连接到 Cloud SQL

问题描述

我未能测试在 Google Cloud 的 Postgresql 产品中使用 IAM 用户的能力。

这是我的思考过程:

  1. 我在 Google Cloud 上的 Postgresql 实例上设置了相应的标志:

    $ gcloud sql instances describe [MY_DB_INSTANCE] --format json | jq '.settings.databaseFlags'
    [
      {
        "name": "cloudsql.iam_authentication","value": "on"
      }
    ]
    $
    
  2. 我在数据库实例中创建了一个 IAM 用户

    gcloud sql users create [MY_EMAIL] --instance=[MY_DB_INSTANCE] --type=CLOUD_IAM_USER
    
    $ gcloud sql users list --instance [MY_DB_INSTANCE] | grep CLOUD_IAM_USER
    [MY_EMAIL]                                      CLOUD_IAM_USER
    $
    
  3. 当我尝试使用以下任一命令连接到数据库时出现身份验证错误在这两种情况下,我都使用 gcloud auth print-access-token输出作为我的密码

    • 方法将我的 IP 添加到许可名单:

      $ gcloud sql connect [MY_DB_INSTANCE] --database=[DB_NAME] --user=[MY_EMAIL]
      Allowlisting your IP for incoming connection for 5 minutes...done.
      Connecting to database with sql user [MY_EMAIL]. Password:
      psql: error: FATAL:  Cloud sql IAM user authentication Failed for user "[MY_EMAIL]"
      FATAL:  pg_hba.conf rejects connection for host "100.200.300.400",user "[MY_EMAIL]",database "[MY_EMAIL]",SSL off
      $
      

      可能与失败有关,也可能无关,但这里的错误信息令人困惑。最后一行说明 ...database "[MY_EMAIL]",但显然我没有尝试连接到与我的电子邮件同名的数据库;我正在连接到具有非常具体名称数据库,例如[DB_NAME]。

      更新。截至目前,“Known issues页面列出了对此的确认:

      以下仅适用于用户('postgres'):gcloud sql connect --user

    • 方法使用 Cloud sql 代理:

      $ gcloud beta sql connect [MY_DB_INSTANCE] --database=[DB_NAME] --user=[MY_EMAIL]
      Starting Cloud sql Proxy: [/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/bin/cloud_sql_proxy -instances my-project-id:europe-west1:[MY_DB_INSTANCE]=tcp:9470 -credential_file /Users/eugene/.config/gcloud/legacy_credentials/[MY_EMAIL]/adc.json]]
      2021/01/26 16:35:03 Rlimits for file descriptors set to {&{8500 9223372036854775807}}
      2021/01/26 16:35:03 using credential file for authentication; path="/Users/eugene/.config/gcloud/legacy_credentials/[MY_EMAIL]/adc.json"
      2021/01/26 16:35:04 Listening on 127.0.0.1:9470 for my-project-id:europe-west1:[MY_DB_INSTANCE]
      2021/01/26 16:35:04 Ready for new connections
      Connecting to database with sql user [MY_EMAIL].Password:
      psql: error: FATAL:  Cloud sql IAM user authentication Failed for user "[MY_EMAIL]"
      $
      
  4. 如果我检查来自 Cloud Console 的访问日志,对于两次登录尝试,我都会看到相同的错误消息:

    2021-01-26 14:20:11.988 UTC [594848]: [2-1] db=[DB_NAME],user=[MY_EMAIL] DETAIL:  Request is missing required authentication credential. Expected OAuth 2 access token,login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
    

此时我很迷茫。

也许我的期望与连接到数据库的工作方式不一致。我预计:

  1. 根本不需要输入密码(例如 gcloud auth print-access-token 的值),因为 gcloud自动为我生成和使用密码

  2. 如果需要手动输入密码(通过从粘贴缓冲区复制粘贴 gcloud auth print-access-token 命令的输出),它会起作用(但不会)。

我希望通过依赖 IAM 身份验证机制对数据库进行身份验证,我将能够避免创建用户并使用 psql(或类似地使用 {{ 1}}).

我可能遗漏了什么?

更新。如果我不使用 gcloud sql users create ... --type=BUILD_IN 命令,而是运行代理并直接使用该命令,则我能够成功连接:

gcloud sql
$ cloud_sql_proxy -instances my-project-id:europe-west1:[MY_DB_INSTANCE]=tcp:9470
2021/01/26 17:29:56 Rlimits for file descriptors set to {&{8500 9223372036854775807}}
2021/01/26 17:29:56 Listening on 127.0.0.1:9470 for my-project-id:europe-west1:[MY_DB_INSTANCE]
2021/01/26 17:29:56 Ready for new connections

解决方法

我遇到了同样的问题。没有详细记录的关键信息是 Cloud SQL 代理工具会在幕后自动为您请求新令牌。因此,您无需手动传递令牌,只需将要使用的客户端指向 Cloud SQL 代理服务即可。

要激活此模式,您需要指定 -enable_iam_login 命令行选项,如下所示:

./cloud_sql_proxy -instances=[project]:[zone]:[server]=tcp:5432 -enable_iam_login

它将为当前使用 gcloud auth login 进行身份验证的任何用户生成访问密钥

连接到 Cloud SQL 代理服务时,请务必禁用 sslmode。它处理自己的加密,因此如果 postgres 客户端也尝试加密连接将超时。由于 Cloud SQL 代理服务正在处理身份验证,因此您只需在 postgres 客户端中指定 user

psql "host=127.0.0.1 dbname=postgres user=[the IAM email account] sslmode=disable"

它不应该要求输入密码。如果是,请将其留空。

我发现 Cloud SQL Proxy 自述文件比官方文档更有用:https://github.com/GoogleCloudPlatform/cloudsql-proxy/blob/main/README.md

,

在玩弄它之后,能够拿起正确的连接命令。这是:

env PGPASSWORD=(gcloud auth print-access-token) gcloud beta sql connect [MY_DB_INSTANCE] --user=[MY_EMAIL] --database=[MY_DB]

这里的关键似乎是为进程指定 PGPASSWORD 变量,然后,当提示输入密码时,只需按 Enter ?

我还尝试过,并且似乎是 gcloud sql 中的一个错误,是通过非测试版 gcloud sql connect 进行连接:

$ env PGPASSWORD=(gcloud auth print-access-token) gcloud sql connect [MY_DB_INSTANCE] --user=[MY_EMAIL] --database=[MY_DB]
Allowlisting your IP for incoming connection for 5 minutes...done.
Connecting to database with SQL user [MY_EMAIL].Password:
psql: error: FATAL:  database "[MY_EMAIL]" does not exist
$

注意它是如何表示 database "[MY_EMAIL]" does not exist,而数据库被指定为命令行标志 --database=[MY_DB]。对我来说似乎是一个错误。