标签: row-level-security

客户端 - 数据库方案中的行级安全性

我正在寻找一个好的模式来实现适合在客户端 - >数据库环境中使用的行级安全控件(通过例如代理,中间人Web服务或存储过程).我控制客户端和数据库.一些要求:

  • 禁止用户查看他们无权查看的查询结果中的行
  • 允许用户将自己的行INSERT并更新到表中,这使他们有权查看它们
  • (软要求)允许用户授予其他人读取或写入行的权限
  • 在Linux上运行的开源或低成本解决方案.据我了解,没有免费的数据库实现行级安全性.Oracle支持这一点,但它也是如此.Postgres 可能会在9.4中实现这一点,但它最初的目标是9.3并且滑落,并且对ML的讨论可能会再次滑落.我暂时考虑使用postgres,因为它们似乎是这个功能最远的.

我曾经有过一些(非常好的)想法:

  • 使用postgresql的安全屏障视图并拒绝用户访问基础表.遗憾的是,没有好的方法将行插入安全屏障视图,因此某些特权代理/ web服务必须处理插入语句.这似乎很难做到.
  • 使用常规视图,并拒绝用户访问基础表.这允许insert,但我需要非常紧密地锁定权限(例如,没有创建函数),并且似乎有很多泄漏信息的陷阱(如除以零).
  • 定义SQL的某个子集,并创建一个代理,它是您与数据库唯一的通信点.代理解析您的SQL查询并重写它以强制执行安全性要求.这似乎很难做到,但也许我可以使用一个非常小的SQL子集,直到postgres实现真正的行级安全性.
  • 只为不同的用户(甚至不同的DB)使用不同的表.但是我不确定它对很多用户来说有多好.此外,这似乎不符合软要求.
  • 找一些商业但价格合理的DB实际支持这个
  • 使用Veil但似乎没有维护,它具有其他解决方案的大部分限制

我已经在这个主题上做了大量的谷歌搜索,但我还没有看到有人在现实世界的场景中如何解决这个问题.有一些关于MS SQL的文档但是在MySQL中似乎不鼓励,而且postgres基本上不存在写入.

这似乎是一个非常常见的问题,但我想很多人都在编写Web应用程序并且满足于将用户手铐放到某些经过预先审查的查询上,但我真的需要尽可能多地为用户提供查询数据的灵活性.我的客户.

database architecture security postgresql row-level-security

7
推荐指数
1
解决办法
2431
查看次数

Postgres 中规范化表的行级安全性

前提

在文档中,行级安全性似乎很棒。根据我读过的内容,我现在可以停止创建这样的视图:

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 …

sql postgresql row-level-security

7
推荐指数
1
解决办法
1221
查看次数

将行级安全性与列授权相结合

比方说,我有一个users表有三列,public_data,private_data,和system_data,和我有一个名为三个角色postgres,authenticated_uservisitor.

postgres是超级用户,可以访问所有数据(system_data当然包括)

authenticated_user应该能够访问每个用户public_data,他们自己private_data,但不是system_data

visitor 只能访问每个用户 public_data

如何设置表格,角色,授权和策略以完成上述操作?

postgresql database-design user-management row-level-security grant

7
推荐指数
1
解决办法
1716
查看次数

组的行级安全性或使行加入组

我希望表中的行只能访问组的成员.我通过以下方法创建用户并将其添加到组中,

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,其中提到了组的名称,其成员可以访问该特定行.任何提示或方法都可以使整个组可以访问行.

sql postgresql row-level-security

7
推荐指数
1
解决办法
232
查看次数

PostgreSQL 行级安全性涉及视图或带有连接的选择

(欢迎提出更好或更描述性标题的建议)。

我想知道在 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)

database postgresql row-level-security relational-database

6
推荐指数
1
解决办法
2429
查看次数

如何在 postgres 中使用“For update skip locked”而不锁定查询中使用的所有表中的行?

当你想使用 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)

postgresql row-level-security

6
推荐指数
1
解决办法
2167
查看次数

行级安全查询计划比相同的非 RLS 查询慢 45 倍

我在让查询规划器为启用行级安全性 (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

5
推荐指数
0
解决办法
840
查看次数

在postgres中,行级安全性(RLS)性能明显降低。

描述:这是性能问题的示例演示。

我们首先创建了两个表,启用了行级安全性,还创建了策略。

表定义:

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

5
推荐指数
1
解决办法
3828
查看次数

PostgreSQL - 在关系策略中检测到无限递归

数据库中有 3 个表 - 部门、员工、帐户。一个部门有很多员工。Employee 包含列department_id bigintAccount 表包含 columns login varcharemployee_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)

sql postgresql policy row-level-security

5
推荐指数
1
解决办法
5566
查看次数

如何比较 postgres 策略中行的旧值和新值以进行更新

我有一个权限结构,因此特定权限仅允许编辑表中 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)

作为最后的手段,我想到在更新和使用之前进行触发 …

sql postgresql row-level-security

5
推荐指数
1
解决办法
3194
查看次数