使用 IAM 身份验证管理用户

本页面介绍如何将使用 IAM 数据库身份验证的用户或服务帐号添加到数据库,以及如何管理这些用户和服务帐号。如需详细了解 IAM 集成,请参阅 IAM 数据库身份验证概览

准备工作

  1. 登录您的 Google Cloud 帐号。如果您是 Google Cloud 新手,请创建一个帐号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

  3. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  4. 安装并初始化 Cloud SDK
  5. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到“项目选择器”

  6. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  7. 安装并初始化 Cloud SDK
  8. 启用 Cloud Key Management Service API。

    启用 API

  9. 确保您的用户帐号具有 Cloud SQL Admin 角色。

    转到 IAM 页面

  10. 在 Cloud SQL 实例上启用 IAM 数据库身份验证
  11. 对于包含用户需要访问的数据库的每个项目,请确保向需要该权限的用户授予 IAM 访问权限。请参阅授予、更改和撤消对资源的访问权限
  12. 确保您已为需要访问项目中的数据库的每个服务添加了服务帐号

将 IAM 用户或服务帐号添加到数据库

对于您要有权访问数据库实例的每位 IAM 用户,您都必须为其创建一个新的数据库用户。数据库用户名必须是 IAM 用户的电子邮件地址,例如 test-user@gmail.com

使用 REST 命令时,用户名必须使用英文引号,因为它包含特殊字符(@.)。

服务帐号使用 service-account-name@project-id.iam.gserviceaccount.com 格式。

如需添加 IAM 用户或服务帐号,您需要添加新的数据库用户并选择 IAM 作为身份验证方法:

控制台

  1. 在 Google Cloud Console 中,转到 Cloud SQL 实例页面。

    转到“Cloud SQL 实例”

  2. 点击实例名称,打开其概览页面。
  3. 从 SQL 导航菜单中选择用户
  4. 点击添加用户帐号。系统会打开将用户帐号添加到实例 instance_name 标签页。
  5. 点击 Cloud IAM 单选按钮。
  6. 成员字段中添加要添加的用户或服务帐号的电子邮件地址。
  7. 点击添加。该用户现在位于用户列表中。
  8. 如需授予用户登录权限,请点击 三角形 并选择添加 IAM 角色。此操作会将 Cloud SQL Instance User 角色分配给用户。

gcloud

创建用户帐号

使用电子邮件地址(如 test-user@gmail.com)来标识用户。

替换以下内容:

  • USERNAME:用户的电子邮件地址。
  • INSTANCE_NAME:您要向用户授予访问权限的实例的名称。
gcloud sql users create USERNAME \
--instance=INSTANCE_NAME \
--type=cloud_iam_user

创建服务帐号

替换以下内容:

  • SERVICE_ACCT:服务帐号的电子邮件地址。
  • INSTANCE_NAME:您要向服务帐号授予访问权限的实例的名称。
gcloud sql users create SERVICE_ACCT \
--instance=INSTANCE_NAME \
--type=cloud_iam_service_account

REST v1

创建用户帐号

在使用任何请求数据之前,请先进行以下替换:

  • project-id:您的项目 ID
  • instance-id:您要向其添加用户的实例的 ID
  • username:用户的电子邮件地址
  • operation-id:操作的 ID

HTTP 方法和网址:

POST https://sqladmin.googleapis.com/v1/projects/project-id/instances/instance-id/users

请求 JSON 正文:

{
  "name": "username",
  "type": "CLOUD_IAM_USER"
  }

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/v1/projects/project-id/instances/instance-id",
  "status": "DONE",
  "user": "user@example.com",
  "insertTime": "2020-02-07T22:44:16.656Z",
  "startTime": "2020-02-07T22:44:16.686Z",
  "endTime": "2020-02-07T22:44:20.437Z",
  "operationType": "CREATE_USER",
  "name": "operation-id",
  "targetId": "instance-id",
  "selfLink": "https://sqladmin.googleapis.com/v1/projects/project-id/operations/operation-id",
  "targetProject": "project-id"
}

创建服务帐号

在使用任何请求数据之前,请先进行以下替换:

  • service-acct:您的服务帐号电子邮件地址
  • project-id:您的项目 ID
  • instance-id:您要向其添加服务帐号的实例的 ID
  • operation-id:操作的 ID

HTTP 方法和网址:

POST https://sqladmin.googleapis.com/v1/projects/project-id/instances/instance-id/users

请求 JSON 正文:

