CREATE POLICY — define uma nova política de segurança no nível de linha para uma tabela
CREATE POLICYnomeONnome_da_tabela[ AS { PERMISSIVE | RESTRICTIVE } ] [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ] [ TO {nome_da_role| PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ] [ USING (expressão_USING) ] [ WITH CHECK (expressão_CHECK) ]
O comando CREATE POLICY define uma nova política
de segurança no nível de linha para uma tabela.
Note que a segurança no nível de linha deve ser ativada na tabela
(usando ALTER TABLE ... ENABLE ROW LEVEL SECURITY)
para que as políticas criadas sejam aplicadas.
Uma política concede permissão para selecionar, inserir, atualizar
ou excluir linhas que correspondam à expressão de política relevante.
As linhas existentes da tabela são verificadas em relação à expressão
especificada em USING, enquanto as novas linhas
a serem criadas via INSERT ou
UPDATE são verificadas em relação à expressão
especificada em WITH CHECK.
Quando a expressão USING retorna verdade para
uma determinada linha, esta linha fica visível para o usuário,
enquanto se retornar falso ou nulo, a linha não ficará visível.
Quando uma expressão WITH CHECK retorna verdade
para uma linha, esta linha é inserida ou atualizada, enquanto se
retornar falso ou nulo, ocorrerá um erro.
Para os comandos INSERT, UPDATE
e MERGE as expressões WITH CHECK
são aplicadas depois que os gatilhos BEFORE são
disparados, e antes que quaisquer modificações de dados reais sejam
feitas.
Assim, um gatilho BEFORE ROW pode modificar os
dados a serem inseridos, afetando o resultado da verificação da
política de segurança.
As expressões WITH CHECK são impostas antes
de qualquer outra restrição.
Os nomes das políticas são por tabela. Portanto, o mesmo nome de política pode ser usado para muitas tabelas diferentes, e ter uma definição apropriada para cada tabela.
As políticas podem ser aplicadas para comandos específicos ou para funções de banco de dados (identificadores de autorização/roles) específicas. O padrão para políticas recém-criadas é que as mesmas se aplicam a todos os comandos e funções de banco de dados, a menos que seja especificado de outra forma. Podem ser aplicadas várias políticas a um único comando; veja abaixo para obter mais detalhes. A Tabela 300 resume como os diferentes tipos de política se aplicam a comandos específicos.
Para as políticas que podem ter as duas expressões
USING e WITH CHECK
(ALL e UPDATE),
se não for definida nenhuma expressão WITH CHECK,
então a expressão USING será usada para determinar
quais linhas são visíveis (modo USING normal),
e quais novas linhas poderão ser adicionadas
(modo WITH CHECK).
Se a segurança no nível de linha estiver ativada para uma tabela, mas não existir nenhuma política aplicável, será assumida a política de “negação padrão”, para que nenhuma linha fique visível ou atualizável.
nomeO nome da política a ser criada. Deve ser diferente do nome de qualquer outra política para a tabela.
nome_da_tabelaO nome (opcionalmente qualificado pelo esquema) da tabela à qual a política se aplica.
PERMISSIVEEspecifica que a política deve ser criada como uma política permissiva. Todas as políticas permissivas aplicáveis a uma determinada consulta são combinadas usando o operador booleano “OR”. Ao criar políticas permissivas, os administradores podem ampliar o conjunto de registros que podem ser acessados. As políticas são permissivas por padrão.
RESTRICTIVEEspecifica que a política deve ser criada como uma política restritiva. Todas as políticas restritivas aplicáveis a uma determinada consulta serão combinadas usando o operador booleano “AND”. Ao criar políticas restritivas, os administradores podem reduzir o conjunto de registros que podem ser acessados, porque todas as políticas restritivas devem ser aprovadas para cada registro.
Note que deve haver pelo menos uma política permissiva para conceder acesso aos registros antes que as políticas restritivas possam ser usadas de forma útil para reduzir este acesso. Se existirem apenas políticas restritivas, nenhum registro estará acessível. Quando há uma mistura de políticas permissivas e restritivas, o registro só será acessível se pelo menos uma das políticas permissivas for aprovada, além de todas as políticas restritivas.
comando
O comando ao qual a política se aplica.
As opções válidas são
ALL, SELECT,
INSERT, UPDATE,
e DELETE.
ALL é o padrão.
Veja abaixo os detalhes sobre como são aplicadas.
nome_da_role
As funções de banco de dados (roles)
às quais a política deve ser aplicada.
O padrão é PUBLIC, que aplicará a política
a todas as funções de banco de dados.
expressão_USING
Qualquer expressão SQL condicional
(retornando boolean).
A expressão condicional não pode conter nenhuma função de
agregação ou de janela.
Esta expressão será adicionada às consultas que se referem
à tabela, se a segurança no nível de linha estiver ativada.
As linhas para as quais a expressão retorna verdade ficarão visíveis.
Quaisquer linhas para as quais a expressão retorne falso ou nulo
não serão visíveis para o usuário (no SELECT),
e não estarão disponível para modificação
(no UPDATE ou DELETE).
Estas linhas são suprimidas silenciosamente; nenhum erro é relatado.
expressão_CHECK
Qualquer expressão SQL condicional
(retornando boolean).
A expressão condicional não pode conter nenhuma função de
agregação ou de janela.
Esta expressão será usada em consultas INSERT
e UPDATE na tabela, se a segurança no nível
de linha estiver ativada.
Somente as linhas para as quais a expressão é avaliada como
verdade serão permitidas.
Será relatado um erro se a expressão for avaliada como falso ou
nulo para qualquer um dos registros inseridos, ou qualquer um dos
registros resultantes da atualização.
Note que a
expressão_CHECK
é avaliada em relação ao novo conteúdo proposto para a linha,
e não ao conteúdo original.
ALL #
Usar ALL para uma política significa que
esta será aplicada a todos os comandos, independentemente do
tipo de comando.
Se existir uma política ALL e políticas mais
específicas, tanto a política ALL quanto a
política (ou políticas) mais específica serão aplicadas.
Além disso, as políticas ALL serão aplicadas
tanto no lado da seleção de uma consulta, quanto no lado da
modificação, usando a expressão USING para
os dois casos se apenas a expressão USING
tiver sido definida.
Como exemplo, se for executado um UPDATE,
então a política ALL será aplicável tanto
nas linhas que o comando UPDATE poderá
selecionar para serem atualizadas
(aplicando a expressão USING),
quanto nas linhas atualizadas resultantes, para verificar se
estas podem ser adicionadas à tabela (caso contrário, aplicando
a expressão WITH CHECK, se definida, e a
expressão USING).
Se o comando INSERT ou UPDATE
tentar adicionar linhas à tabela que não passam pela expressão
WITH CHECK da política ALL,
todo o comando será interrompido.
SELECT #
Usar SELECT para uma política significa que
ela será aplicada a consultas SELECT,
e sempre que as permissões SELECT forem
necessárias na relação para a qual a política foi definida.
O resultado é que apenas os registros da relação que passam
pela política SELECT serão retornados
durante uma consulta SELECT, e que os
comandos que exigem permissões SELECT,
como UPDATE, também verão apenas os
registros permitidos pela política SELECT.
Uma política SELECT não pode ter uma
expressão WITH CHECK, porque ela só se
aplica nos casos em que os registros estão sendo obtidos
da relação.
INSERT #
Para uma política, usar INSERT significa que
ela será aplicada aos comandos INSERT e
MERGE contendo ações INSERT.
As linhas inseridas que não forem aprovadas por esta política
resultarão em erro de violação de política, e todo o comando
INSERT será interrompido.
Uma política INSERT não pode ter uma
expressão USING, porque ela só se aplica
nos casos em que registros estão sendo adicionados à relação.
Note que INSERT com a cláusula
ON CONFLICT DO UPDATE verifica as expressões
WITH CHECK das políticas
INSERT apenas para as linhas adicionadas
à relação pelo caminho INSERT.
UPDATE #
Usar UPDATE para uma política significa que
esta se aplicará aos comandos UPDATE,
SELECT FOR UPDATE e
SELECT FOR SHARE, assim bem como cláusulas
auxiliares ON CONFLICT DO UPDATE de comandos
INSERT.
Os comandos MERGE contendo ações
UPDATE também são afetados.
Uma vez que o comando UPDATE envolve extrair
um registro existente e substituí-lo por um novo registro
modificado, as políticas UPDATE aceitam uma
expressão USING e uma expressão
WITH CHECK.
A expressão USING determina quais registros
o comando UPDATE terá acesso para operar,
enquanto a expressão WITH CHECK define quais
linhas modificadas poderão ser armazenadas de volta na relação.
Qualquer linha cujos valores atualizados não sejam aprovados
pela expressão WITH CHECK causará um erro,
e todo o comando será interrompido.
Se for especificada apenas a cláusula USING,
então esta cláusula será usada para os casos
USING e WITH CHECK.
Normalmente, um comando UPDATE também precisa
ler dados de colunas na relação que está sendo atualizada
(por exemplo, em uma cláusula WHERE ou uma
cláusula RETURNING, ou em uma expressão
no lado direito da cláusula SET).
Neste caso, os direitos para SELECT também
são necessários na relação que está sendo atualizada, e as
políticas SELECT ou ALL
apropriadas serão aplicadas além das políticas
UPDATE.
Assim, o usuário deve ter acesso à(s) linha(s) sendo
atualizada(s) por meio de uma política SELECT
ou ALL, além de receber permissão para
atualizar a(s) linha(s) por meio de uma política
UPDATE ou ALL.
Quando o comando INSERT tem uma cláusula
auxiliar ON CONFLICT DO UPDATE, se for usado
o caminho UPDATE, a linha a ser atualizada
é primeiro verificada em relação às expressões
USING de qualquer política
UPDATE e, em seguida, a nova linha
atualizada é verificada em relação às expressões
WITH CHECK.
Note, no entanto, que, ao contrário de um comando
UPDATE autônomo, se a linha existente não
for aprovada pelas expressões USING,
será relatado um erro (o caminho UPDATE
nunca será evitado silenciosamente).
DELETE #
Usar DELETE para uma política significa que
esta será aplicada aos comandos DELETE.
Apenas as linhas que forem aprovadas por esta política serão
vistas por um comando DELETE.
Pode haver linhas visíveis por meio do SELECT
que não estarão disponíveis para exclusão, se as mesmas não
forem aprovadas pela expressão USING da
política DELETE.
Geralmente, o comando DELETE também
precisa ler dados de colunas na relação que está excluindo
(por exemplo, em uma cláusula WHERE ou uma
cláusula RETURNING).
Neste caso, também são necessários os direitos
SELECT na relação, e as políticas
SELECT ou ALL apropriadas
serão aplicadas além das políticas DELETE.
Assim, o usuário deve ter acesso à(s) linha(s) que está(ão)
sendo excluída(s) por meio de uma política
SELECT ou ALL, além de
receber permissão para excluir a(s) linha(s) por meio de uma
política DELETE ou ALL.
A política DELETE não pode ter uma expressão
WITH CHECK, porque ela só se aplica nos
casos em que os registros estão sendo excluídos da relação,
de modo que não há nenhuma nova linha a ser verificada.
Tabela 300. Políticas aplicadas por tipo de comando
| Comando | SELECT/ALL política | INSERT/ALL política | UPDATE/ALL política | DELETE/ALL política | |
|---|---|---|---|---|---|
USING expressão | WITH CHECK expressão | USING expressão | WITH CHECK expressão | USING expressão | |
SELECT | Linha existente | — | — | — | — |
SELECT FOR UPDATE/SHARE | Linha existente | — | Linha existente | — | — |
INSERT / MERGE ... THEN INSERT | — | Nova linha | — | — | — |
INSERT ... RETURNING | Nova linha [a] | Nova linha | — | — | — |
UPDATE / MERGE ... THEN UPDATE | Existente & novas linhas [a] | — | Linha existente | Nova linha | — |
DELETE | Linha existente [a] | — | — | — | Linha existente |
ON CONFLICT DO UPDATE | Existente & novas linhas | — | Linha existente | Nova linha | — |
[a]
Se for necessário o acesso de leitura para a linha existente
ou nova (por exemplo, uma cláusula | |||||
Quando várias políticas de diferentes tipos de comando se aplicam
ao mesmo comando (por exemplo, políticas SELECT
e UPDATE aplicadas a um comando
UPDATE), então o usuário deverá ter os dois tipos
de permissão (por exemplo, permissão para selecionar linhas da
relação, bem como permissão para atualizá-las).
Assim, as expressões para um tipo de política são combinadas com as
expressões para o outro tipo de política usando o operador
AND.
Quando várias políticas do mesmo tipo de comando se aplicam ao mesmo
comando, deve haver pelo menos uma política
PERMISSIVE concedendo acesso à relação,
e todas as políticas RESTRICTIVE devem ser
aprovadas.
Assim, todas as expressões de política PERMISSIVE
são combinadas usando OR, todas as expressões
de política RESTRICTIVE são combinadas usando
AND, e os resultados são combinados usando
AND.
Se não houver políticas PERMISSIVE, o acesso
será negado.
Note que, para fins de combinação de várias políticas, as políticas
ALL são tratadas como tendo o mesmo tipo de
qualquer outro tipo de política que esteja sendo aplicada.
Por exemplo, em um comando UPDATE que requer as
permissões SELECT e UPDATE,
se houver várias políticas aplicáveis de cada tipo, estas serão
combinadas como mostrado a seguir:
expressãofrom RESTRICTIVE SELECT/ALL política 1 ANDexpressãofrom RESTRICTIVE SELECT/ALL política 2 AND ... AND (expressãofrom PERMISSIVE SELECT/ALL política 1 ORexpressãofrom PERMISSIVE SELECT/ALL política 2 OR ... ) ANDexpressãofrom RESTRICTIVE UPDATE/ALL política 1 ANDexpressãofrom RESTRICTIVE UPDATE/ALL política 2 AND ... AND (expressãofrom PERMISSIVE UPDATE/ALL política 1 ORexpressãofrom PERMISSIVE UPDATE/ALL política 2 OR ... )
É necessário ser o dono da tabela para criar ou alterar políticas para ela.
Embora as políticas sejam aplicadas para consultas explícitas em tabelas no banco de dados, elas não são aplicadas quando o sistema está executando verificações internas de integridade referencial ou validando restrições. Isto significa que existem maneiras indiretas de determinar a existência de um determinado valor. Um exemplo disso é tentar inserir um valor duplicado em uma coluna que é chave primária, ou possui restrição de unicidade. Se a inserção falhar, o usuário poderá inferir que o valor já existe. (Este exemplo assume que o usuário tem permissão pela política para inserir registros que ele não tem permissão para ver.) Outro exemplo é quando um usuário tem permissão para inserir linhas em uma tabela que faz referência a outra tabela que, de outra forma, seria uma tabela oculta. A existência pode ser determinada pelo usuário inserindo valores na tabela que faz a referência, onde o sucesso indicaria que o valor existe na tabela referenciada. Estes problemas podem ser resolvidos com a criação cuidadosa de políticas para impedir que os usuários possam inserir, excluir ou atualizar registros que poderiam indicar um valor que eles não poderiam ver, ou usando valores gerados (por exemplo, chaves alternativas) em vez de chaves com significado externo.
Geralmente, o sistema aplicará as condições de filtro impostas usando
políticas de segurança antes das qualificações que aparecem nas
consultas do usuário, a fim de evitar a exposição inadvertida de
dados protegidos a funções definidas pelo usuário que podem não ser
confiáveis.
No entanto, funções e operadores marcados pelo sistema (ou pelo
administrador do sistema) como LEAKPROOF podem
ser avaliadas antes das expressões de política, porque são
consideradas confiáveis.
Como as expressões de política são adicionadas diretamente à
consulta do usuário, estas serão executadas com os direitos do
usuário que está executando a consulta geral.
Portanto, os usuários que estão usando uma determinada política
devem ser capazes de acessar quaisquer tabelas ou funções
referenciadas na expressão, ou simplesmente receberão um erro de
permissão negada ao tentar consultar a tabela com segurança no
nível de linha ativada.
No entanto, isto não muda como as visões funcionam.
Assim como nas consultas e visões normais, as verificações de
permissão e as políticas para as tabelas referenciadas por uma
visão usarão os direitos do dono da visão, e quaisquer políticas
que se apliquem ao dono da visão, exceto se a visão for
definida usando a opção security_invoker
(veja CREATE VIEW).
Não existe uma política separada para MERGE.
Em vez disso, as políticas definidas para SELECT,
INSERT, UPDATE e
DELETE são aplicadas durante a execução do
comando MERGE, dependendo das ações que forem
realizadas.
Uma discussão adicional e exemplos práticos podem ser encontrados na Políticas de segurança de linha.
O comando CREATE POLICY é uma extensão do
PostgreSQL.