You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Aurora Postgres 14 Upsert触发行级安全策略违规问题

问题解决:Aurora Postgres 14.5 Upsert触发行级安全策略违规

问题背景

使用AWS Aurora PostgreSQL 14.5,通过Rust Diesel框架操作contacts表,执行Upsert时,触发冲突进入更新分支会报错:

new row violates row-level security policy (USING expression) for table "contacts"

本地PostgreSQL 14.8环境下同逻辑可正常运行。

表结构

create table contacts (
    email TEXT NOT NULL,
    user_id TEXT NOT NULL,
    contact_data JSONB,
    user_groups TEXT[],
    tenant_groups TEXT[],
    tags TEXT[],
    PRIMARY KEY (email, user_id)
);

行级安全策略

ALTER TABLE contacts FORCE ROW LEVEL SECURITY;
CREATE POLICY select_contacts_policy ON contacts 
FOR SELECT
USING (user_id = current_setting('myapp.user_id'));
ALTER TABLE contacts ENABLE ROW LEVEL SECURITY;

CREATE POLICY insert_contacts_policy ON contacts 
FOR INSERT
WITH CHECK (true);
ALTER TABLE contacts ENABLE ROW LEVEL SECURITY;

Diesel执行逻辑

  1. 设置会话参数:
sql_query(format!("SET SESSION myapp.user_id = '{user_id}'")).execute(pg_conn)?;
  1. 执行Upsert:
diesel::insert_into(contacts::table)
    .values(&contacts)
    .on_conflict((contacts::email, contacts::user_id))
    .do_update()
    .set(&contacts)
    .execute(pg_conn)?;
  1. 恢复会话参数:
sql_query("SET SESSION myapp.user_id = -1").execute(pg_conn)?;

问题原因

PostgreSQL的行级安全(RLS)对Upsert的UPDATE分支会触发UPDATE类型的策略检查,但当前仅配置了SELECT和INSERT的策略,缺少UPDATE策略:

  • Aurora Postgres 14.5对RLS的执行逻辑更严格,要求所有操作(包括Upsert中的UPDATE)必须匹配对应的RLS策略;
  • 本地14.8社区版存在隐式处理,未严格校验UPDATE分支的RLS规则。

当触发Upsert的更新分支时,数据库会检查UPDATE的USING规则(验证是否允许修改该行),但由于没有定义UPDATE策略,默认拒绝操作,导致报错。

解决方案

1. 添加UPDATE行级安全策略

为contacts表添加针对UPDATE的RLS策略,确保更新操作符合权限要求:

CREATE POLICY update_contacts_policy ON contacts
FOR UPDATE
USING (user_id = current_setting('myapp.user_id'))
WITH CHECK (true);
  • USING子句:确保要更新的行的user_id与当前会话的myapp.user_id一致,符合数据隔离要求;
  • WITH CHECK子句:允许更新后的行满足条件(这里设为true,与INSERT策略保持一致,可根据业务需求调整)。

2. 验证会话参数有效性

执行Upsert前,确认会话参数myapp.user_id已正确设置,避免因参数值错误导致RLS校验失败:

let current_user_id = sql_query("SELECT current_setting('myapp.user_id')")
    .get_result::<String>(pg_conn)?;
// 可添加日志或断言验证参数是否正确

3. 确认RLS策略生效

执行以下SQL确认所有策略已正确启用:

SELECT polname, polcmd, polrelid::regclass
FROM pg_policy
WHERE polrelid = 'contacts'::regclass;

确保输出包含select_contacts_policy、insert_contacts_policy和update_contacts_policy三条策略。

内容的提问来源于stack exchange,提问作者parmesant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 15:27:41