问题描述
我未能测试在 Google Cloud 的 Postgresql 产品中使用 IAM 用户的能力。
这是我的思考过程:
-
我在 Google Cloud 上的 Postgresql 实例上设置了相应的标志:
$ gcloud sql instances describe [MY_DB_INSTANCE] --format json | jq '.settings.databaseFlags' [ { "name": "cloudsql.iam_authentication","value": "on" } ] $
-
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 $
-
当我尝试使用以下任一命令连接到数据库时出现身份验证错误。在这两种情况下,我都使用
gcloud auth print-access-token
的输出作为我的密码:-
$ 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”页面列出了对此的确认:
-
$ 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]" $
-
-
如果我检查来自 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.
此时我很迷茫。
也许我的期望与连接到数据库的工作方式不一致。我预计:
根本不需要输入密码(例如
gcloud auth print-access-token
的值),因为gcloud
会自动为我生成和使用密码,-
如果需要手动输入密码(通过从粘贴缓冲区复制粘贴
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]
。对我来说似乎是一个错误。