Por que não consigo remover um usuário ou função na minha instância de banco de dados do RDS for PostgreSQL?

5 minuto de leitura
0

Quando tento remover um usuário ou função na minha instância do Amazon Relational Database Service (Amazon RDS) para PostgreSQL, recebo o erro “a função não pode ser descartada porque alguns objetos dependem dela”.

Breve descrição

Quando um usuário ou função no RDS para PostgreSQL cria um objeto, como uma tabela ou esquema, o usuário ou função é o proprietário do objeto criado. Se você tentar remover um usuário ou função que possui um ou mais objetos em qualquer banco de dados ou tem privilégios nesses objetos, você receberá um erro indicando que há objetos que dependem do usuário ou função junto com as permissões concedidas, se houver.

Para remover um usuário ou função que tenha objetos dependentes, você deve fazer o seguinte:

  1. Reatribua a propriedade desses objetos a outro usuário.
  2. Revogue todas as permissões que foram concedidas ao usuário ou à função.

Observação: se esses objetos não forem mais necessários, considere removê-los e excluir a função. Você pode remover todos os objetos que pertencem a uma função em um banco de dados usando o comando DROP OWNED. Você também pode revogar quaisquer privilégios concedidos à função em objetos nesse banco de dados ou objetos compartilhados. Depois que o comando DROP OWNED for executado com sucesso, você poderá descartar a função.

Resolução

No exemplo a seguir, três funções de banco de dados diferentes são usadas:

  • test_user: este é o usuário ou função que deve ser removido.
  • admin_user: essa é a função usada para remover o usuário ou a função necessária. Este usuário é o usuário mais privilegiado no RDS com a função rds_superuser anexada a ele.
  • another_user: este é o usuário ou função que recebeu a propriedade de objetos pertencentes a test_user.

Execute o seguinte comando para ver a função com a qual você fez login:

pg_example=> SELECT current_user;

A saída é semelhante à seguinte:

current_user
--------------
 admin_user
(1 row)

Quando você tenta remover um usuário ou função com objetos dependentes, você recebe um erro semelhante ao seguinte:

pg_example=> DROP ROLE test_user;
ERROR:  role "test_user" cannot be dropped because some objects depend on it
DETAIL:  privileges for database pg_example
owner of table test_table
owner of schema test_schema
owner of sequence test_schema.test_seq
privileges for table test_t2

Neste exemplo, a função que está sendo removida é test_user. Observe que a função atualmente conectada é admin_user, que é o usuário mestre do banco de dados.

A partir da mensagem de erro, você obtém as seguintes informações:

  • A função test_user tem privilégios concedidos no banco de dados pg_example e na tabela test_t2.
  • A função test_user possui a tabela test_table, esquema test_schema e um objeto de sequência test_seq em test_schema.

Observação: se você remover um usuário ou função quando estiver conectado a um banco de dados diferente, obterá uma saída semelhante à seguinte:

pg_another_db=> DROP ROLE test_user;
ERROR:  role "test_user" cannot be dropped because some objects depend on it
DETAIL:  privileges for database pg_example
4 objects in database pg_example

Para ver objetos que pertencem a um usuário ou função, certifique-se de se conectar ao banco de dados onde os objetos pertencentes estão localizados.

Para remover o usuário ou a função, você deve reatribuir a propriedade dos objetos pertencentes a outro usuário ou função e revogar as permissões associadas. Você pode usar o comando PostgreSQL REASSIGN OWNED para reatribuir a propriedade desses objetos a outro usuário. Ao executar esse comando, você pode receber um erro semelhante ao seguinte:

pg_example=> select current_user;
 current_user
--------------
 test_user
pg_example=> REASSIGN OWNED BY test_user TO another_user;
ERROR:  permission denied to reassign objects

Para resolver esse problema, você deve conceder o usuário ou a função ao usuário que está reatribuindo a propriedade. Você não pode usar test_user para fazer isso porque test_user não é o proprietário de another_user. Portanto, você pode ver um erro semelhante ao seguinte:

pg_example=> select current_user;
 current_user
--------------
 test_user
pg_example=> grant another_user to test_user;
ERROR:  must have admin option on role "another_user"

Você pode realizar uma das ações a seguir para conceder o usuário ou a função ao usuário que está reatribuindo a propriedade:

  • Faça login no seu usuário mestre e execute o comando GRANT:
pg_example=> select current_user;
 current_user
--------------
 admin_user
pg_example=> GRANT another_user TO test_user;
GRANT ROLE
  • Faça login no usuário que reatribuirá a propriedade e executará o comando GRANT:
pg_example=> select current_user;
 current_user
--------------
 another_user
pg_example=> GRANT another_user TO test_user;
GRANT ROLE

Depois de escolher uma das opções anteriores, reatribua a propriedade dos objetos pertencentes a test_user a another_user depois de fazer login em test_user:

pg_example=> select current_user;
 current_user
--------------
 test_user
pg_example=> reassign owned by test_user to another_user;
REASSIGN OWNED

Se você entrar no seu usuário mestre e tentar remover o test_user que ainda tem privilégios existentes, você pode ter um erro semelhante ao seguinte:

pg_example=> select current_user;
 current_user
--------------
 admin_user
pg_example=> DROP ROLE test_user;
ERROR:  role "test_user" cannot be dropped because some objects depend on it
DETAIL:  privileges for database pg_example
privileges for table test_t2

Nesse caso, você recebe um erro mesmo que o comando REASSIGN seja bem-sucedido. Isso ocorre porque os privilégios de test_user devem ser revogados. Execute o comando REVOKE para revogar todas as permissões de uso de qualquer objeto no qual test_user tenha privilégios. Neste exemplo, revogue as permissões no banco de dados pg_example e na tabela test_t2 para test_user.

pg_example=> REVOKE ALL ON TABLE test_t2 FROM test_user;
REVOKE
pg_example=> REVOKE ALL ON DATABASE pg_example FROM test_user;
REVOKE

Em seguida, remova o usuário test_user:

pg_example=> DROP ROLE test_user;
DROP ROLE

Depois de revogar os privilégios, você pode removê-lo da função com êxito.


Informações relacionadas

Documentação do PostgreSQL para DROP ROLE