{
    "name": "service-acct"
    "type": "CLOUD_IAM_SERVICE_ACCOUNT"
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
"kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/v1/projects/project-id/instances/instance-id",
  "status": "DONE",
  "user": "user@example.com",
  "insertTime": "2020-11-20T04:08:00.211Z",
  "startTime": "2020-11-20T04:08:00.240Z",
  "endTime": "2020-11-20T04:08:02.003Z",
  "operationType": "CREATE_USER",
  "name": "operation-id",
  "targetId": "instance-id",
  "selfLink": "https://sqladmin.googleapis.com/v1/projects/project-id/operations/operation-id",
  "targetProject": "project-id"
}

REST v1beta4

创建用户帐号

在使用任何请求数据之前,请先进行以下替换:

  • project-id:您的项目 ID
  • instance-id:您要向其添加用户的实例的 ID
  • username:用户的电子邮件地址
  • operation-id:操作的 ID

HTTP 方法和网址:

POST https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances/instance-id/users

请求 JSON 正文:

{
  "name": "username",
  "type": "CLOUD_IAM_USER"
  }

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances/instance-id",
  "status": "DONE",
  "user": "user@example.com",
  "insertTime": "2020-02-07T22:44:16.656Z",
  "startTime": "2020-02-07T22:44:16.686Z",
  "endTime": "2020-02-07T22:44:20.437Z",
  "operationType": "CREATE_USER",
  "name": "operation-id",
  "targetId": "instance-id",
  "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/operations/operation-id",
  "targetProject": "project-id"
}

创建服务帐号

在使用任何请求数据之前,请先进行以下替换:

  • service-acct:您的服务帐号电子邮件地址
  • project-id:您的项目 ID
  • instance-id:您要向其添加服务帐号的实例的 ID
  • operation-id:操作的 ID

HTTP 方法和网址:

POST https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances/instance-id/users

请求 JSON 正文:

{
    "name": "service-acct"
    "type": "CLOUD_IAM_SERVICE_ACCOUNT"
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
"kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances/instance-id",
  "status": "DONE",
  "user": "user@example.com",
  "insertTime": "2020-11-20T04:08:00.211Z",
  "startTime": "2020-11-20T04:08:00.240Z",
  "endTime": "2020-11-20T04:08:02.003Z",
  "operationType": "CREATE_USER",
  "name": "operation-id",
  "targetId": "instance-id",
  "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/operations/operation-id",
  "targetProject": "project-id"
}

向 IAM 用户授予数据库权限

默认情况下,将 IAM 用户添加到数据库实例时,该新用户不会对任何数据库授予权限。

用户或服务帐号连接到数据库时,可以针对已被授予 PUBLIC 访问权限的任何数据库对象运行查询。

如果他们需要其他访问权限,可以使用 GRANT 语句授予更多权限。如需查看您可以向用户和服务帐号授予的完整权限列表,请参阅 GRANT 参考页面。从命令行运行 GRANT。

替换以下内容:

  • USERNAME:用户的电子邮件地址。您必须使用英文引号括住电子邮件地址,因为它包含特殊字符(@.)。
  • TABLE_NAME:您要向用户授予访问权限的表的名称。
    grant select on TABLE_NAME to "USERNAME";
    

从数据库中移除 IAM 用户或服务帐号

要从数据库中移除用户或服务帐号,请从实例中删除该帐号:

控制台

  1. 在 Google Cloud Console 中,转到 Cloud SQL 实例页面。

    转到“Cloud SQL 实例”

  2. 点击实例名称,打开其概览页面。
  3. 从 SQL 导航菜单中选择用户
  4. 针对您要移除的用户,点击
  5. 选择移除。这样只会撤消对此实例的访问权限。

gcloud

撤消用户

使用电子邮件地址(如 test-user@gmail.com)来标识用户。

替换以下内容:

  • USERNAME:不带 @域名的电子邮件地址。
  • INSTANCE_NAME:您要从中移除用户的实例的名称。
gcloud sql users delete USERNAME \
--instance=INSTANCE_NAME

删除服务帐号

替换以下内容:

  • SERVICE_ACCT:服务帐号的电子邮件地址。
  • INSTANCE_NAME:您要从中移除用户的实例的名称。
gcloud sql users delete SERVICE_ACCT \
--instance=INSTANCE_NAME

REST v1beta4

以下请求使用 users:delete 方法删除指定的用户帐号。

在使用任何请求数据之前,请先进行以下替换:

  • project-id:您的项目 ID
  • instance-id:所需的实例 ID
  • username:用户或服务帐号的电子邮件地址

HTTP 方法和网址:

