我正在寻找一个好的模式来实现适合在客户端 - >数据库环境中使用的行级安全控件(通过例如代理,中间人Web服务或存储过程).我控制客户端和数据库.一些要求:
我曾经有过一些(非常好的)想法:
insert,但我需要非常紧密地锁定权限(例如,没有创建函数),并且似乎有很多泄漏信息的陷阱(如除以零).我已经在这个主题上做了大量的谷歌搜索,但我还没有看到有人在现实世界的场景中如何解决这个问题.有一些关于MS SQL的文档但是在MySQL中似乎不鼓励,而且postgres基本上不存在写入.
这似乎是一个非常常见的问题,但我想很多人都在编写Web应用程序并且满足于将用户手铐放到某些经过预先审查的查询上,但我真的需要尽可能多地为用户提供查询数据的灵活性.我的客户.
database architecture security postgresql row-level-security
在文档中,行级安全性似乎很棒。根据我读过的内容,我现在可以停止创建这样的视图:
SELECT data.*
FROM data
JOIN user_data
ON data.id = user_data.data_id
AND user_data.role = CURRENT_ROLE
Run Code Online (Sandbox Code Playgroud)
最重要的是,Postgres 对此进行了很好的分析,view从索引扫描开始,然后是user_data表上的散列连接,这正是我们想要发生的,因为它非常快。将其与我的 RLS 实现进行比较:
CREATE POLICY data_owner
ON data
FOR ALL
TO user
USING (
(
SELECT TRUE AS BOOL FROM (
SELECT data_id FROM user_data WHERE user_role = CURRENT_USER
) AS user_data WHERE user_data.data_id = data.id
) = true
)
WITH CHECK (TRUE);
Run Code Online (Sandbox Code Playgroud)
政策的这种无赖执行的条件各行的data,而不是由作用域查询到我们行优化表,CURRENT_USER可以访问,就像我们的观点一样。需要明确的是,这意味着select * from data命中表中的每一行data …
比方说,我有一个users表有三列,public_data,private_data,和system_data,和我有一个名为三个角色postgres,authenticated_user和visitor.
postgres是超级用户,可以访问所有数据(system_data当然包括)
authenticated_user应该能够访问每个用户public_data,他们自己private_data,但不是system_data
visitor 只能访问每个用户 public_data
如何设置表格,角色,授权和策略以完成上述操作?
postgresql database-design user-management row-level-security grant
我希望表中的行只能访问组的成员.我通过以下方法创建用户并将其添加到组中,
CREATE USER abc LOGIN PASSWORD 'securedpassword1';
CREATE USER xyz LOGIN PASSWORD 'securedpassword2';
ALTER GROUP permanent ADD USER abc;
Run Code Online (Sandbox Code Playgroud)
然后我写的策略使它只对当前用户可访问.但我需要整个小组才能访问它.
CREATE TABLE table_Workers
(
worID INT
,worName CHARACTER VARYING
,pgUser CHARACTER VARYING
);
INSERT INTO table_Workers VALUES
(1,'Jason','abc'),(2,'Roy','abc'),(3,'Johny','abc')
,(4,'Jane','xyz'),(5,'Kane','xyz'),(6,'Stuart','xyz');
CREATE POLICY policy_employee_user ON table_Workers FOR ALL
TO PUBLIC USING (pgUser = current_user);
ALTER TABLE table_Workers ENABLE ROW LEVEL SECURITY;
Run Code Online (Sandbox Code Playgroud)
pgUser命名可以访问该行的用户.我希望用pgRole替换列pgUser,其中提到了组的名称,其成员可以访问该特定行.任何提示或方法都可以使整个组可以访问行.
(欢迎提出更好或更描述性标题的建议)。
我想知道在 PostgreSQL 中是否可以使用 RLS(或任何其他机制)进行以下操作。如果用户名与另一个表中的列匹配,我希望用户能够更新表的某些行。在下面的示例中,我希望在 table 中nene显示为列的user能够更新列 和table 。我想表达的是将策略应用于 t2 中的行,该行将由以下 select 语句匹配: ut0apt2SELECT a, p FROM t2 INNER JOIN t1 ON (t2.t1id = t1.id) INNER JOIN t0 ON (t1.t0id = t0.id) WHERE t0.u = 'nene';
这可能吗?有关如何进行的任何建议?一个明显的解决方法是在表 t2 上复制用户名,但这会在 t2 上添加无关信息并需要额外的约束来强制执行。
这是我的三个表(在实际情况中字段更多,表 t1 无法排除问题;我将其留在示例中,因为需要两个连接可能会改变解决方案空间)。
表t0是用创建的CREATE TABLE t0 (id TEXT PRIMARY KEY, u TEXT UNIQUE, pn TEXT);,现在包含:
=> SELECT * FROM t0;
id | u | pn
------+------+------
b321 | …Run Code Online (Sandbox Code Playgroud)当你想使用 postgres 的 SELECT FOR UPDATE SKIP LOCKED 功能来确保两个不同的用户从一个表中读取并声明任务不会被彼此阻止并且也不会被另一个用户读取任务时:
查询中正在使用连接来检索任务。除了包含主要信息的表之外,我们不希望任何其他表具有行级锁定。下面的示例查询 - 仅锁定表中的行 - 以下查询中的“任务”
SELECT v.someid , v.info, v.parentinfo_id, v.stage FROM task v, parentinfo pi WHERE v.stage = 'READY_TASK'
AND v.parentinfo_id = pi.id
AND pi.important_info_number = (
SELECT MAX(important_info_number) FROM parentinfo )
ORDER BY v.id limit 200 for update skip locked;
Run Code Online (Sandbox Code Playgroud)
现在,如果用户 A 正在检索该表的大约 200 行,用户 B 应该能够检索另一组 200 行。
编辑:根据下面的评论,查询将更改为:
SELECT v.someid , v.info, v.parentinfo_id, v.stage FROM task v, parentinfo pi WHERE v.stage = 'READY_TASK'
AND v.parentinfo_id = pi.id …Run Code Online (Sandbox Code Playgroud) 我在让查询规划器为启用行级安全性 (RLS) 的表编写良好的计划时遇到一些麻烦。似乎所需要做的就是从启用行级安全性的表到启用非行级安全性的表的联接来强制执行错误的计划,即使规划器应该能够使用两个表上都有适当的索引。
有没有办法帮助规划者解决这个问题?或者当涉及 RLS 时某些统计数据不可用?
USING (TRUE)我尝试为不需要 RLS 的表启用 RLS(使用 添加广泛开放的策略),这与在该表上不包含策略具有相同的效果。
DROP SCHEMA IF EXISTS foo CASCADE;
CREATE SCHEMA foo;
CREATE TABLE foo.bar AS
SELECT generate_series(1,10000000) AS id, md5(random()::text) AS descr, random() * 5 + 1 AS licflag;
CREATE TABLE foo.baz AS
SELECT generate_series(1,10000000) AS id, md5(random()::text) AS descr, random() * 5 + 1 AS licflag;
CREATE UNIQUE INDEX ON foo.bar (id);
CREATE INDEX ON foo.bar (licflag);
CREATE UNIQUE INDEX ON foo.baz (id);
CREATE INDEX ON foo.baz (licflag); …Run Code Online (Sandbox Code Playgroud) postgresql performance row-level-security sql-execution-plan
描述:这是性能问题的示例演示。
我们首先创建了两个表,启用了行级安全性,还创建了策略。
表定义:
create table sample_schema.sample_table1(ID numeric(38) PRIMARY KEY NOT NULL,
tenant_id VARCHAR(255) NOT NULL,
Description VARCHAR(255)
);
create table sample_schema.sample_table2(ID2 numeric(38) PRIMARY KEY NOT NULL,
tenant_id VARCHAR(255) NOT NULL,
table1_id numeric (38),
Description2 VARCHAR(255)
);
Run Code Online (Sandbox Code Playgroud)
索引创建:
CREATE UNIQUE INDEX sample_table1_idx1 ON sample_schema.sample_table1(tenant_id,id);
Run Code Online (Sandbox Code Playgroud)
启用行级安全性:
ALTER TABLE sample_schema.sample_table1 ENABLE ROW LEVEL SECURITY;
Run Code Online (Sandbox Code Playgroud)
创建角色:
CREATE ROLE tenant_grp_role_p_id;
Run Code Online (Sandbox Code Playgroud)
创建策略:我希望策略选择tenant_id列值具有与登录用户相同角色的数据。
CREATE POLICY Tenant_Roles ON sample_schema.sample_table1 TO tenant_grp_role_p_id USING ((tenant_id) IN ( SELECT rolname FROM pg_roles WHERE pg_has_role( current_user, oid, 'member')));
Run Code Online (Sandbox Code Playgroud)
创建样本数据:
insert into sample_schema.sample_table1 …Run Code Online (Sandbox Code Playgroud) sql postgresql row-level-security database-indexes postgresql-performance
数据库中有 3 个表 - 部门、员工、帐户。一个部门有很多员工。Employee 包含列department_id bigintAccount 表包含 columns login varchar,employee_id bigint用于将 Postgres 用户(角色)绑定到 Employee 中的行。
我的目标是让用户仅查看和使用 Employee 的值与department_id用户相同的那些行。
一定有类似的东西:
CREATE POLICY locale_policy ON employee
TO justuser, operator
USING (department_id =
(SELECT department_id FROM employee WHERE id =
(SELECT employee_id FROM account WHERE login = CURRENT_USER)
)
)
Run Code Online (Sandbox Code Playgroud)
但由于 Employee 的子查询,它正在提高infinite recursion detected in policy for relation employee。
编辑:关系定义为:
create table department(
id serial primary key);
create table employee(
id serial …Run Code Online (Sandbox Code Playgroud) 我有一个权限结构,因此特定权限仅允许编辑表中 5 个字段中的 2 个。我的整个系统中有 RLS,因此我需要在策略内执行上述操作。
起初,我想到编写一个函数来检查用户是否更新了他们没有更新权限的字段,并在策略中使用它的返回值。但我找不到一种无需定义变量即可在策略内使用返回值的方法,这显然不能在策略内定义。
这是所说的功能:
CREATE OR REPLACE FUNCTION is_user_updating_non_permitted_fields(id uuid, fieldA integer, fieldB text...)
.....
DECLARE
old_row MY_TABLE
BEGIN
SELECT * FROM MY_TABLE m WHERE id = m.id INTO old_row;
IF (fieldA != old_row.fieldA OR fieldB != old_row.fieldB)
THEN RETURN 1;
ELSE RETURN 0;
ENDIF;
END;
....
Run Code Online (Sandbox Code Playgroud)
该政策将类似于:
CREATE POLICY my_table_update ON MY_TABLE FOR UPDATE
WITH CHECK (
(SELECT CASE WHEN (
''use function here''
) = 1 THEN false ELSE true END;
)
)
Run Code Online (Sandbox Code Playgroud)
作为最后的手段,我想到在更新和使用之前进行触发 …
postgresql ×10
sql ×5
database ×2
architecture ×1
grant ×1
performance ×1
policy ×1
security ×1