侧边栏壁纸
  • 累计撰写 10 篇文章
  • 累计创建 36 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Foxglove + ROS 2 权限架构落地实践:分层设计与接口暴露边界

猿有味
2026-04-18 / 0 评论 / 2 点赞 / 5 阅读 / 0 字

摘要

上一篇文章 “别把 Foxglove 当权限系统:ROS 2 可视化平台最容易踩的一个坑” 先把一个最容易踩的坑说清楚了:别把 Foxglove 当权限系统。

这个判断说清以后,后面真正要落地的,其实就剩两件事:

  • 权限到底该分几层
  • 哪些接口可以给 Foxglove,哪些接口不要直接给

所以这一篇不再重复上一篇那套判断过程,直接往下讲:架构怎么拆,角色怎么压,接口边界怎么收。

如果你的项目已经进入远程调试、多人协作、客户演示或者上线运维阶段,这两件事最好早点定下来。很多系统不是完全不能用,而是控制面和观测面一开始就没分开,后面越补越乱。

一、职责拆分

Foxglove + ROS 2 这套东西里,最容易混在一起的,通常是下面 4 件事:

  • 谁能接进来
  • 接进来以后能碰哪些 ROS 接口
  • 节点之间到底有没有硬权限边界
  • 当前这个动作在业务上该不该执行

这 4 件事如果全压在一层上,最后大多会变成:

  • 前端在做显隐
  • foxglove_bridge 在做一点收口
  • 底层接口还是直接暴露着

更稳的做法,是先把这些问题各归各位,别继续混着处理。

flowchart TD A[谁能进来] --> A1[接入层] A1 --> A2[认证网关] A1 --> A3[会话与审计] B[能碰哪些接口] --> B1[Bridge 层] B1 --> B2[topic / service / param 白名单] B1 --> B3[capabilities 收口] C[节点本身有没有权访问] --> C1[ROS 2 安全层] C1 --> C2[SROS2 / DDS Security] D[当前动作该不该执行] --> D1[业务代理层] D1 --> D2[状态校验] D1 --> D3[互锁 / 二次确认 / 审计]

二、四层分工

1. 接入层

这一层只回答一件事:谁能进。

它通常关心这些事:

  • 用户是否登录
  • 属于哪个角色
  • 能访问哪台机器人
  • 是否来自允许的网络
  • 是否要走 HTTPS / WSS
  • 是否记录访问审计

这一层一般落在:

  • Nginx / OpenResty
  • JWT / Session
  • OIDC / OAuth2
  • VPN 或零信任入口

这里重点不在 ROS 2,而在统一接入。

如果 Foxglove 直接裸暴露到外面,后面再补角色、审计和来源控制,基本都会很别扭。

2. Bridge 层

这一层只负责一件事:桥接层收口。

也就是决定 ROS 2 这一侧哪些内容可以被桥到 WebSocket,例如:

  • topic_whitelist
  • service_whitelist
  • param_whitelist
  • client_topic_whitelist
  • capabilities
  • address
  • tls
  • asset_uri_allowlist

这一层该做的,是先把暴露面收紧,不是自己去扛完整权限系统。

工程上更实用的做法就三条:

  • 默认最小暴露
  • 默认只读优先
  • 不把危险底层接口直接桥出去

3. ROS 2 安全层

这一层回答的是:节点本身有没有权访问。

如果项目后面要交付、远程运维或者长期上线,那单靠前端显隐和 bridge 白名单通常不够,还是得回到 SROS2 / DDS Security 这一层来兜底。

它解决的是这类问题:

  • foxglove_bridge 所在节点能不能访问某些 Topic
  • UI 代理节点能不能调某些 Service
  • 核心控制节点是否只接受受控节点的访问
  • 某个部署单元是否持有不该持有的安全制品

说白一点,就是上层即使配错了,底层也不能默认裸着。

4. 业务代理层

这一层最容易被低估,但其实最关键。

