队列的精细访问权限控制

本页面介绍了精细访问权限控制如何与 GoogleSQL 方言数据库和 PostgreSQL 方言数据库的 Spanner 队列配合使用。

在 Spanner 中,队列被定义为一种架构对象。发送消息、接收消息、延长消息租约、确认和删除消息或直接查询队列的访问权限符合标准的 Spanner 数据库角色和权限。

授予发送消息的权限(生产者)

如需使用 DML (INSERT INTO) 或 Mutation API(请参阅插入语句)向队列发送消息,请向数据库角色授予队列的 INSERT 权限:

GoogleSQL

GRANT INSERT ON QUEUE QUEUE_NAME TO ROLE ROLE_NAME;

PostgreSQL

GRANT INSERT ON QUEUE QUEUE_NAME TO ROLE_NAME;

如需撤消此权限,请执行以下操作:

GoogleSQL

REVOKE INSERT ON QUEUE QUEUE_NAME FROM ROLE ROLE_NAME;

PostgreSQL

REVOKE INSERT ON QUEUE QUEUE_NAME FROM ROLE_NAME;

接收消息的授权(消费者)

为了从队列中流式传输消息,消费者工作器会使用 ExecuteStreamingSQL 执行 RECEIVE_QUEUE_NAME() 表值函数 (TVF)。

如需允许数据库角色从队列中流式传输消息,请针对自动创建的 RECEIVE_QUEUE_NAME 函数授予 EXECUTE 权限:

GoogleSQL

GRANT EXECUTE ON TABLE FUNCTION RECEIVE_QUEUE_NAME TO ROLE ROLE_NAME;

PostgreSQL

GRANT EXECUTE ON FUNCTION spanner.receive_QUEUE_NAME TO ROLE_NAME;

如需撤消此权限,请执行以下操作:

GoogleSQL

REVOKE EXECUTE ON TABLE FUNCTION RECEIVE_QUEUE_NAME FROM ROLE ROLE_NAME;

PostgreSQL

REVOKE EXECUTE ON FUNCTION spanner.receive_QUEUE_NAME FROM ROLE_NAME;

在 TVF 上调用 RECEIVE_QUEUE_NAME() 仅需要 EXECUTE;不需要在队列上调用 SELECT

延长消息租约

当消费者收到消息时,Spanner 会分配一个初始的 10 秒租约。如果消息处理时间超过初始租期,消费者必须使用 RENEWLEASE_QUEUE_NAME() TVF 延长租期。

如需延长租期,该角色必须对 RENEWLEASE_QUEUE_NAME 函数具有 EXECUTE 权限:

GoogleSQL

GRANT EXECUTE ON TABLE FUNCTION RENEWLEASE_QUEUE_NAME TO ROLE ROLE_NAME;

PostgreSQL

GRANT EXECUTE ON FUNCTION spanner.renew_lease_QUEUE_NAME TO ROLE_NAME;

如需撤消此权限,请执行以下操作:

GoogleSQL

REVOKE EXECUTE ON TABLE FUNCTION RENEWLEASE_QUEUE_NAME FROM ROLE ROLE_NAME;

PostgreSQL

REVOKE EXECUTE ON FUNCTION spanner.renewlease_QUEUE_NAME FROM ROLE_NAME;

调用 RENEWLEASE_QUEUE_NAME() 仅需要 TVF 上的 EXECUTE;不需要队列上的 SELECT

如需详细了解如何接收消息和延长租期,请参阅使用队列

直接查询队列的授权

如需使用标准 SQL (SELECT * FROM QUEUE_NAME) 或 Read API 直接从队列中读取或检查消息,请授予队列 SELECT 权限:

GoogleSQL

GRANT SELECT ON QUEUE QUEUE_NAME TO ROLE ROLE_NAME;

PostgreSQL

GRANT SELECT ON QUEUE QUEUE_NAME TO ROLE_NAME;

如需撤消此权限,请执行以下操作:

GoogleSQL

REVOKE SELECT ON QUEUE QUEUE_NAME FROM ROLE ROLE_NAME;

PostgreSQL

REVOKE SELECT ON QUEUE QUEUE_NAME FROM ROLE_NAME;

授予队列的 SELECT 权限允许将队列作为表进行查询,但不会授予 RECEIVE_QUEUE_NAME()RENEWLEASE_QUEUE_NAME()EXECUTE 权限。

用于确认和删除消息的授权

如需使用 DML (DELETE FROM) 或 Mutation API(AckDelete)确认或删除队列中的消息,请授予对该队列的 DELETE 权限:

GoogleSQL

GRANT DELETE ON QUEUE QUEUE_NAME TO ROLE ROLE_NAME;

PostgreSQL

GRANT DELETE ON QUEUE QUEUE_NAME TO ROLE_NAME;

如需撤消此权限,请执行以下操作:

GoogleSQL

REVOKE DELETE ON QUEUE QUEUE_NAME FROM ROLE ROLE_NAME;

PostgreSQL

REVOKE DELETE ON QUEUE QUEUE_NAME FROM ROLE_NAME;

队列操作所需的权限

下表总结了常见队列操作所需的权限:

