【问题标题】:How Do I Insert Into a Table With Row Level Security?如何插入具有行级安全性的表?
【发布时间】:2018-10-07 17:51:17
【问题描述】:

我有下表:

            Table "api_v1.person"
    Column     |  Type  |      Modifiers
---------------+--------+-------------------------------------------------------
 person_id     | bigint | not null default...
 name          | text   | not null
 date_of_birth | date   |
 api_user      | text   | not null default "current_user"()

具有以下政策:

POLICY "api_user_only" FOR ALL
  USING ((api_user = ("current_user"())::text))
  WITH CHECK ((api_user = ("current_user"())::text))

我的理解是,该策略的FOR ALL 部分意味着它涵盖了插入,而WITH CHECK 确保插入到 api_user 中的值与当前用户相同,例如角色名称。 USING 子句应该只影响 SELECTS 或返回的其他数据。但是,当我尝试插入时,会得到以下结果:

demo=> INSERT INTO api_v1.person (name, api_user) VALUES ('Greg', current_user);
ERROR:  query would be affected by row-level security policy for table "person"

如何插入?

我正在运行 PostgreSQL 9.6.8。

这是重现所需的 SQL:

BEGIN;

CREATE SCHEMA api_v1;

CREATE TABLE api_v1.person (
    person_id BIGSERIAL PRIMARY KEY,
    "name" TEXT NOT NULL,
    date_of_birth DATE,
    api_user TEXT NOT NULL DEFAULT current_user
);

ALTER TABLE api_v1.person ENABLE ROW LEVEL SECURITY;

CREATE POLICY
api_user_only
ON
    api_v1.person
USING
    (api_user = CURRENT_USER)
WITH CHECK
    (api_user = CURRENT_USER)
;

CREATE ROLE test_role;

GRANT USAGE ON SCHEMA api_v1 TO test_role;
GRANT ALL ON api_v1.person TO test_role;
GRANT USAGE ON SEQUENCE api_v1.person_person_id_seq TO test_role;

COMMIT;

SET ROLE test_role;

INSERT INTO api_v1.person ("name") VALUES ('Greg');

【问题讨论】:

  • 我试过你的例子,它适用于我的 PostgreSQL v10。您能否扩展问题以包含展示行为的完整示例(请提供完整的 SQL 语句)?
  • @LaurenzAlbe 我已添加完整的 SQL 语句来重现此问题。感谢您抽出宝贵时间提供帮助。
  • 当我在 v10 和 9.6 上运行您的示例时,我收到错误 ERROR: permission denied for sequence person_person_id_seq。这与行级安全性无关,由GRANT USAGE ON SEQUENCE api_v1.person_person_id_seq TO test_role; 修复。
  • @LaurenzAlbe 所以我授予使用该序列并将角色切换到 test_role 并且我仍然收到ERROR: query would be affected by row-level security policy for table "person" 消息。我可以作为超级用户插入,但不能插入 test_role。
  • 我还测试了 PostgreSQL 10.3 的全新安装并得到了同样的错误。

标签: postgresql postgresql-9.6 row-level-security


【解决方案1】:

在 postgresql.conf 中有一个设置,row_security。如果将其设置为关闭,则受行级安全策略影响的任何查询都会失败并出现错误:ERROR: query would be affected by row-level security policy for table "table_name"。但是,来自超级用户、表所有者(如果您不强制 RLS)和具有 bypassrls 的角色的查询将起作用。

row_security 设置需要设置为on,然后需要重新启动 PostgreSQL,以便针对具有行级安全策略的表处理常规用户语句。

来自源代码:

/*
 * We should apply RLS.  However, the user may turn off the row_security
 * GUC to get a forced error instead.
 */
if (!row_security && !noError)
    ereport(ERROR,
            (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
             errmsg("query would be affected by row-level security policy for table \"%s\"",
                    get_rel_name(relid)),
             amowner ? errhint("To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY.") : 0));

【讨论】:

  • 感谢您的信息。似乎 EDB 安装程序默认将其设置为 on。您的服务器是否以其他方式安装?
  • @klin 我使用名为 ANXS.postgresql 的 Ansible 角色从 PostgreSQL apt 存储库安装。我正在深入挖掘,看看它是否在那个 Ansible 角色中被关闭。如果是这样,我会将其作为他们的错误提出。我也可能会提出 PostgreSQL 的问题。该错误消息没有帮助。
  • @klin 看起来标准 PostgreSQL 存储库也默认为“on”,这是 Ansible 角色的问题。
  • 谢谢。我检查了 EDB 的 9.5、9.6 和 10,也检查了 BigSql 的 10 - 全部使用 on
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-06
  • 2014-03-31
  • 2011-06-29
  • 1970-01-01
  • 2021-09-19
相关资源
最近更新 更多