DELETE https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances/instance-id/users?host=&name=username

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances/instance-id",
  "status": "DONE",
  "user": "user@example.com",
  "insertTime": "2020-02-07T22:38:41.217Z",
  "startTime": "2020-02-07T22:38:41.217Z",
  "endTime": "2020-02-07T22:38:44.801Z",
  "operationType": "DELETE_USER",
  "name": "operation-id",
  "targetId": "instance-id",
  "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/operations/operation-id",
  "targetProject": "project-id"
}

在审核日志中查看登录信息

您可以启用审核日志以捕获对数据库的 IAM 登录。如果出现登录问题,您可以使用审核日志来诊断问题。

注意:Audit Logging 会产生额外费用。如需了解详情,请参阅日志记录数据的价格

配置后,您可以使用日志查看器查看成功登录的数据访问审核日志

例如,日志可能包含类似如下所示的信息:

{
 insertId: "..."
 logName: "projects/.../logs/cloudaudit.googleapis.com%2Fdata_access"
 protoPayload: {
  @type: "type.googleapis.com/google.cloud.audit.AuditLog"
  authenticationInfo: {
   principalEmail: "..."
  }
  authorizationInfo: [
   0: {
    granted: true
    permission: "cloudsql.instances.login"
    resource: "instances/..."
    resourceAttributes: {
    }
   }
  ]
  methodName: "cloudsql.instances.login"
  request: {
   @type: "type.googleapis.com/google.cloud.sql.authorization.v1.InstancesLoginRequest"
   clientIpAddress: "..."
   database: "..."
   databaseSessionId: ...
   instance: "projects/.../locations/us-central1/instances/..."
   user: "..."
  }
  requestMetadata: {
   callerIp: "..."
   destinationAttributes: {
   }
   requestAttributes: {
    auth: {
    }
    time: "..."
   }
  }
  resourceName: "instances/..."
  serviceName: "cloudsql.googleapis.com"
  status: {
  }
 }
 receiveTimestamp: "..."
 resource: {
  labels: {
   database_id: "...:..."
   project_id: "..."
   region: "us-central"
  }
  type: "cloudsql_database"
 }
 severity: "INFO"
 timestamp: "..."
}

排查登录失败问题

尝试登录失败时,出于安全考虑,PostgreSQL 会返回最少的错误消息。例如:

PGPASSWORD=not-a-password psql --host=... --username=... --dbname=...
psql: error: could not connect to server: FATAL:  Cloud SQL IAM user authentication failed for user "..."
FATAL:  pg_hba.conf rejects connection for host "...", user "...", database "...", SSL off

您可以查看 PostgreSQL 错误日志以详细了解错误。如需了解详情,请参阅查看日志

例如,对于前面的错误,以下日志条目说明了您可以执行来解决该问题的操作。

F ... [152172]: [1-1] db=...,user=... FATAL:  Cloud SQL IAM user authentication failed for user "..."
I ... [152172]: [2-1] db=...,user=... DETAIL:  Request is missing required authentication credential. Expected OAuth 2 access token, log in cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.

检查您收到的错误消息。如果消息未指明您使用的是“Cloud SQL IAM 用户身份验证”还是“Cloud SQL IAM 服务帐号身份验证”,请验证用于登录的数据库用户类型是 CLOUD_IAM_USERCLOUD_IAM_SERVICE_ACCOUNT。您可以使用 Cloud Console 或 gcloud sql users list 命令检查此项。对于 IAM 用户,验证数据库用户名是否为 IAM 用户的电子邮件地址。

如果您使用的是 IAM 数据库身份验证,请查看错误消息的详细信息。您可以在数据库错误日志中找到错误消息。如果消息指明您发送用作密码的访问令牌 (OAuth 2.0) 无效,您可以使用 gcloud auth application-default print-access-token gcloud 命令查找令牌的详细信息,如下所示:

curl -H "Content-Type: application/x-www-form-urlencoded" \
-d "access_token=$(gcloud auth application-default print-access-token)" \
https://www.googleapis.com/oauth2/v1/tokeninfo

验证该令牌适用于预期的 IAM 用户或服务帐号,并且未过期。

如果详细信息指明缺少权限,请验证已使用预定义的 Cloud SQL Instance User 角色或实例项目的 IAM 政策中的自定义角色为 IAM 用户或服务帐号授予了 cloudsql.instances.login 权限。如需其他帮助,请使用 IAM 政策问题排查工具

如果由于 IAM 数据库身份验证不可用而导致登录失败,则用户可以使用默认的 PostgreSQL 用户名和密码登录。这种登录方法仍可为用户提供整个数据库的访问权限。 验证连接是否为安全连接。

后续步骤