Broker 配置
权威配置参考

Broker 管理和投递配置

运行中的 PSSP Broker 独立完成客户端认证、主题/投递授权和 SQLite 管理。WebService 与其他开通服务只能调用加密的管理监听器。

单 Broker 架构

此实现明确不支持 Broker 集群、复制、仲裁、分区所有权或跨节点协调。运行一个权威的低延迟 Broker,并让多个远程 worker/客户端实例连接它。可以部署多个 WebService worker,但不能部署多个 Broker 副本。

安全与存储边界

组件知道什么禁止做什么
PSSP BrokerSQLite 路径、Argon2id 哈希、ACL、订阅投递授权、管理服务白名单、审计调用方。调用 WebService 或解析业务负载。
WebService管理主机/端口、自身 service ID 和 Ed25519 私钥、固定的 Broker 管理公钥。打开 SQLite、获取 SQLite 路径、启动 Broker 二进制文件或验证 PSSP 客户端密码。
PSSP 客户端/worker一次性的 client ID、用户名、密码、普通 PSSP 地址和数据面 Broker 公钥。自行提升为未授权的投递模式/worker 组,或创建其他主体。

Broker 运行期间会独占锁定 <sqlite_path>.lock。此时离线管理命令会失败。setup 是唯一引导例外,必须在 serve 之前执行。

管理 TOML 示例

普通 PSSP 数据面和管理面必须使用不同的 X25519 私钥。完整样例位于 broker/config/pssp.aes-only.example.toml

[management]
enabled = true
bind = "127.0.0.1:6690"
encryption_enabled = true
static_private_key = "替换为管理面_X25519_私钥"
max_request_bytes = 65536
authentication_timeout_seconds = 10
request_timeout_seconds = 15

[[management.allowed_services]]
service_id = "oxrecorder-webservice"
enabled = true
ed25519_public_key = "替换为32字节Ed25519原始公钥的base64url"
permissions = ["principal.provision", "principal.delete"]
principal_kinds = ["device"]
client_id_patterns = ["ox-device-*"]
username_patterns = ["device-*"]
allowed_delivery_modes = ["broadcast"]
allowed_share_groups = []
publish_topic_patterns = [
  "/api/devices/*/heartbeat",
  "/api/devices/*/audio/chunks",
]
subscribe_topic_patterns = ["/api/devices/*/commands"]

字段含义

字段含义
bind独立管理监听地址。建议仅绑定回环或受防火墙保护的管理网络。
encryption_enabled必须为 true。管理面使用 X25519/HKDF 和 AES-256-GCM,不依赖 TLS。
static_private_key32 字节 X25519 私钥的无填充 base64url;必须与数据面私钥不同。
service_id稳定的应用身份,包含在签名挑战和凭据审计 actor 中。
ed25519_public_key服务 Ed25519 原始 32 字节公钥。对应私钥只保存在该服务中。
permissions允许 principal.provision 和/或 principal.delete
principal_kinds服务可创建的主体类型。管理面永远禁止创建 administrator
client_id_patterns/username_patterns简单 glob 白名单,* 匹配零个或多个字符。
allowed_delivery_modes允许 broadcastshared 或两者。
allowed_share_groups服务可以分配的准确 worker 组名称。
主题 pattern单独的 * 匹配一个具体主题段。授权 worker 的通配过滤器时使用字面量 +。禁止扩大为 #

密钥生成

# 分别生成数据面和管理面 X25519 私钥
pssp-broker generate-aes-only-private-key
pssp-broker generate-aes-only-private-key

# 从受保护的私钥文件派生管理公钥,供调用方固定
pssp-broker aes-only-public-key \
  --private-key-file /run/secrets/pssp-management-x25519

# 为 WebService 生成 Ed25519 身份;命令写入 0600 PKCS#8 PEM,
# 并直接打印 TOML 所需的原始公钥 base64url
pssp-broker generate-management-service-key \
  --private-key-file /run/secrets/pssp-webservice-ed25519.pem

# 以后可安全地再次输出公钥
pssp-broker management-service-public-key \
  --private-key-file /run/secrets/pssp-webservice-ed25519.pem

服务私钥不能写入 Broker TOML;Broker 私钥不能写入 WebService 环境变量。只能通过可信部署渠道分发公钥 pin。

管理认证流程

  1. Broker 发送随机 challenge 和管理 X25519 公钥。
  2. 服务检查公钥 pin,生成临时 X25519 密钥和 salt,并使用 Ed25519 签署 service ID、challenge、时间戳、临时公钥和 salt。
  3. Broker 查找准确且启用的服务,验证签名和 ±30 秒时钟偏差,然后通过 X25519/HKDF-SHA256 派生会话密钥。
  4. 后续帧使用带序列号的 AES-256-GCM。重放、乱序、修改、错误签名、未知或禁用服务都会被拒绝。
  5. 每个请求还会检查 permission、主体类型、身份 pattern、主题、投递模式和 worker 组,然后才进入 Broker 内部事务。