因为很多动作就算接口上允许,也不代表当前就该执行,比如:

  • 启动任务
  • 暂停任务
  • 恢复任务
  • 取消任务
  • 手动点动
  • 设置初始位姿
  • 故障恢复

这些动作通常还要看:

  • 当前是不是自动模式
  • 任务是否正在运行
  • 是否存在故障锁
  • 是否满足互锁条件
  • 是否需要二次确认
  • 是否需要审计留痕

所以更稳的做法,不是让 Foxglove 直接碰底层,而是只让它调用高层业务接口。真正执不执行,由代理节点判断。

三、角色划分

很多项目一上来就想把 RBAC 做得很细,结果菜单权限、接口权限、节点权限和业务状态全缠到一起。

更实用的起点,通常是先压成 3 类。

flowchart TD A[Viewer 只读] B[Operator 操作] C[Admin 维护] A --> A1[只看状态与画面] A --> A2[不能 publish] A --> A3[不能调 service] A --> A4[不能改参数] B --> B1[可执行高层业务动作] B --> B2[可暂停/恢复/取消任务] B --> B3[可有限手动控制] B --> B4[不能直控底层] C --> C1[短时维护授权] C --> C2[有限参数调整] C --> C3[诊断与恢复] C --> C4[全量审计]

1. Viewer

这一类就进观测面。

通常允许:

  • 看地图、TF、视频
  • 看点云、激光
  • 看诊断信息
  • 看运行状态
  • 看日志趋势

通常不允许:

  • 主动 publish
  • service
  • parameter
  • 执行控制动作

如果场景是看板、客户演示、远程观察,这一类角色往往最省心,因为它根本不进控制面。

2. Operator

这是最常见的业务角色。

通常允许:

  • 启动任务
  • 暂停任务
  • 恢复任务
  • 取消任务
  • 下发高层目标
  • 做有限手动点动

但这里关键不在“给不给控制”,而在:

只能碰高层业务接口,不能直通底层接口。

也就是说,给它的是:

  • /ui/start_task
  • /ui/pause_task
  • /ui/resume_task
  • /ui/cancel_task
  • /ui/manual_jog
  • /ui/set_initial_pose

而不是:

  • /cmd_vel
  • 原始电机使能
  • 原始设备控制
  • 底层驱动 service

3. Admin

这一层不是让管理员永久常驻最高权限,而是给维护、恢复、校准这些场景做短时放权

通常允许:

  • 调诊断类 service
  • 读写有限参数
  • 执行恢复类操作
  • 查看更完整的内部状态

但最好同时带上:

  • 审计日志
  • 权限过期
  • 二次确认
  • 与普通操作角色隔离

很多系统最后边界失守,不是因为完全没做权限,而是管理员权限长期常开。

四、接口划分

真到落地的时候,最值得单独整理的,往往不是角色表,而是接口清单。

1. 适合直接暴露给 Foxglove