操作 所需的权限
发送消息(DML INSERT 或 Mutation API Send 队列中的 INSERT
接收消息 (RECEIVE_QUEUE_NAME() TVF) RECEIVE_QUEUE_NAME 函数的 EXECUTE
延长消息租约(RENEWLEASE_QUEUE_NAME() TVF) RENEWLEASE_QUEUE_NAME 函数的 EXECUTE
确认或删除消息(DML DELETE 或 Mutation API AckDelete 队列中的 DELETE
直接读取队列数据(SQL SELECT 或 Read API) 队列中的 SELECT

示例:配置生产者和消费者角色

以下示例针对名为 OrdersQueue 的队列,为生产者、消费者和审核员分别配置了数据库角色:

GoogleSQL

-- Create producer role and grant send permissions
CREATE ROLE queue_producer;
GRANT INSERT ON QUEUE OrdersQueue TO ROLE queue_producer;

-- Create consumer role and grant receive, renew, and delete permissions
CREATE ROLE queue_consumer;
GRANT EXECUTE ON TABLE FUNCTION RECEIVE_OrdersQueue TO ROLE queue_consumer;
GRANT EXECUTE ON TABLE FUNCTION RENEWLEASE_OrdersQueue TO ROLE queue_consumer;
GRANT DELETE ON QUEUE OrdersQueue TO ROLE queue_consumer;

-- Create reader role for inspection without consumer streaming permissions
CREATE ROLE queue_reader;
GRANT SELECT ON QUEUE OrdersQueue TO ROLE queue_reader;

PostgreSQL

-- Create producer role and grant send permissions
CREATE ROLE queue_producer;
GRANT INSERT ON QUEUE OrdersQueue TO queue_producer;

-- Create consumer role and grant receive, renew, and delete permissions
CREATE ROLE queue_consumer;
GRANT EXECUTE ON FUNCTION spanner.receive_OrdersQueue TO queue_consumer;
GRANT EXECUTE ON FUNCTION spanner.renewlease_OrdersQueue TO queue_consumer;
GRANT DELETE ON QUEUE OrdersQueue TO queue_consumer;

-- Create reader role for inspection without consumer streaming permissions
CREATE ROLE queue_reader;
GRANT SELECT ON QUEUE OrdersQueue TO queue_reader;

队列的 INFORMATION_SCHEMA 视图

以下视图显示了队列的数据库角色和权限信息:

由于 Spanner 将队列建模为表级架构对象,因此在队列上授予的权限会显示在 TABLE_PRIVILEGES 中。授予队列表值函数的权限显示在 ROUTINE_PRIVILEGES 中。

这些视图中的行会根据当前数据库角色的权限进行过滤。这样可确保主账号只能查看其有权访问的角色、权限和队列。

行过滤还适用于以下队列元数据视图:

GoogleSQL

  • INFORMATION_SCHEMA.TABLES
  • INFORMATION_SCHEMA.COLUMNS

PostgreSQL

  • information_schema.tables
  • information_schema.columns

行过滤还适用于队列表值函数的元数据视图(RECEIVE_QUEUE_NAMERENEWLEASE_QUEUE_NAME):

系统角色 spanner_info_reader 及其成员始终会看到未经过滤的 INFORMATION_SCHEMA

注意事项和考虑因素

  • TVF 执行和直接队列查询的权限各不相同:授予队列的 SELECT 权限不会授予关联的表值函数(RECEIVE_QUEUE_NAMERENEWLEASE_QUEUE_NAME)的 EXECUTE 权限。同样,授予 TVF 的 EXECUTE 权限不会授予队列的 SELECT 权限。

    • 如果队列中只有 SELECT 的角色尝试执行 RECEIVE_QUEUE_NAME(),Spanner 会返回一条错误,指出该角色对表函数 RECEIVE_QUEUE_NAME 没有必需的权限。
    • 如果仅具有 TVF 上的 EXECUTE 权限的角色尝试运行 SELECT * FROM QUEUE_NAME,Spanner 会返回一条错误,指出该角色在队列 QUEUE_NAME 上没有所需的权限。
  • 与变更数据流的区别:与变更数据流(需要在数据流上设置 SELECT,在读取函数上设置 EXECUTE)不同,队列消息的使用者只需要在 RECEIVE TVF 上设置 EXECUTE。它们不需要队列本身具有 SELECT

  • 不支持列级权限:与表不同,Spanner 不支持对队列(例如 GRANT SELECT (COLUMN_NAME) ON QUEUE)设置列级权限。必须对整个队列对象授予权限,因为队列包含内部系统元数据列。

  • 分离生产者和消费者角色:建议为消息生产者和消息消费者定义单独的数据库角色。例如:

    • 队列上只有 INSERT 的提供方角色。
    • RECEIVE_QUEUE_NAMERENEWLEASE_QUEUE_NAME 函数中具有 EXECUTE 的消费者角色,如果使用 DELETEAck 突变确认消息,则在队列中具有 DELETE
  • 直接 DML 与队列 TVF 传送:直接 DELETEUPDATE 语句会绕过队列租用和传送状态机。建议仅向管理或维护角色授予这些权限。

后续步骤