开通成功时,Broker 原子地创建/轮换主体、替换 ACL 与投递授权,只保存 Argon2id 密码哈希,在审计中记录已认证的 service_id,并且只返回一次明文密码。

旧管理客户端如果省略 deliveryGrants,Broker 会为订阅 ACL 创建广播授权;共享 worker 必须明确发送投递授权。普通 PSSP 客户端若省略 shareGroup,且该过滤器只有一个授权,Broker 会自动使用该授权,客户端无法覆盖它。

workerID、共享 worker 与广播客户端

clientId 用于认证与授权;workerIDSUBSCRIBE 中持久 ACK/恢复身份;connection ID 只代表当前 TCP 会话;shareGroup 代表竞争 worker 组,但 Broker 只有在数据库存在准确投递授权时才接受。

连接workerID授权每条消息
Aaudio-worker-ashared / audio-workers三个共享 worker 之一。
Baudio-worker-bshared / audio-workers三个共享 worker 之一。
Caudio-worker-cshared / audio-workers三个共享 worker 之一。
Dviewer-dbroadcast总是收到独立副本。

对于 A/B/C/D,Broker 通过本地轮询只把消息发给 A、B、C 中一个,同时也给 D 一份。A/B/C 共享一个组游标;选中的 worker 在 MSGACK 前断开时,Broker 会把未确认 QoS 1 消息重新投递给另一个在线组成员。D 的游标由自己的 workerID 标识,可使用 from: "resume" 重连。

多个广播 workerID 各自收到一份;不同共享组各收到一份。worker 不能去掉配置组来获得广播权限,viewer 也不能自行加入 worker 组。投递是至少一次,因此 worker 必须实现幂等处理。慢客户端不会阻塞 publisher ACK 或其他订阅者。

兼容期

Broker 暂时接受旧的 subscriberId 作为输入别名。更新后的客户端发送 workerID,新集成必须使用 workerID

WebService 环境配置

PSSP_DEVICE_PROVISIONING_ENABLED=true
PSSP_MANAGEMENT_HOST=127.0.0.1
PSSP_MANAGEMENT_PORT=6690
PSSP_MANAGEMENT_SERVICE_ID=oxrecorder-webservice
PSSP_MANAGEMENT_PRIVATE_KEY_FILE=/run/secrets/pssp-webservice-ed25519.pem
PSSP_MANAGEMENT_BROKER_PUBLIC_KEY=固定的管理X25519公钥
PSSP_MANAGEMENT_TIMEOUT_MS=15000

POST /api/me/devices 完成注册后,WebService 请求 Broker 创建一个设备主体,并向设备返回 pssp_client_idpssp_username 和一次性的 pssp_password。WebService 不保存明文密码。删除设备时通过同一管理监听器发送 deletePrincipal

旧的 PSSP_BROKER_BINARYPSSP_BROKER_CONFIGPSSP_BROKER_WORKING_DIRECTORY 已移除,不应恢复。

初始化与迁移

  1. 备份 SQLite 并停止旧 Broker。
  2. 在受保护 TOML 中加入管理配置与明确服务白名单,分别安装各类私钥。
  3. 新数据库先运行 setup,然后启动 serve
  4. Schema v1 启动时迁移到 v2,并为已有订阅 ACL 创建广播投递授权。
  5. 更新并重启 WebService,确认它没有 Broker 二进制、TOML 或 SQLite 路径。
  6. 通过另一个获授权的部署控制器开通 worker;每个实例使用唯一 workerID,同类实例使用相同已授权 shareGroup

故障排查

现象检查项
管理连接立即拒绝service ID 是否存在/启用;Ed25519 密钥是否匹配;系统时钟偏差是否小于 30 秒。
Broker 公钥 pin 不匹配WebService pin 必须从 management.static_private_key 派生,不能绕过检查。
management_not_authorizedpermission、主体类型、身份 pattern、主题、投递模式或组超出服务范围。
subscription_delivery_not_authorized主体没有“过滤器 + 广播/共享组”的准确结构化授权。
离线 CLI 提示 Broker 占用 SQLite这是预期保护;使用管理 API,或仅在批准维护时停止 Broker。
A/B/C 只有一个收到消息同一共享组的预期行为。D 需要独立广播授权。
故障后出现重复处理至少一次语义的预期结果;按主题序号或业务消息 ID 去重。