由 John Doe 七月 15, 2025
你想在 PostgreSQL 中添加一些用于监控或管理数据库的 SQL 函数吗?那么,你需要控制好它们的访问权限。
特性提交日志
新增 “pg_database_owner” 默认角色。
该角色的成员隐含为当前数据库的所有者。预计在模板数据库中使用。一旦 pg_database_owner 在模板中拥有权限,从该模板实例化的数据库的每个所有者都将行使这些权限。
讨论:https://postgr.es/m/20201228043148.GA1053024@rfd.leadboat.com
示例
你可能知道,只要在 template1 数据库中创建了某些内容,当你使用默认选项创建新数据库时,新数据库会复制 template1 中的所有内容。有时候,我们可能会往 template1 添加一些监控函数或类似的东西。
让我们看看 pg_database_owner 是如何工作的。
假设我们有 3 个用户:redrock(超级用户)、test 和 test2。
当 test 或 test2 查询 pg_stat_activity 时,在 query 列中,他们通常会看到“权限不足”。
现在,我们以 redrock 的身份登录到 template1,并执行:
create function get_running_queries()
returns table (pid int4, query text) as
$$
select pid, query from pg_stat_activity
where backend_type = 'client backend';
$$ language sql security definer;
revoke all on function get_running_queries() from public;
grant execute on FUNCTION get_running_queries() to pg_database_owner;
现在,当我们以 test 或 test2 的身份连接到 template1,并尝试使用这个函数时,会得到:
$ for u in test test2; do psql -d template1 -U $u -X -c 'select * from get_running_queries()'; done
ERROR: permission denied for function get_running_queries
ERROR: permission denied for function get_running_queries
但是,当我们创建一个以 test 为所有者的数据库:
create database test with owner test;
并在 test 数据库中重新进行测试时:
$ for u in test test2
do
echo "===== user: $u ====="
psql -d test -U $u -X -c 'select * from get_running_queries()'
echo
done
===== user: test =====
pid | query
--------+---------------------------------------
174949 | select * from get_running_queries()
169886 | select pg_sleep(1000000);
170124 | select * from pg_stat_activity ;
170312 | create database test with owner test;
(4 rows)
===== user: test2 =====
ERROR: permission denied for function get_running_queries
当然,这个例子相当简单,但是希望这能展示出可以实现的功能。
它允许轻松创建那些仅对数据库所有者可用、而对其他任何用户不可用的内容,无需在每个新数据库中手动授予权限。
非常不错的特性。感谢社区的所有相关人员。
参考
提交日志:https://git.postgresql.org/pg/commitdiff/a14a0118a1fecf4066e53af52ed0f188607d0c4b