Controle de acesso granular para filas

Nesta página, explicamos como o controle de acesso refinado funciona com filas do Spanner para bancos de dados com dialeto GoogleSQL e PostgreSQL.

No Spanner, uma fila é definida como um objeto de esquema. O acesso para enviar mensagens, receber mensagens, estender concessões de mensagens, confirmar e excluir mensagens ou consultar filas diretamente está em conformidade com as funções e os privilégios padrão do banco de dados do Spanner.

Concessões para enviar mensagens (produtores)

Para enviar mensagens a uma fila usando DML (INSERT INTO) ou a API Mutation (consulte Instrução INSERT), conceda o privilégio INSERT na fila à função do banco de dados:

GoogleSQL

GRANT INSERT ON QUEUE QUEUE_NAME TO ROLE ROLE_NAME;

PostgreSQL

GRANT INSERT ON QUEUE QUEUE_NAME TO ROLE_NAME;

Para revogar o privilégio:

GoogleSQL

REVOKE INSERT ON QUEUE QUEUE_NAME FROM ROLE ROLE_NAME;

PostgreSQL

REVOKE INSERT ON QUEUE QUEUE_NAME FROM ROLE_NAME;

Concessões para receber mensagens (consumidores)

Para transmitir mensagens de uma fila, os workers consumidores executam a função com valor de tabela (TVF) RECEIVE_QUEUE_NAME() com ExecuteStreamingSQL.

Para permitir que uma função de banco de dados transmita mensagens da fila, conceda EXECUTE na função RECEIVE_QUEUE_NAME criada automaticamente:

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;

Para revogar o privilégio:

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;

Para chamar RECEIVE_QUEUE_NAME(), é necessário apenas EXECUTE na TVF, não SELECT na fila.

Estender concessões de mensagens

Quando um consumidor recebe uma mensagem, o Spanner atribui um lease inicial de 10 segundos. Se o processamento da mensagem levar mais tempo do que a concessão inicial, o consumidor precisará estender a concessão usando a TVF RENEWLEASE_QUEUE_NAME().

Para estender concessões, o papel precisa ter EXECUTE na função RENEWLEASE_QUEUE_NAME:

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;

Para revogar o privilégio:

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;

Para chamar RENEWLEASE_QUEUE_NAME(), é necessário apenas EXECUTE no TVF, não SELECT na fila.

Para mais informações sobre como receber mensagens e estender concessões, consulte Usar filas.

Concessões para consultar filas diretamente

Para ler ou inspecionar mensagens diretamente de uma fila usando o SQL padrão (SELECT * FROM QUEUE_NAME) ou a API Read, conceda o privilégio SELECT na fila:

GoogleSQL

GRANT SELECT ON QUEUE QUEUE_NAME TO ROLE ROLE_NAME;

PostgreSQL

GRANT SELECT ON QUEUE QUEUE_NAME TO ROLE_NAME;

Para revogar o privilégio:

GoogleSQL

REVOKE SELECT ON QUEUE QUEUE_NAME FROM ROLE ROLE_NAME;

PostgreSQL

REVOKE SELECT ON QUEUE QUEUE_NAME FROM ROLE_NAME;

Conceder SELECT na fila permite consultá-la como uma tabela, mas não concede EXECUTE em RECEIVE_QUEUE_NAME() ou RENEWLEASE_QUEUE_NAME().

Concessões para confirmar e excluir mensagens

Para confirmar ou excluir mensagens de uma fila usando DML (DELETE FROM) ou a API Mutation (Ack ou Delete), conceda o privilégio DELETE na fila:

GoogleSQL

GRANT DELETE ON QUEUE QUEUE_NAME TO ROLE ROLE_NAME;

PostgreSQL

GRANT DELETE ON QUEUE QUEUE_NAME TO ROLE_NAME;

Para revogar o privilégio:

GoogleSQL

REVOKE DELETE ON QUEUE QUEUE_NAME FROM ROLE ROLE_NAME;

PostgreSQL

REVOKE DELETE ON QUEUE QUEUE_NAME FROM ROLE_NAME;

Privilégios necessários para operações de fila

