【问题标题】:PostgreSQL trigger with a given role具有给定角色的 PostgreSQL 触发器
【发布时间】:2014-09-17 01:18:26
【问题描述】:
我用 Plpython 做了一个小 PostgreSQL 触发器。这个触发器在文件系统上有点作用,创建和删除我的一些文件。创建的文件归“postgres”unix 用户所有,但我希望它们归另一个用户所有,比如说 foobar。触发器与用户“foobar”一起安装,并由用户“foobar”执行。
有没有办法通过 PostgreSQL 或 Plpython 使用 unix 用户 'foobar' 执行 SQL 触发器?
我应该使用SET ROLE foobar 吗?
与SECURITY INVOKER 和SECURITY DEFINER 一起玩似乎还不够好。
【问题讨论】:
标签:
postgresql
roles
plpython
【解决方案1】:
您混淆了操作系统用户和 PostgreSQL 用户。
SECURITY DEFINER 允许您以定义 postgresql 用户的身份运行函数。但无论 PostgreSQL 用户运行的是哪个操作系统用户,后端服务器的运行方式始终相同——通常是操作系统用户postgres。
根据设计,PostgreSQL 服务器不能像其他操作系统用户一样运行操作系统命令或系统调用。那将是一个令人讨厌的安全漏洞。
但是,如果您想允许,您可以。你可以:
- 授予
postgres用户sudo以其他用户身份运行部分或全部命令的权限;或
- 编写一个程序以使用
setuid 权限运行,以执行您想要的操作,并授予postgres 用户执行该程序的权限。
在任何一种情况下,运行这些程序的唯一方法是从不受信任的过程语言(如 plpython 或 plperl)或从 C 扩展启动它们。'
不清楚您为什么要首先设置这样的文件所有权,但我怀疑这可能不是一个好主意。如果 PostgreSQL 客户端和服务器甚至不在同一台计算机上怎么办?如果该 PostgreSQL 用户没有操作系统用户,或者用户名不同怎么办?等等。
【解决方案2】:
您的用户在 Postgres 中承担的“角色”是数据库本地的。您在数据库中的角色强制执行数据库权限。所以,你可以说 foobar 可以运行这个存储过程,或者选择这个表,Postgres 会强制执行。如果您使用 SECURITY INVOKER 创建您的过程,这意味着正在运行的过程将使用当前登录的 Postgres 用户运行。 SECURITY DEFINER 意味着该过程将使用创建该过程的角色运行。无论哪种方式,如果您的程序在 Postgres 之外执行任何操作(例如创建文件),它将作为启动 Postgres 的身份来完成(正如您所发现的那样)。就我而言,我有一个名为“postgres”的 Unix 用户,当我启动 Postgres 时,我以该用户身份进行操作。因此,创建的任何文件都将归“postgres”用户所有。
您没有告诉我们您的操作系统。 Windows 将不同于 *nix。此答案适用于 *nix。
您确实提到您的存储过程语言是 plpython。因此,您可以创建该文件,然后在您的过程中创建它之后更改它的所有权。喜欢:
import os
import pwd
f = open('/tmp/myfile','w')
f.write('hello')
f.close()
user_id = pwd.getpwnam("foobar").pw_uid
os.chown('/tmp/myfile', user_id, -1)
假设在运行 Postgres 的主机上有一个 foobar 用户,这应该可以工作。
-g