守护管道:事件层中的零信任
SchemaBridge Team · 2026-01-03 · Security, Zero Trust
保护长时间运行的工作流:仅凭引用的密钥、即时注入,以及零信任身份。
看不见的边界:为什么传统安全在事件层失效
在单体应用的世界里,安全很简单。你建起一座"堡垒"——在服务器外围架设防火墙。你掌控网络、硬件和软件。你在入口处使用身份提供商(IdP),请求一旦进入内部,就被视为"可信"。这就是 Castle-and-Moat(城堡与护城河)安全模型。
但随着我们进入分布式、长时间运行的业务生命周期时代——也就是我们所说的事件层——城墙已经崩塌。你的应用不再只存在于一个地方。它是由微服务、第三方 SaaS API 以及由外部 Webhook 触发的无头 worker 组成的集群。边界已不复存在。数据持续处于传输之中,被并非由你编写的代码转换,并存储在你无法完全掌控的数据库里。
在这种碎片化的格局下,旧的护城河毫无用处。我们需要一种新的安全范式,一种内建于引擎自身指令集中的范式。我们称之为事务性零信任。
安全噩梦:凭据泄露
作为架构师,你在事件层面临若干根本性的、关乎存亡的威胁。其中最关键的威胁之一就是凭据泄露。
集成离不开 API 密钥。你有 Stripe 密钥、Salesforce 令牌和内部数据库密码。在"胶水代码"脚本中,这些密钥往往存放在环境变量里,或在 JSON 负载中四处传递。如果某位开发者为了调试不小心加了一行 console.log(payload),或者你的日志系统遭到入侵,你最核心的生产密钥就会暴露在外。泄露和管理不善的凭据是云上安全事件的主要原因之一。
SchemaBridge 安全栈:基础设施层面的隔离
在 SchemaBridge,我们构建安全模型的方式是以基础设施约束来应对这些威胁,而不是仅仅依赖"良好的编码实践"。例如,租户脚本在 GraalVM 上运行,处于一个隔离的、不持有任何凭据且没有网络出口的脚本运行器中,因此脚本即使尝试,也无法触及你的密钥或平台的数据库。
零信任身份:超越 API 密钥
在分布式流程中,身份必须是动态且有范围限定的。让所有 worker 共用一个"root" API 密钥是灾难性的风险。
SchemaBridge 对凭据采用仅引用模型:
1. 加密密钥存储:你的生产 API 密钥从不存储在工作流配置或状态中。它们存放在加密的密钥存储(即我们的 EntitySecretRepository)中,静态数据使用 AES-256-GCM 加密,并支持密钥轮换。
2. 仅引用:在可视化图中,你只能看到按名称对密钥的引用(例如 {{ secrets.STRIPE_KEY }})。名称是刻意设计为静态的:不支持表达式,因为计算得出的名称会让负载得以选择读取哪个凭据。
3. 即时注入:只有在 Gateway Vertex 发送其 HTTP 请求时,引擎才会解析引用、解密令牌,并将其替换进出站请求的请求头或请求体中。配置表达式和脚本都无法读取密钥,具名密钥也绝不会被复制到 vertex 配置或工作流状态中。
{
"type": "GATEWAY",
"config": {
"url": "https://api.stripe.com/v1/refunds",
"method": "POST",
"headers": {
"Authorization": "Bearer {{ secrets.STRIPE_KEY }}"
}
}
}
此外还有几道防护栏:只有 bearer、API 密钥和请求头映射类型的密钥才可能离开平台(HMAC 签名密钥永远不会),并且工作流作者无法注入由平台管理的密钥。
一个示例:减少密钥泄露的支付聚合商
设想一家假想的支付聚合商,为庞大的商户群处理转账,并与少数几家支付服务商集成。
挑战
设想他们基于 Kubernetes Secrets 构建的旧系统,每个服务商密钥都作为环境变量加载到 Node.js worker 中。某天,一位开发者添加了一条调试日志,在某个失败请求上意外打印出了 process.env 对象。在这样的架构下,服务商密钥可能泄露到整个工程团队都能访问的 ELK 栈中——这是一次严重的安全事件,需要大规模的密钥轮换,并向监管机构提交正式报告。
SchemaBridge 的做法
现在设想同一个团队把支付流程迁移到 SchemaBridge。
1. 迁移到密钥存储:他们把服务商密钥迁入 SchemaBridge 密钥存储,每个凭据对应一个具名密钥。
2. 按名称引用:每个 Gateway vertex 都按名称({{ secrets.stripe-key }})引用其凭据,从不按值引用。
3. 更干净的日志:由于 Gateway 只在出站时才替换值,日志中只会显示密钥引用。即使开发者把某个步骤的整个负载记录到日志中,密钥的值也从未被放进去过。
可能的结果
- 安全态势:由于密钥被隔离在工作流配置和状态之外,通过日志和负载泄露凭据的可能性大大降低。但并非不可能:如果目标服务会回显请求头,密钥仍会出现在该步骤记录的输出中;此外,工作区管理员也可以有意地查看密钥。
- 运维速度:添加新的服务商凭据变成一项配置任务,而不再是一次 Kubernetes 密钥发布。
- 安心:日常调试不再意味着要接触明文凭据。
未来:零信任编排成为标准
我们预计在未来十年里,"Castle-and-Moat" 模型将彻底消失。分布式系统中的每一个 vertex 都将被视为其自身的微边界。安全将从一个"层"转变为指令本身的属性。
我们正朝着这个方向构建 SchemaBridge。通过将不可信代码的隔离(租户脚本运行在隔离的、不持有凭据且没有网络出口的运行器中)与仅引用的密钥注入相结合,我们的目标是让你能够构建复杂的集成,而无需把明文凭据交给每一个接触它们的组件。
安全编排专家清单
要构建一个"久经沙场"的事件层,请遵循以下三条不容妥协的规则:
1. 反转你的密钥:密钥永远不应存放在代码或工作流负载中。在尽可能晚的时刻才解析它们,并让它们远离任何会被记录到日志中的内容。
2. 最小权限访问:处理物流面单的 worker 不应持有你计费网关的 API 密钥。在平台允许的范围内,尽可能收窄凭据的作用范围。(在 SchemaBridge 中,密钥的作用范围是工作区,因此请使用不同的工作区来隔离那些不得共享凭据的职责。)
3. 审计每一次访问:作为一般实践,记录谁访问了哪个密钥以及原因;不可篡改的审计轨迹是取证调查中最好的防线。SchemaBridge 目前不会为每次密钥访问生成审计事件,因此如有需要,请配合你自己的管控措施使用。
结论:信任建立在基础设施之上,而非意图之上
你无法靠"培训"获得一个安全的系统。人为错误不可避免。真正的安全建立在结构性约束之上,让人难以无意间做错事。SchemaBridge 提供了其中的若干约束,让你可以专注于构建功能,同时减少凭据外泄的途径。
另请参阅:持久化延迟 —— 管理跨越数周乃至数月的基于时间的业务生命周期。