A tabela a seguir resume os privilégios necessários para operações comuns de fila:

Operação Privilégios necessários
Enviar mensagens (DML INSERT ou API Mutation Send) INSERT na fila
Receber mensagens (RECEIVE_QUEUE_NAME() TVF) EXECUTE na função RECEIVE_QUEUE_NAME
Estender concessão de mensagem (TVF RENEWLEASE_QUEUE_NAME()) EXECUTE na função RENEWLEASE_QUEUE_NAME
Confirmar ou excluir mensagens (DML DELETE ou API Mutation Ack ou Delete) DELETE na fila
Ler dados da fila diretamente (SQL SELECT ou API Read) SELECT na fila

Exemplo: configurar funções de produtor e consumidor

O exemplo a seguir configura papéis de banco de dados separados para um produtor, um consumidor e um auditor em uma fila chamada 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 visualizações para filas

As visualizações a seguir mostram informações sobre papéis e privilégios de banco de dados para filas:

Como o Spanner modela filas como objetos de esquema no nível da tabela, os privilégios concedidos a elas aparecem em TABLE_PRIVILEGES. Os privilégios concedidos em funções com valor de tabela de fila aparecem em ROUTINE_PRIVILEGES.

As linhas nessas visualizações são filtradas com base nos privilégios da função do banco de dados atual. Isso garante que os participantes possam ver apenas os papéis, privilégios e filas a que têm acesso.

A filtragem de linhas também se aplica às seguintes visualizações de metadados da fila:

GoogleSQL

  • INFORMATION_SCHEMA.TABLES
  • INFORMATION_SCHEMA.COLUMNS

PostgreSQL

  • information_schema.tables
  • information_schema.columns

A filtragem de linhas também se aplica às visualizações de metadados para funções de tabela de fila (RECEIVE_QUEUE_NAME e RENEWLEASE_QUEUE_NAME):

A função do sistema spanner_info_reader e os membros dela sempre veem um INFORMATION_SCHEMA sem filtro.

Advertências e considerações

  • Privilégios distintos para execução de TVF e consultas diretas de fila: conceder SELECT na fila não concede EXECUTE nas funções com valor de tabela (RECEIVE_QUEUE_NAME ou RENEWLEASE_QUEUE_NAME) associadas. Da mesma forma, conceder EXECUTE na TVF não concede SELECT na fila.

    • Se uma função com apenas SELECT na fila tentar executar RECEIVE_QUEUE_NAME(), o Spanner vai retornar um erro informando que a função não tem os privilégios necessários na função de tabela RECEIVE_QUEUE_NAME.
    • Se uma função com apenas EXECUTE na TVF tentar executar SELECT * FROM QUEUE_NAME, o Spanner vai retornar um erro informando que a função não tem os privilégios necessários na fila QUEUE_NAME.
  • Diferença dos fluxos de alterações: ao contrário dos fluxos de alterações (que exigem SELECT no fluxo e EXECUTE na função de leitura), os consumidores de mensagens da fila exigem apenas EXECUTE na TVF RECEIVE. Elas não exigem SELECT na própria fila.

  • Privilégios no nível da coluna não são compatíveis: ao contrário das tabelas, o Spanner não oferece suporte a privilégios no nível da coluna em filas (como GRANT SELECT (COLUMN_NAME) ON QUEUE). Os privilégios precisam ser concedidos no objeto de fila como um todo porque as filas incluem colunas de metadados internos do sistema.

  • Separação das funções de produtor e consumidor: recomendamos definir funções de banco de dados separadas para produtores e consumidores de mensagens. Exemplo:

    • Uma função de produtor com apenas INSERT na fila.
    • Uma função de consumidor com EXECUTE nas funções RECEIVE_QUEUE_NAME e RENEWLEASE_QUEUE_NAME, além de DELETE na fila, se o reconhecimento de mensagens for feito com DELETE ou a mutação Ack.
  • DML direta x entrega de TVF de fila: as instruções DELETE ou UPDATE diretas ignoram a máquina de estado de concessão e entrega da fila. Recomendamos restringir esses privilégios a funções administrativas ou de manutenção.

A seguir