無法在 PgSQL AWS RDS 中撤銷權限或刪除使用者
我想
asd
從數據庫中刪除使用者。所以,我有兩個數據庫:foo
並且bar
使用者顯然對兩者都有依賴關係。數據庫是從 root 使用者創建的postgres
,但裡面的所有表和序列都是由使用者foo_migration
和bar_migration
分別創建的。首先,我以
postgres
使用者身份登錄foo
數據庫。當我嘗試刪除使用者時,我得到:
ERROR: role "asd" cannot be dropped because some objects depend on it
包含有關來自多個序列、表、bar
數據庫和數據庫中的一些對象的權限的詳細資訊postgres
。因此,我嘗試一一清除(同時仍以數據庫
postgres
使用者身份登錄foo
)。我首先嘗試REASSIGN OWNED BY asd TO foo_migration;
。這返回ERROR: permission denied
,這很奇怪,因為我以postgres
使用者身份登錄。無論如何,那我試試REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public FROM asd; REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM asd;
我得到一堆
WARNING: no privileges could be revoked
使用者有權訪問的所有序列和表格。我也嘗試DROP OWNED BY asd;
了也以ERROR: permission denied
.這一切都不成功,所以我嘗試以使用者身份登錄
postgres
數據庫postgres
並執行相同的步驟。REVOKE
命令成功執行而沒有警告,但實際上沒有權限被更改/影響。並且REASSIGN
仍然DROP OWNED BY
導致ERROR: permission denied
.錯誤消息是裸露的。沒有提供任何提示或細節。
我沒有
asd
使用者的密碼,所以我無法嘗試使用它登錄並執行任何操作。您對如何解決此問題有任何想法嗎?我是否需要查看一些顯示所有權的表格並從那裡開始?使用者不是
postgres
“全能”的管理員使用者嗎?
我在 Postgres RDS 上遇到了類似的問題。這是我用來將對像從一個使用者重新分配給另一個使用者然後刪除使用者的解決方法。對你來說,它會像:
-- logged in as the rds_superuser role you defined when you created your RDS instance CREATE ROLE change_owner LOGIN; GRANT asd TO change_owner; GRANT foo_migration TO change_owner; -- log out of current user and log in as `change_owner` REASSIGN OWNED BY asd TO foo_migration; -- log out of current user and log in as rds_superuser role DROP USER asd;
我首先使用腳本撤銷所有內容來解決這個問題。
我用python(sqlalchemy)編寫它並保持postgresql明確;遷移到另一種語言應該足夠清楚。
all_schemas = db_conn.execute( "SELECT schema_name FROM information_schema.schemata " "WHERE schema_name != 'information_schema' " "AND schema_name != 'pg_toast' " "AND schema_name != 'pg_catalog';" ).fetchall() for schem in all_schemas: if any([s in schem[0] for s in ["pg_temp_", "pg_toast_temp_"]]): continue # skip over these. This is kinda what '\dn' does in psql. db_conn.execute(f"REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA {schem[0]} FROM {user}") db_conn.execute(f"REVOKE ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {schem[0]} FROM {user}") db_conn.execute(f"REVOKE ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA {schem[0]} FROM {user}") db_conn.execute(f"REVOKE USAGE ON SCHEMA {schem[0]} FROM {user}") # this is response from \d all_resources = db_conn.execute(""" SELECT n.nspname as "Schema", c.relname as "Name", CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as "Type", pg_catalog.pg_get_userbyid(c.relowner) as "Owner" FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('r','v','m','S','f','') AND n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema' AND n.nspname !~ '^pg_toast' AND pg_catalog.pg_table_is_visible(c.oid) ORDER BY 1,2; """).fetchall() for resource in all_resources: resource_name = resource[1] db_conn.execute(f"REVOKE ALL ON {resource_name} FROM {user}") all_databases = db_conn.execute( "SELECT datname FROM pg_database " "WHERE NOT datacl ~ 'rdsadmin=CTc/rdsadmin';" ).fetchall() for db_tup in all_databases: db_conn.execute(f"REVOKE ALL PRIVILEGES ON DATABASE {db_tup[0]} FROM {user}") # And finally (good god this shouldn't be this hard) db_conn.execute(f"DROP USER IF EXISTS {user}")