同一个数据表,用Spark查和用DuckDB查,结果可能不一样。这不是bug,是治理责任该由谁扛的问题。

Apache Iceberg社区最近给REST Catalog加了两样东西:读限制(read restrictions)和目录标签(catalog labels)。前者解决引擎和目录之间的权限执行归属,后者解决多个目录之间的治理上下文怎么传递。

打开网易新闻 查看精彩图片

三种责任,两种分法

任何一次受治理的数据查询,都有三件事要发生:目录拿到请求方身份、评估策略、把结果落到数据上。这三步放在哪执行,决定了两种架构。

集中式执行,三步全留在目录自己的环境里。Databricks的做法是把查询透明地路由到一个安全过滤集群,在数据交给外部引擎之前先做净化。Unity Catalog的跨引擎ABAC就是把过滤集群藏在Iceberg REST Catalog的scan/plan API后面。

委托式执行,目录只负责识别身份和评估策略,然后把行、列限制交给一个它信任的引擎去执行。这里的"信任"有明确含义:目录能指望这个引擎真的执行限制,用户绕不过去。

Spark和DuckDB在用户能控制运行时的情况下属于不可信引擎——用户可以执行任意代码,或者直接去读底层数据。配置得当的Trino部署则是可信引擎的例子,因为它原生支持行过滤和列掩码。

引擎拿到的不是策略,是结果

委托式执行需要目录和引擎之间有份共同契约,读限制就是这份契约。

读取方通过Iceberg REST Catalog加载表时,目录针对请求主体和请求上下文评估适用策略,返回所需的列投影动作和行过滤表达式,可信引擎在读取时必须应用这些限制。

有两个设计决定值得注意。

第一,引擎拿不到管理员定义的那条策略原文,拿到的是针对某个具体主体的执行结果,以过滤或掩码指令的形式呈现。初始规范定义了一套有边界的词汇表:九种预定义列投影动作,以及标准化的行过滤表达式,比如比较或集合成员判断。

很多企业级策略依赖子查询、查找表或自定义UDF,这些表达不进读限制的词汇表。含义很直接:只有当目录能把策略结果归约到标准定义的词汇表里,这条策略才能被表达出来,否则策略语义就丢了。

第二,规范定义了可信引擎必须执行什么,但没定义目录怎么建立这份信任。客户端自己声称可信不算数,系统管理员和实现方必须用适合自己环境的安全机制。Iceberg社区讨论过mTLS和OAuth这类机制,但信任最终留在协议之外。

读限制最适合的场景是引擎直连目录,且源目录的策略足够简单、有可信引擎能执行最终决策。还有不少实现问题悬着:引擎怎么安全地传递终端用户的身份和属性,目录怎么区分用户本人和代表用户行事的引擎,凭证怎么绑定到预期接收方。

目录之间怎么交换治理上下文

目录标签解决的是另一个场景:联邦目录之间的治理。

很多企业现在通过联邦和开放API连接多个目录,比如Unity Catalog、Snowflake、AWS Lake Formation和Google Cloud Knowledge Catalog。这比引擎到目录的集成更复杂,因为每个目录用各自的身份模型、策略语言和语义服务自己的用户、应用和引擎。

目录标签允许目录之间通过开放API在表和列级别交换轻量级的键值元数据。标签可以标明某个字段含PII,可以把数据集关联到某个业务域,也可以给AI模型提供语义提示。因为这个提案足够通用,标签能支撑的不只是访问控制,还包括发现、归属、成本归因、AI上下文和数据质量。

当消费方目录通过目录联邦从生产方目录加载一张表时,生产方目录返回表和列级别的标签。消费方目录把这些标签映射进自己的分类、属性或原生标签模型,然后用自己原生的身份和策略来评估访问。