这类接口主要承担观测作用,通常可以直接进 bridge 白名单:

  • /tf
  • /tf_static
  • /map
  • /odom
  • /scan
  • /pointcloud
  • /camera/*
  • /diagnostics
  • /robot_status
  • /battery_state

它们有个共同点:主要用于可视化、诊断和观测,不直接进入危险控制链路。

2. 适合暴露给前端,但要经过代理层的

这类接口可以给操作角色,但建议都先收口成高层业务入口:

  • /ui/start_task
  • /ui/pause_task
  • /ui/resume_task
  • /ui/cancel_task
  • /ui/manual_jog
  • /ui/set_initial_pose

这样做的好处很直接:

  • 语义清晰
  • 便于做状态校验
  • 便于做角色区分
  • 便于做审计
  • 后续扩展成本低

3. 不建议直接暴露给 Foxglove

这类接口建议默认按高风险处理。

底盘原始控制
  • /cmd_vel
  • 原始速度命令
  • 电机使能 / 失能
  • 控制器底层 service
设备原始执行
  • 叉齿原始升降控制
  • 液压原始控制
  • 原始继电器输出
  • 原始 I/O 输出
总线与驱动透传
  • CAN 原始透传
  • 串口透传
  • 驱动层调试 service
核心参数直改
  • 核心 PID
  • 安全阈值
  • 控制模式参数
  • 关键定位参数

很多风险不是来自那些一眼就很危险的接口,而是来自调试阶段顺手开出来、后面一直没收回去的接口。

这类接口一旦给前端直通,Foxglove 在事实上就已经进控制面了。

五、推荐链路

很多项目早期是这样接的:

flowchart LR A[Foxglove Client] --> B[foxglove_bridge] B --> C[""/cmd_vel] B --> D[""/goal_pose] B --> E[底层 Service] B --> F[参数读写]

它能跑,但问题也很明显:

  • 前端直接碰底层
  • bridge 事实上成了控制面
  • 角色边界和业务边界混在一起
  • 很难做审计
  • 很难做状态互锁

上一篇已经给过一张总览图:认证网关 -> foxglove_bridge -> UI代理节点 -> 核心 ROS 2 节点

把那张总览图往下展开,尤其是把 bridge 后面到底接什么、UI 代理节点内部再怎么分,链路更接近下面这种:

flowchart LR A[Foxglove Client] --> B[认证网关] B --> C[foxglove_bridge] C --> L[状态类 Topic] C --> D[""/ui/start_task] C --> E[""/ui/manual_jog] C --> F[""/ui/set_initial_pose] D --> G[UI 代理节点] E --> G F --> G G --> H[导航节点] G --> I[底盘控制节点] G --> J[设备控制节点] G --> M[审计日志] H --> K[SROS2 / DDS Security] I --> K J --> K

这套结构里,每一层干的事都比较清楚:

  • 认证网关决定谁能进
  • foxglove_bridge 决定桥接层暴露什么
  • UI 代理节点决定当前动作是否允许执行
  • 核心 ROS 2 节点只接受受控调用
  • SROS2 / DDS Security 继续提供节点级硬边界

六、落地顺序

如果你现在项目里已经用了 Foxglove,但权限边界还比较粗,建议按这个顺序往回收:

  1. 先把 foxglove_bridge 从“默认全开”改成“默认从严”。
  2. 先分开观测接口和控制接口,不要继续混在一个暴露面里。
  3. 不要再让前端直接碰 /cmd_vel、原始控制 service 和核心参数写接口。
  4. 把高风险动作改成经过业务代理节点,由状态机、互锁和审计去兜底。
  5. 再规划 SROS2 / DDS Security,把节点级硬权限补上。
  6. 如果需要远程接入,把监听地址、网络边界和 TLS / WSS 一起收紧。

这几步不一定一次做完,但顺序最好别反。

先收 bridge 暴露面,再收业务入口,再补节点级硬边界,这样返工最少。

七、小结

上一篇解决的是“别放错位置”,这一篇解决的是“放对以后怎么收”。

核心其实就这 4 句:

  • 接入层解决谁能进
  • bridge 层解决暴露什么
  • ROS 2 安全层解决节点本身有没有权访问
  • 业务代理层解决当前动作该不该执行

如果再压成一句话,就是:

Foxglove 适合做观测入口和桥接收口,不适合直接进入底层控制面。

如果你现在的系统还是“登录后直接进 Foxglove,按钮显隐当权限,底层接口顺手桥出去”,那它大概率还停留在能跑阶段,离适合上线还差一截。

下一篇我会继续往下走,不再停留在分层判断,而是直接进实战,重点会放在这几件事上:

  • foxglove_bridge 的配置原则怎么定
  • 节点分层到底怎么落
  • 高风险动作怎么做代理
  • 哪些接口该桥,哪些接口该隔离

参考

  1. foxglove_bridge 文档(ROS 2 Humble)
  2. ROS 2 Security:Introducing ROS 2 security
  3. ROS 2 Security:Access Controls
  4. ROS 2 Security:Deployment Guidelines
2

评论区