记录访问
在对象权限允许之后,控制用户能看到或修改哪些记录 —— 共享模型默认值、租户隔离、共享规则、记录共享。
记录访问控制的是:在对象权限允许某项操作之后,用户能看到或修改哪些行。
机制
| 机制 | 用途 |
|---|---|
| 行级安全 | 强制执行租户或组织隔离 |
| 共享规则 | 基于声明式条件授予访问 |
| 记录共享 | 向特定用户、团队、岗位、业务单元,或某个单元及其下级授予访问 |
| 所有权 / 层级 | 通过负责人和业务单元树授予访问 |
共享模型默认值
每个对象都会声明(或继承)一个 sharingModel,它设定组织范围的默认值:
private、public_read、public_read_write 或 controlled_by_parent。
从 ObjectStack 13 起,带有负责人字段且没有声明 sharingModel 的自定义对象默认
为私有 —— 记录只对其负责人(以及管理员)可见,直到某条共享规则、记录共享或
更宽的默认值把它们开放出来。显式声明模型即可恢复开放的行为:
ObjectSchema.create({
name: 'crm_lead',
sharingModel: 'public_read_write',
fields: {
company: Field.text({ label: 'Company' }),
// …
},
});13 之前的别名 read、read_write 和 full 已被移除;os compile 会通过
security-owd-unset 和 security-owd-alias lint 标出未设置或使用别名的模型。
默认的租户隔离
安全插件通过当前用户的上下文强制执行租户隔离。对于标准的平台对象,默认规则会 保护那些不带常规组织字段的全局表。
客户在实践中的预期是:
Users only see records that belong to their organization or records
explicitly shared with them.共享规则
用共享规则表达可重复的业务策略:
- 所有区域经理都可以读取其所在区域的客户;
- 支持经理可以看到已升级的案例;
- 财务可以读取已批准的发票;
- 审计人员可以读取标记为待审计的记录。
一条规则是基于字段值的 CEL condition,在编写时编译成行过滤条件;匹配的记录会
为解析出的接收方(某个用户、团队、岗位、业务单元,或某个单元及其下级)生成
sys_record_share 授权。criteria 规则是唯一可编写的形式。
两个开关都失败即关闭
两件读者理所当然会假定、却直到 ObjectStack 17.0 才成立的事:
- 没有条件的共享规则什么都不共享。 过去,一条存储时没有条件谓词的规则会被 求值为该对象的每一条记录 —— 即空过滤条件 —— 所以经由某个未校验的写入路径 产生的一个拼写错误,就会悄悄地开放整张表。现在,写入一个匹配全部的条件会被 拒绝,求值器也会把空条件视为什么都不匹配。
enabled: false的 RLS 策略就是禁用的。 过去,被关闭的策略仍会继续贡献 它的 OR 分支授权,所以关闭一条策略并不会收回访问。现在,被禁用的策略根本不会 被求值。
如果你在更早的版本下审计过访问,并得出"这条规则什么也没授予"或"这条策略是关闭 的"的结论,值得重新运行一遍 解释引擎 —— 实际的范围可能比 元数据所说的更宽。
行级安全拒绝它无法强制执行的内容
从 ObjectStack 17.5 起,RLS 策略要么精确地收窄它所声明的范围,要么拒绝:
- 没有
check的策略用它的using门控写入。 文档一直说check默认为using,但只有声明了check的策略才会被应用到写入上,所以用户可能写入一行 自己读不回来的数据。现在,单行插入或按 id 更新的结果如果落在所有适用的写入 策略的using之外,会返回403 PERMISSION_DENIED。如果一条策略本意就是让 写入可以落在其读取范围之外,就必须声明一个允许这些写入的check。 - 它无法强制执行的谓词会拒绝。 把字段与列表比较
(
record.status != ['closed', 'archived'])、与裸的current_user而不是current_user.id比较,或者指定了对象未声明的字段,都可能放进它本来要拒绝的 行和写入。这样的策略现在会失败即关闭:它的读取不返回任何行,写入返回403。 - 写入按存储后的行来判定。
check和组织隔离墙看到的,是引擎在beforeInsert/beforeUpdate钩子运行之后所存储的行。
os validate 会在这些形态发布之前报告它们(rls-predicate-unenforceable、
rls-predicate-unknown-field),元数据保存入口也会拒绝携带这类策略的权限集
(422 INVALID_METADATA)。
记录共享
用记录共享处理例外情况:
- 把某个商机共享给一位专家;
- 在升级处理期间授予临时访问;
- 让外部集成访问某条特定记录。
可见性故障排查
当用户看不到某条记录时,按以下顺序检查:
- 用户是否已认证,且处于预期的组织中?
- 用户是否拥有对象的
read权限? - 对象的
sharingModel是什么(从 ObjectStack 13 起,自定义对象默认为private)? - 行级安全是否允许这条记录?
- 是否有本应适用的共享规则?
- 是否有直接的记录共享?
- 记录是否由预期业务单元子树中的某个用户拥有?
- 用户访问的项目 / 主机名是否正确?
解释引擎一次调用就能回答所有这些 问题 —— 它会报告每一层的判定,以及是哪项授权(或缺少的授权)决定了结果。