【免费下载链接】astron-rpa
Enterprise-grade desktop RPA client with a pluggable library of atomic capabilities, policy‑friendly packaging, and CI/CD‑friendly CLI. Integrates with leading Agent platforms and LLMs for end‑to‑end desktop/web automation. 这是一个镜像仓库,有issue、pr欢迎去github提交。
导读
本文以 backend/openapi-service/EXTERNAL_INTEGRATION_SECURITY.md 为主体,系统讲解 AstronRPA 面向外部 Agent 平台与 LLM 的集成安全边界:外部调用如何通过 API Key 完成身份认证、每类入口点被强制执行哪些资源权限、工作流能力边界如何收敛、API Key 生命周期如何管理,以及 n8n 社区节点应如何安全接入。读完本文,你将掌握 AstronRPA 的信任边界模型、授权矩阵、密钥轮换流程与 HTTPS 部署验收清单,能够在生产环境中正确、安全地开放 RPA 工作流的对外执行能力。
一、集成安全契约总体概览
AstronRPA(OpenAPI 服务)对外暴露两类传输通道,均受同一安全契约约束:
- MCP Streamable HTTP:主通道,承担工作流的发现(discovery)、执行(execution)与查询(query);
- REST:辅助通道,是显式的兼容性接口(compatibility interface)。
两条通道共享相同的认证、授权与执行记录机制。契约中有两条铁律:
- 单传输原则:认证失败或启动响应不确定(uncertain start response)时,禁止在另一条传输通道上重试启动同一任务;
- 单一身份源:外部调用只能携带一种明确的凭据,绝不接受"先用 API Key 失败、再回退到桌面会话身份"的双重身份语义。
从源码看,这一契约的落点非常明确:
- app/security/api_key.py 实现了统一凭据解析与 bcrypt 校验;
- app/security/mcp_auth.py 在请求进入 MCP SDK 之前完成 API Key 认证;
- app/security/workflow_authorization.py 为固定/动态 MCP 与外部 REST 提供共享的资源授权策略。
二、身份与信任边界(Identity and Trust Boundary)
2.1 凭据形态与校验规则
外部调用恰好使用以下两种凭据之一:
Authorization: Bearer <API_KEY>;X-API-Key: <API_KEY>。
两条传输通道使用同一个活跃密钥查找(active-key lookup)与 bcrypt 校验逻辑。凭据解析规则在 extract_api_key() 中实现:
- 重复或冲突的
Authorization头(多个值)→ 直接拒绝; - 格式错误的 Bearer 头(非两段、非
Bearer前缀、空值)→ 拒绝; - 重复的
X-API-Key头 → 拒绝; - REST 请求的
?key=URL 查询参数凭据 → 默认拒绝(allow_query_api_key=False); - 最终必须恰好得到一个凭据,多于或少于一个都会抛出
APIKeyAuthenticationError。
2.2 MCP URL Key 与迁移开关
MCP 通道的 URL 查询密钥默认关闭。配置项 MCP_ALLOW_QUERY_API_KEY=true 只是临时的、仅限 MCP 的迁移选项,不是生产环境推荐配置。理由在 app/config.py 的注释中写得很清楚:URL 查询串经常出现在浏览器历史与代理访问日志中,存在泄密风险。
认证存储故障(如数据库不可用)时统一返回 HTTP 503,且不泄露任何数据库细节(见 MCPAPIKeyAuthMiddleware:只记录异常类型名,不记录敏感异常文本)。
2.3 每次请求重新校验,无正向缓存
密钥在每一个请求上都重新校验,不存在"认证成功后缓存、吊销后仍存活"的正向认证缓存。这意味着:密钥被吊销后,即使请求发生在既有 HTTP 连接上,也会立即被拒绝。
2.4 桌面会话与网关身份剥离
桌面端的密钥管理、工作流发布走既有已认证的会话网关。OpenAPI 网关在认证前会剥离外来请求携带的 user_id、X-User-Id、user-info 请求头,只转发从既有 robot/auth 服务获得的身份。相关实现见 docker/volumes/nginx/lua/openapi_auth.lua:
ngx.req.clear_header("user_id")
ngx.req.clear_header("X-User-Id")
ngx.req.clear_header("user-info")
具体行为(见 gateway-routes.conf 与 app/dependencies/init.py):
- 外部入口(
/workflows/execute、/workflows/execute-async、/workflows/stop-current、/workflows/copy-workflow、/health/local-check、/health/remote-check、/executions/get、/executions/{id})→ 必须走 API Key 认证; - 混合入口(
/workflows/get、/workflows/get/{project_id})→ 若携带 API Key 凭据,一律以 API Key 身份读取,凭据无效时绝不回退到会话身份;无凭据时保留设计器的既有视图; - 管理路由(密钥创建/列表/吊销、工作流 upsert、Astron 凭据管理等)→ 只接受桌面会话身份,API Key 不能访问管理路由,也不能冒充桌面 WebSocket 连接。
2.5 端口私密性与信任边界
OpenAPI 容器端口必须保持私有(docker-compose 中端口被注释,仅通过网关暴露,见 docker/docker-compose.yml)。robot-service 的内部发布请求仍须在受信任服务网络上断言 user_id。如果直接公网暴露该端口,或用一个"转发调用方身份头"的替代代理,都会击穿该信任边界。升级时必须同时升级 OpenAPI 应用与其网关策略。
2.6 用户级绑定与租户隔离
OpenAPI 的密钥、工作流与执行记录目前绑定到 user_id,而非已验证的租户上下文(tenant context)。OpenAPI 不实现第二套账户体系,会话认证只提供既有身份。因此:
- 测试/生产环境、租户隔离应使用独立的身份与独立部署;
- 共享部署要求同一用户在两个租户持有不同授权,不在本契约支持范围内;
- 在请求数据里带上 tenant/user ID 并不构成授权。
三、当前授权矩阵(Current Authorization Matrix)
原文档给出的授权矩阵是理解整个安全模型的核心,完整继承如下:
| 入口点 | 身份 | 强制执行的资源权限 |
|---|---|---|
| 固定 MCP list/get | API Key | 属主、外部访问已启用、有效已发布版本;固定工具要求精确的 projectId |
| 动态 MCP discovery/call | API Key | 相同属主/开放发布策略;启动时重新校验 discovery 期间解析到的版本 |
| 固定 MCP / REST start | API Key | 授权项目/当前版本 + 已注册范围的准入(在创建记录/派发之前);仅限执行器;无委托的手机号身份 |
| MCP execution get/cancel / REST execution list/get | API Key | 执行属主与当前工作流属主、已启用外部访问、有效的已接受执行版本 |
| 带 API Key 的 REST workflow list/get | API Key | 当前属主开放的、已发布的工作流;遗留示例别名仅可解析到该属主授权副本 |
| 密钥 create/list/revoke、工作流 upsert、Astron 凭据管理 | 经私有网关的已认证桌面会话 | 当前用户;API Key 不能铸造密钥或授予外部工作流访问权 |
/workflows/stop-current | API Key | 仅针对已认证用户自己的客户端;无调用方可选目标身份 |
/health/remote-check | API Key | 只报告该用户客户端的存在;不启动工作 |
/health/local-check | API Key | 比较一个诊断客户端身份;提供的比较值不授权访问 |
/users/register、/users/get-key、跨用户复制/委托启动 | 已禁用 | 历史共享令牌/手机号查询不能证明委托授权 |
3.1 拒绝行为与错误语义
- 普通重新发布(republication)保留对已接受执行记录的访问;
- 外部访问吊销、工作流删除或属主变更 → 拒绝访问(包括 REST 列表计数);API Key 吊销 → 拒绝请求;
- 上述变更不会停止已经接受的(already accepted)任务;
- 缺失资源与不可见资源具有等价的拒绝行为;
- REST start 对不可用项目返回 404、对不允许的版本或执行模式返回 403;执行详情返回 404;工作流详情保留既有响应信封、资源不可用时无数据;
- MCP 工具拒绝使用
isError/安全业务错误,而不是 HTTP 授权状态码。
这些规则在源码中的落实可参看 require_workflow_access()(属主、状态、版本三重校验,抛出 WORKFLOW_NOT_FOUND/VERSION_NOT_ALLOWED),以及 workflows.py 中的 _execution_http_error()(CLIENT_OFFLINE/CLIENT_CAPABILITY_UNCONFIRMED → 503,CLIENT_PROTOCOL_UNSUPPORTED → 409,其余按 404/403 映射)。
3.2 用户级权限边界
API Key 当前是用户级权限,没有 per-key 作用域(scopes)或过期时间字段。属主显式开启外部访问,即把该发布版本的执行权授予属主自己的密钥。需要特别强调的是:
- 读取工作流元数据 ≠ 执行一个恰好做只读业务的工作流;
- MCP 工具注解(tool annotations)与 n8n 节点过滤不能约束服务端授权。
四、工作流能力边界(Workflow Capability Boundaries)
外部集成不是"一张工作流全开放"。能力按以下矩阵分级准入:
| 能力 | 集成要求 |
|---|---|
| 元数据读取 | 已认证属主 + 允许的工作流;不作为连接测试来执行 |
| 只读业务工作流 | 显式启用的发布版本、受控输入与外部凭据 |
| 外部写入 | 独立评审过的工作流/身份;用原始稳定业务键恢复不确定启动 |
| 文件 / Office | 授权文件句柄、访问限制与生命周期策略;无任意本地路径 |
| 桌面 / UI | 授权执行器、会话就绪、真实停止确认 |
| AI 自动调用 | 允许的工具/输入 + 独立授权;模型输出不是授权 |
| 高风险/不可逆工作 | 评审过的允许列表 + 人工审批或禁止自动调用 |
这些是准入要求(admission requirements),不是新实现的 per-key 能力作用域。管理员拥有的声明(declaration)会对已注册用户在固定 MCP、动态 MCP 与 REST 上施加额外准入检查。受支持的 JSON 与已声明秘密输入遵循 执行管理契约;文件与运行时对象仍不支持。运维人员只应发布其确实允许集成身份执行的工作流。
五、API Key 生命周期与迁移(Key Lifecycle and Migration)
5.1 创建与存储
通过已登录桌面设置创建密钥。只有创建响应会返回新的原始密钥;openapi_auth 只存储其哈希与 8 字符前缀。后续密钥列表返回掩码(如 prefix + "******************",见 api_key.py 服务层)。
原始密钥必须存放在调用方的凭据存储中(如 n8n Credentials),永远不要放进工作流 JSON、URL、源码或导出的示例里。实现上,密钥生成使用 secrets 随机 32 位大小写字母+数字,哈希使用 bcrypt(见 app/utils/api_key.py);校验时先按 8 字符前缀定位活跃记录,再执行 bcrypt 校验(见 validate_api_key())。该校验还会拒绝超过 72 字节的密钥,以避免 bcrypt 前缀截断造成的"长密钥前缀相同即通过"风险。
5.2 轮换流程(不启动任务)
- 为目标身份/环境创建新密钥;
- 用新 Credential 初始化 MCP,发现/读取授权工作流;
- 将调用方切换到新 Credential —— 空授权工作流列表是成功的认证结果,不是执行任务的理由;
- 通过属主会话吊销旧密钥;此后 MCP/REST 请求(包括既有 HTTP 连接上的请求)必须拒绝它。
保持新旧密钥重叠期短暂。若吊销前校验失败,保留旧 Credential 的同时修复配置。已吊销密钥不会由此流程重新激活:必要时再创建一个密钥。吊销阻止新请求,但不是执行取消;由于密钥没有自动过期,运维需自行安排轮换并显式吊销未使用/已泄露的密钥。
5.3 部署前需评审的兼容性变更
- API Key 无法访问会话管理端点或认证 WebSocket;
- 网关移除原始公共用户头与无效 Bearer 回退;
- REST start 不能再选择禁用/未发布/其他版本、编辑器执行或其他用户的手机号;未知顶层执行字段被拒绝,业务输入请放入
params; - 遗留共享令牌手机号密钥供给与跨用户复制返回拒绝;请使用已认证密钥管理,委托执行不受支持;
- 既有外部调用方在普通重新发布后仍可访问已接受的执行;吊销访问仍拒绝读取与取消——持有执行 ID 并不建立授权;
- 遗留用户供给可能在历史用户记录中存过明文
default_api_key。此变更阻断该公共供给路径,但不重写既有数据库行或备份。请清点受影响密钥、轮换/吊销它们,并按部署的数据保留策略清除过时的明文副本;不执行自动破坏性数据迁移。
per-key 作用域、自动过期、共享租户授权与委托身份均不由本契约提供。
六、n8n 凭据与接入(n8n Credentials)
6.1 凭据字段契约
| 字段 | 契约 |
|---|---|
| MCP Endpoint | 部署提供的完整 HTTPS URL,包含其配置路径;不要猜测或丢弃路径段 |
| API Key | 秘密凭据字段;标准 Bearer 头,绝不放进查询数据 |
| Protocol | MCP 2025-11-25 over Streamable HTTP;无自动协议升级/回退 |
6.2 节点行为要求
使用正常的证书链/主机名校验。Loopback/tunnel 传输仅用于开发测试环境,不是 Community Node 的要求。AstronRPA 社区节点提供凭据 UI,且所有业务操作均通过 MCP 完成;其 n8n SDK 依赖被限制在独立节点包内。
连接测试可以初始化 MCP、发现工具并执行一次授权读取,但不得调用 execute/stop、使用 REST 回退启动或自动重试启动。需要区分以下失败类别:
- 无效/已吊销密钥;
- TLS/网络失败;
- 协议不匹配;
- discovery 服务失败;
- 已认证但无可见工作流。
n8n 工作流只保留一个凭据引用(Credential reference)。实例加密密钥、凭据共享与加密备份属于 n8n 管理员职责范围。
七、部署与验收(Deployment and Acceptance)
7.1 HTTPS 部署前提
遵循 HTTPS 部署指南。部署方提供并维护服务器、DNS、证书/私钥及续期;项目方提供应用配置、镜像与文档。共享开发者证书与 SSH 隧道都不是生产依赖。
7.2 Casdoor 初始化与轮换
Casdoor 在首次初始化时生成独立签名密钥与应用 Secret,并在重启后保留。部署同步命令只把所选应用的 Secret 与公共签名证书复制进被 Git 忽略的 .env。从早期公共 bootstrap 密钥初始化的部署需要显式密钥/Secret 轮换与默认账户审查——仅更新 JSON 或网关 TLS 证书无法完成该轮换。详见 HTTPS 指南的"认证初始化/轮换"章节。
7.3 升级与回滚流程
- 升级前:备份部署配置,记录应用镜像与源码版本;保持客户端空闲;
- 网关策略与应用一起部署,校验渲染后的 nginx 配置,只 reload 本项目网关;
- 校验:登录、Secure cookie、WSS、MCP POST/SSE(需关闭缓冲——参见 gateway-routes.conf 中 MCP 位置的
proxy_buffering off); - 证书更换/续期后:重复信任/主机名校验,重连客户端/MCP 调用方;
- 回滚:使用项目保存的配置/镜像回滚;不要改动主机级代理/证书配置或无关服务;回滚安全代码也会恢复其旧暴露面,回滚期间必须隔离外部访问。
7.4 桌面客户端与 Scheduler 传输
- 桌面客户端须同步更新:其 Chromium 进程必须使用正常证书校验,移除历史全局证书错误旁路;
- Scheduler 的 remote transport 持有已验证的 HTTPS/WSS 连接;捆绑的本地 router 通过 loopback 连接该 transport 并继续路由本地模块;
- 不要将该二进制作为独立远程 TLS 客户端运行:其历史 transport 跳过证书校验;
- 配置的公共
remote_addr仍是部署 URL,无需 SSH 隧道; - 会话按配置的 origin 持久化在客户端工作目录的
.remote-cookies下;只有该 origin 的既有会话从.cookie.json迁移;上游 cookie 不委托给二进制的临时 loopback 身份; - 登出清空新存储(跨重启生效);损坏的本地会话数据被丢弃且不记录其内容,因此仍可重新登录;损坏的新存储不会恢复旧遗留凭据;两个会话存储路径均被 Git 排除;
- HTTP 与 WSS 请求不会携带会话凭据自动跟随重定向——请显式配置最终部署端点;
- HTTPS 网关监听器为 Casdoor 会话 cookie 添加
Secure/HttpOnly(含网关的 Casdoor 代理路径);显式遗留 HTTP 监听器保留既有 cookie 行为。
7.5 WebSocket 管理器兼容性
OpenAPI 的 WebSocket 管理器将每条收到的消息绑定到自己的处理程序(包括缓冲的 busy/success 回复)。这是对捆绑 rpawebsocket 1.0.7 监听器的兼容性修复,保留既有线上协议,不实现服务重启后的持久执行恢复。
7.6 验收标准
单元/ASGI 测试与隔离的 OpenResty 测试不构成生产 TLS 验收。部署验收要求真实的 HTTPS/WSS:
- 真实部署域名下的可信连接;
- 错误/过期证书的拒绝;
- 真实 n8n/桌面成功、业务失败、离线/busy 与超时/同 ID 续跑;
- 脱敏检查(redaction checks);
- 证书更换/恢复演练。
不可用条件记为 untested(未测试)。
7.7 日志与历史数据保护
- 审查网关/服务/客户端日志与 n8n 历史中的凭据和内部错误数据;
- 合法工作流结果可能包含业务机密:限制历史访问、保留与导出;
- 受管执行(managed execution)以持久幂等性、对账与已确认取消扩展本安全契约,见 执行管理;
- 取消使用与执行相同的执行属主、当前工作流属主/外部访问检查;
- 遗留客户端保留
supportsCancel=false;吊销密钥仍不能取消正在运行的工作。
八、安全模型的源码级印证
本契约并非纸面文档,仓库中的实现与测试均可验证:
- 认证:MCPAPIKeyAuthMiddleware 在每个 Streamable HTTP 请求进入 MCP SDK 前认证,失败统一 401(带
WWW-Authenticate: Bearer)或 503;REST 侧依赖get_user_id_from_api_key同样只接受头部凭据、绝不接受 URL key; - 授权:workflow_authorization.py 是固定/动态 MCP 与外部 REST 共享的资源策略,属主、状态、版本任一不满足即安全拒绝;
- 网关剥离:openapi_auth.lua 在转发前清除
user_id/X-User-Id/user-info,并区分外部入口、混合入口与会话入口; - 测试验证:test_external_security.py 使用真实模型与 MCP/REST 路由构建跨传输安全用例(属主/他者/已吊销密钥、启用/禁用/未发布工作流、旧版本执行等),test_mcp_auth.py 覆盖 MCP 认证边界。
结语
AstronRPA 的外部集成安全契约围绕一条主线展开:外部调用永远只信任 API Key 这一种身份,且每个入口点都有明确的最小权限。无论是通过 MCP 还是 REST 接入,认证失败、启动不确定、凭据冲突都遵循"拒绝并保持原状"的保守语义,绝不跨传输重试、绝不回退身份。配合上述密钥轮换、能力分级与 HTTPS 验收流程,运维人员可以把 RPA 能力安全、可控地开放给 n8n 等 Agent 平台,同时避免"模型输出即授权""凭据进 URL""执行 ID 即访问权"等常见集成误区。
【免费下载链接】astron-rpa
Enterprise-grade desktop RPA client with a pluggable library of atomic capabilities, policy‑friendly packaging, and CI/CD‑friendly CLI. Integrates with leading Agent platforms and LLMs for end‑to‑end desktop/web automation. 这是一个镜像仓库,有issue、pr欢迎去github提交。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



