P2 Foundry
访问控制与数据治理:看得见才敢信
数据既要"看得见",也要"分得清、管得住"。Foundry 的访问控制让读路径按 RLS/CLS/属性级三层过滤、写路径有记录级 RLS 兜底;数据治理用术语表统一词汇、分类标签标注敏感度、质量规则做闭环。本主题 4 个故事覆盖"能看什么、能改什么、怎么讲清楚、怎么保质量"。
管理员
数据工程师
业务分析师
RLS
CLS
质量规则
共 4 个故事
能 / 不能速览
✅ 这个主题能做
- 只读路径三层过滤:RLS 行级 + CLS 列级(mask/hide/nullify)+ 无 Read 属性列置 NULL(不整行拒绝)
- 写路径记录级 RLS(RECORD_ACCESS_DENIED)+ 无 WHERE 无边界写整批拒绝
- 语义查询 / OOL / 指标查询统一注入 RLS/CLS 与属性级安全
- 术语表关联属性、数据分类(level 0-3)打标、属性治理汇总
- 质量规则(null/format/unique/referential)挂管道运行时检查 + 问题确认/修复闭环
⛔ 这个主题做不了
- ABAC 策略只做 CRUD 与显式授权,未接入查询 / 写路径
- 分类标签不会自动驱动 CLS 访问控制,需管理员另配 cls_policies
- 质量规则"未达标不得部署"弱化为"run 标红 + 数据照写",error 级不阻断落库
- 保留策略只有 CRUD 配置,不真正删除 / 归档 / 匿名化数据
适用角色
本主题面向三个角色:
- 管理员:配置 RLS / CLS / 权限点(用户/角色/策略管理在 AIP 安全后台),授权并追责。
- 数据工程师:建术语表、打分类标签、写质量规则,让数据"讲得清、保得准"。
- 业务分析师:消费受保护的只读查询,遇到脱敏 / null 能看懂原因。
能力速览(能做什么)
只读三层过滤
RLS 行级注入 WHERE、CLS 列级 mask/hide/nullify、属性级无 Read 置 NULL——查询一条路全过。
记录级写权限
写路径先 SELECT 主键 + RLS 双计数校验目标记录可见性,越权整批拒绝,绝不静默放大影响。
术语表 + 分类
术语统一"客单价""GMV"这类词汇并关联属性;分类标签(0 公开~3 绝密)标注属性敏感度。
质量规则闭环
null/format/unique/referential 四类规则挂管道输出,违规记 issue,open → acknowledged → fixed。
属性治理汇总
一个接口看全某属性的术语 + 分类 + 基本信息,讲不清楚的属性一键查证。
调整指南(怎么调整)
- 想管行:在 AIP 安全后台配 RLS 策略(如 region = '{user_id}')挂到角色,读与写同时生效。
- 想脱敏:配 CLS 策略对敏感列做 mask / hide / nullify,查询自动生效。
- 想统一词汇:建术语表并关联本体属性,再让分析师按术语搜。
- 想标敏感度:建 level 0-3 分类给属性打标,治理汇总一处看全。
- 想拦坏数据:给管道建质量规则,run 后看 /quality/issues,按 open → fix 闭环。
做得好的场景
安全与治理让"敢用数据、说得清数据"成为可能,特别适合以下场景:
- 分权可见:区域负责人只能看、只能改自己区域的数据,越权写直接被拒。
- 脱敏合规:敏感列自动脱敏,分析师查数不碰裸数据。
- 词汇统一:术语表 + 分类让"客单价"还是"平均订单金额"不再打架。
- 质量前置:管道运行即检查,坏数据一落地就被问题跟踪盯上。
限制与不足
以下是明确的边界,使用前先知道:
- ABAC 未接入链路:策略 CRUD + /security/authorize 已实现,但不会在查询 / 写路径自动执行。
- 分类不自动联动:打"机密"标签不会自动隐藏,需管理员另配 CLS。
- 质量不隔离:error 级违规只把 run 标红,数据照写不阻断。
- 保留策略是死配置:delete / archive / anonymize 不会真正执行。
场景故事
故事 1
越权改"华南"客户被记录级 RLS 整批拒绝
场景:记录级写权限
角色:管理员 + 区域运营
耗时:约 6 分钟
- 背景
- demo 数据源 foundry_demo_warehouse 的 customers 表有 region 列(张三=华东、李四=华北、王五=华南)。管理员给区域运营账号 zhangsan 配置 RLS 策略
region = '{user_id}',并让数据工程师建了一个 modify 型"客户回写"动作(目标表 customers)。zhangsan 想顺手把华南客户王五(customer_id=3)的 region 改成华东。
- 传统做法对比
- 以前一张 UPDATE 全表都能跑,区域运营拿到的权限往往"要么全有要么全无",越权改数据只能靠事后翻日志;现在写路径先做记录级校验,目标记录对你不可见就直接整批拒绝,改都改不动。
- 角色
- 管理员(配 RLS 策略与权限点);区域运营 zhangsan(执行动作);数据工程师(建动作定义)。
- 操作步骤
-
- 管理员在 AIP 安全后台配置 RLS 策略并挂到 zhangsan 角色
- 数据工程师建 modify 动作(UPDATE customers SET region=:region WHERE customer_id=:customer_id)并授 action 权限
- zhangsan 登录,对 customer_id=3 执行动作
- 观察返回:记录级检查通过/拒绝
- 系统响应
- zhangsan 更新王五(华南行)返回 HTTP 403,响应体(status=record_denied):
{
"code": 0,
"data": {
"mode": "VALIDATE_AND_EXECUTE",
"status": "record_denied",
"operation_id": "run_6"
}
}
目标行对 zhangsan 不可见 → 双计数不相等 → 整批拒绝;同时写一条 result=record_denied 的审计。
- 结果洞察
- 写路径第三步 stepRecordScope 会先 SELECT 目标主键并注入 RLS 再数可见行:visible == total 才放行;zhangsan 改自己区域的客户(张三)则正常成功。审计里能查到这次被拒操作,越权有痕。
- 调整建议
- RLS 策略按区域/负责人维度设计;给角色的动作权限做最小化;被拒后先查自己的 RLS 可见范围再操作,别硬试。
- 动手试一试
- 页面路径:Action 测试 → update 型动作。输入内容:用 zhangsan 改 customer_id=3(王五)。预期结果:返回 status=record_denied(403);改 customer_id=1 成功。记录级检查仅对 modify 型动作生效。
- 限制提示
- 记录级检查只对 modify(UPDATE/DELETE 模板)生效,create/link/delete 跳过;RLS 未配置时等价全可见;RLS/CLS 管理路由在 AIP 后台,不在 Foundry。
故事 2
只读三层过滤:amount 脱敏、customer_id 置 null、行级按区域过滤
场景:只读安全
角色:管理员 + 业务分析师
耗时:约 5 分钟
- 背景
- 管理员给分析师账号 lisi 配置了三条规则:RLS 只看得到 orders 中自己区域客户的订单;CLS 对 orders.amount 做脱敏(mask);属性权限里 lisi 对 orders.customer_id 无 Read。lisi 在对象查询里拉订单明细,想看看金额和客户。
- 传统做法对比
- 以前要么整张表开只读权限(裸数据裸奔),要么干脆不给查(业务没法用);现在同一查询按"行级 → 列级 → 属性级"三层自动过滤,能看的看、该藏的藏、不该给的不给。
- 角色
- 管理员(配 RLS/CLS/属性权限);业务分析师 lisi(消费查询结果)。
- 操作步骤
-
- 管理员配置 RLS(orders 按区域)、CLS(amount 脱敏)、属性权限(customer_id 无 Read)
- lisi 登录,在对象查询选择 order 对象,带 user_id 参数
- 提交查询,观察 amount / customer_id 输出
- 对照自己区域核对可见行
- 系统响应
- 查询返回时 amount 列输出脱敏表达式、customer_id 列为 null、行集被 RLS 过滤:
{
"code": 0,
"data": {
"columns": ["order_id", "amount", "customer_id", "status"],
"rows": [
[1, "9**", null, "shipped"],
[3, "19**", null, "shipped"]
]
}
}
翻译期把无 Read 属性替换为 NULL AS "customer_id",CLS 把 amount 换成 mask 表达式,RLS 追加 WHERE 只留可见行。
- 结果洞察
- 三条规则独立叠加、互不干扰:属性级 null 发生在翻译期、RLS/CLS 发生在 SQL 组装后;lisi 拿到的结果"能看趋势、看不到裸敏感值、看不到越权行"。指标 / OOL 查询同样走这套注入。
- 调整建议
- 敏感度高的列优先 CLS mask;查询字段尽量收敛,少拉无关列;分析师发现字段为 null 先查属性权限,别怀疑数据丢了。
- 动手试一试
- 页面路径:对象查询 → order。输入内容:配置 CLS/属性权限后以 lisi 查询。预期结果:amount 脱敏、customer_id 为 null、行集受 RLS 过滤。RLS/CLS 是字符串级改写,对复杂子查询注入位置可能不准。
- 限制提示
- 无 Read 属性返回 null 而不是整行拒绝;聚合查询对无 Read 列是"直接拒绝"而非隐藏;编辑态叠加的值不重新过 RLS/CLS。
故事 3
用术语表和分类标签,让"客单价"不再跟"平均订单金额"打架
场景:语义治理
角色:数据工程师 + 业务分析师
耗时:约 4 分钟
- 背景
- 月底复盘,销售说"客单价 1020 元",财务说"平均订单金额 890 元",两边数据对不上。数据工程师在 Foundry 数据治理页建术语"客单价",定义 = GMV/订单数,同义词"平均订单金额、AOV",关联到 order 对象的 amount 属性,并把 amount 打上 level=2"机密"分类。
- 传统做法对比
- 以前口径散落在 Excel、口头约定和旧报表里,对齐一次口径要开三次会;现在术语表 + 属性关联把"这个词什么意思"固化在平台里,任何人查属性治理汇总就能看到统一口径。
- 角色
- 数据工程师(建术语/分类、打标);业务分析师与财务(消费统一口径)。
- 操作步骤
-
- 在数据治理页建术语"客单价"(定义、同义词、状态 approved)
- 创建 level=2"机密"分类标签
- 把术语关联到 order.amount 属性,并给 amount 打"机密"标签
- 查看属性治理汇总,核对术语 + 分类
- 系统响应
- 创建术语返回
{code:0, data:{id:1}};汇总接口返回:{
"code": 0,
"data": {
"object_name": "order", "property_name": "amount", "data_type": "number",
"terms": [ { "name": "客单价", "abbreviation": "AOV",
"status": "approved", "definition": "GMV/订单数" } ],
"classifications": [ { "classification_name": "机密", "level": 2,
"color": "#e5533b", "applied_by": "zhang" } ]
}
}
重复关联同一属性返回 409;删除术语级联删除关联。
- 结果洞察
- 销售和财务在平台里查 amount 属性,看到的都是同一份术语定义与敏感度标注,口径之争有了唯一的"字典"。敏感度标签同时为后续 CLS 配置提供依据。
- 调整建议
- 核心属性都建术语并写定义;敏感属性按 level 0-3 打标;术语状态用 approved 发布后再对外引用。
- 动手试一试
- 页面路径:数据治理 → 术语表 / 分类标签。输入内容:建术语"客单价"关联 order.amount,建"机密"分类打标。预期结果:GET /governance/properties/2/3 汇总返回术语与分类。打标签不会自动隐藏数据,需另配 CLS。
- 限制提示
- 分类标签不会自动驱动访问控制(CLS 需管理员另行配置);保留策略只有 CRUD 不会真执行;demo 未预置治理示例,需手工造数。
故事 4
管道质量规则:外键缺失被记录,问题走确认 → 修复闭环
场景:质量规则
角色:数据工程师
耗时:约 6 分钟
- 背景
- 数据工程师建了一条把"脏订单"清洗进 orders 表的管道,并在数据质量页给管道挂了一条 referential 规则:
customer_id 必须在 customers 表中存在,severity=error。管道跑完后,发现确实有 2 行引用了不存在的客户。
- 传统做法对比
- 以前坏数据进了表,要等报表算出来才发现不对,定位问题靠 DBA 手工查一遍;现在质量规则挂在管道输出上,跑完自动检查、自动记 issue,带样本数据一眼看到问题。
- 角色
- 数据工程师(建管道 + 质量规则 + 修数据);运营(消费结果)。
- 操作步骤
-
- 在数据质量页创建 referential 规则(column=customer_id、ref_table=customers)挂到管道
- 手动运行管道(POST /pipelines/:id/run)
- 打开问题列表查看 open 问题与样本
- 修完数据后把问题标记 fix
- 系统响应
- 管道 run 返回 failed(error 级违规),问题列表出现 open 记录:
GET /quality/issues → {
"code": 0,
"data": { "issues": [
{ "id": 1, "rule_id": 1, "affected_table": "orders",
"affected_rows": { "count": 2,
"sample": [ { "customer_id": 99 }, { "customer_id": 88 } ] },
"status": "open" } ] } }
POST /quality/issues/1/fix 后状态变 fixed。
- 结果洞察
- 四类规则(null/format/unique/referential)自动生成检查 SQL 并返回 {Total, Passed, Failed, Sample≤10};severity=error 违规把 run 标 failed,但结果表数据照写("data written, issues isolated")。问题状态机 open → acknowledged → fixed 全程留痕。
- 调整建议
- 关键输出表挂 referential + null 规则;format 规则用正则校验字段格式;修复后把 issue 标记 fix 关闭;error 级规则建议配合人工门禁,别只靠 run 标红。
- 动手试一试
- 页面路径:数据质量 → 建规则 → 运行管道。输入内容:referential 规则(orders.customer_id → customers.customer_id)。预期结果:/quality/issues 出现 open 问题且带样本;error 级违规时 run 状态 failed。数据照写不隔离。
- 限制提示
- 质量规则只对 scope=pipeline 生效(scope=object 只 CRUD 不执行);unique/format 是整列拉内存比对,大表慎用;error 级不阻断落库。
常见问题
RLS / CLS 策略在哪里配置?
用户/角色/RLS/CLS 策略的管理路由在 AIP 安全后台(RolesPage / UsersPage / SecurityPage);Foundry 服务端只注册登录与 ABAC 策略路由,策略数据存同一套平台库。
属性被置为 null 是数据丢了吗?
不是。只读路径对无 Read 权限的属性列输出 NULL(而非整行拒绝);聚合查询则直接返回"禁止聚合"(422),因为聚合列 null 化会产生错误统计值。
记录级权限和 RLS 什么关系?
写路径不 SQL 改写,而是先按 RLS 数出"你能看到的行数",再和模板目标行数比对,相等才放行;RLS 未配置时等价全可见,因此策略要配在角色上才有效。
打了"机密"标签会自动隐藏数据吗?
不会。分类标签只做标注,访问控制需要管理员另行配置 CLS 策略;"打标即生效"的自动联动是待补齐能力。
质量规则能阻止坏数据落库吗?
当前不能完全阻止:error 级违规把 run 标 failed 并记 issue,但数据照写;需要隔离语义(未达标不落库)的部署场景,需等该能力补齐。
主题小结
一句话:Foundry 用"读三层过滤 + 写记录级兜底"管住数据可见与可改,用"术语表 + 分类 + 质量规则"把数据讲清楚、保得住。记住三件事:ABAC 尚未接入链路、打标签不会自动隐藏、质量不隔离(error 只标红)。