21.3. Participação em função de banco de dados #

Frequentemente é conveniente agrupar usuários para facilitar o gerenciamento de privilégios: dessa forma, os privilégios podem ser concedidos ou revogados para um grupo como um todo. No PostgreSQL isto é feito criando uma função de banco de dados (role) que representa o grupo e, em seguida, concedendo a participação de usuários individualmente nesta função de banco de dados de grupo, tornando-os membros dessa função de banco de dados.

Para definir uma função de banco de dados de grupo, primeiro é criada a função de banco de dados:

CREATE ROLE nome;

Normalmente, a função de banco de dados a ser utilizada como um grupo não possui o atributo LOGIN definido, embora se possa defini-lo se assim desejar.

Após a função de banco de dados de grupo ter sido criada, será possível adicionar e remover membros usando os comandos GRANT e REVOKE:

GRANT nome_da_role_de_grupo TO role1, ... ;
REVOKE nome_da_role_de_grupo FROM role1, ... ;

Também pode ser concedida participação a outras funções de banco de dados de grupo (já que não existe realmente nenhuma distinção entre funções de banco de dados de grupo e funções de banco de dados que não são de grupo). O banco de dados não permitirá que se configure laços de participação circulares. Além disso, não é permitido conceder participação em uma função de banco de dados para PUBLIC.

Os membros de uma função de banco de dados de grupo podem utilizar os privilégios da função de banco de dados de duas maneiras. Primeiro, as funções de banco de dados membro às quais foi concedida a participação com a opção SET podem executar SET ROLE para se tornarem temporariamente a função de banco de dados de grupo. Neste estado, a sessão de banco de dados tem acesso aos privilégios da função de banco de dados de grupo, em vez da função de banco de dados da conexão original, e quaisquer objetos de banco de dados criados são considerados de propriedade da função de banco de dados de grupo, e não da função de banco de dados da conexão. Em segundo lugar, as funções de banco de dados membro às quais foi concedida a participação com a opção INHERIT herdam automaticamente os privilégios das funções de banco de dados das quais são membros (direta ou indiretamente), embora a cadeia seja interrompida em participações que não possuam a opção de herança. Como exemplo, supondo que tenha sido executado:

CREATE ROLE joe LOGIN;
CREATE ROLE admin;
CREATE ROLE wheel;
CREATE ROLE island;
GRANT admin TO joe WITH INHERIT TRUE;
GRANT wheel TO admin WITH INHERIT FALSE;
GRANT island TO joe WITH INHERIT TRUE, SET FALSE;

Imediatamente após conectar-se como a função de banco de dados joe, a sessão de banco de dados terá acesso aos privilégios concedidos diretamente a joe, mais quaisquer privilégios concedidos a admin e island, porque joe herda estes privilégios. Entretanto, os privilégios concedidos à wheel não estão disponíveis, porque embora joe seja indiretamente membro de wheel, a participação é feita via admin, que foi concedida usando WITH INHERIT FALSE. Após

SET ROLE admin;

a sessão utilizaria apenas os privilégios concedidos a admin, e não aqueles concedidos a joe ou island. Após

SET ROLE wheel;

a sessão teria acesso apenas aos privilégios concedidos a wheel, e não aqueles concedidos a joe ou a admin. O estado inicial de privilégios pode ser restaurado por qualquer um dos seguintes comandos:

SET ROLE joe;
SET ROLE NONE;
RESET ROLE;

Nota

O comando SET ROLE sempre permite selecionar qualquer função de banco de dados da qual a função de banco de dados da conexão original seja membro direta ou indiretamente, desde que exista uma cadeia de associação de concessões em que cada uma delas tenha SET TRUE (que é o padrão). Assim, no exemplo acima, não é necessário tornar-se admin antes de tornar-se wheel. Por outro lado, não é possível tornar-se island de forma alguma; joe só pode acessar estes privilégios por meio de herança.

Nota

No padrão SQL há uma distinção clara entre usuários e funções de banco de dados, e os usuários não herdam privilégios automaticamente, enquanto as funções de banco de dados sim. Este comportamento pode ser emulado no PostgreSQL atribuindo às funções de banco de dados sendo usadas como funções de banco de dados do SQL o atributo INHERIT, enquanto dando às funções de banco de dados que estão sendo usadas como usuários do SQL o atributo NOINHERIT. Entretanto, o padrão do PostgreSQL é dar a todas as funções de banco de dados o atributo INHERIT, para manter a compatibilidade com as versões anteriores à versão 8.1, nas quais os usuários sempre tiveram acesso às permissões concedidas a grupos dos quais eram membros.

Os atributos de função de banco de dados LOGIN, SUPERUSER, CREATEDB e CREATEROLE podem ser vistos como privilégios especiais, mas nunca são herdados como privilégios comuns em objetos de banco de dados. Na verdade, é necessário usar SET ROLE para uma função de banco de dados específica com um desses atributos para poder usar o atributo. Continuando o exemplo acima, pode-se optar por conceder CREATEDB e CREATEROLE para a função de banco de dados admin. Então uma sessão conectando como a função de banco de dados joe não teria estes privilégios imediatamente, somente após executar SET ROLE admin.

Para remover uma função de banco de dados de grupo, é usado o comando DROP ROLE:

DROP ROLE nome_da_role_de_grupo;

Quaisquer participações na função de banco de dados de grupo são revogadas automaticamente (mas as funções de banco de dados dos membros não são afetadas de outra forma).