Skip to content

客户端授权

客户端通过认证后,FlowMQ 对其发布、订阅、消费等每一次操作执行授权校验,仅放行策略允许的操作。

授权采用基于**策略(Policy)**的模型:每条策略声明哪些身份可以对哪些资源执行哪些动作,以及允许还是拒绝。授权配置与策略均按命名空间隔离,不同租户互不影响。

按命名空间启用

授权配置是按命名空间独立的,包含两个开关:

配置项说明默认值
enabled是否对该命名空间启用授权校验。关闭时放行所有操作关闭
deny_if_no_match没有任何策略匹配时是否拒绝:true 拒绝(安全默认),false 放行true

授权默认关闭,确保开箱即用;管理员可随时为某个命名空间开启,配置动态生效并持久化保存,无需重启。

TIP

deny_if_no_match 在认证关闭(匿名接入)的协议上尤为重要:若 enabled=truedeny_if_no_match=true,在没有匹配策略时所有操作都会被拒绝。此时应将 deny_if_no_match 设为 false,或显式编写允许匿名身份的策略。

策略模型

一条策略包含以下要素:

字段说明
effect决策效果:ALLOW(允许)或 DENY(拒绝)
actions适用的动作列表(见下表)
resources适用的资源列表(类型 + 名称 + 匹配方式)
principals适用的身份:可按用户 ID、认证器、属性等条件选择,或匹配全部
enabled该策略是否生效

资源类型

资源类型按各协议的用户心智划分:

资源类型对应协议含义
topicMQTT / NATSMQTT 主题 / NATS subject
streamKafkaKafka 主题
queueAMQPAMQP 队列
exchangeAMQPAMQP 交换机
consumer-groupKafkaKafka 消费组

INFO

目前授权校验在 MQTT、Kafka、NATS 的发布/订阅/消费路径上强制执行;queueexchangeconsumer-group 等资源类型已纳入模型,对应的策略执行将逐步完善。

动作

动作说明
ALL匹配所有动作
READ读取(订阅 / 消费)
WRITE写入(发布 / 生产)
CREATE创建资源
DELETE删除资源
DESCRIBE查询元数据
ALTER修改配置
LIST列举

各协议操作到动作的映射示例:

协议操作资源类型动作
MQTT 发布topicWRITE
MQTT 订阅topicREAD
Kafka 生产(Produce)streamWRITE
Kafka 消费(Fetch)streamREAD
Kafka 创建主题streamCREATE
Kafka 删除主题streamDELETE

资源匹配方式

策略资源的 match 字段决定资源名的匹配方式,取值为 filter(默认)或 literal。订阅类操作的请求资源名可能是带通配符的过滤器(如 MQTT SUBSCRIBE foo/#),发布/生产类操作的请求资源名是具体主题,filter 模式对两者的处理不同。

filter(过滤器,默认)

将资源名作为主题过滤器解释,+# 按 MQTT 通配规则展开。匹配条件按 effect 区分:

effect匹配条件含义
ALLOW策略过滤器覆盖请求过滤器请求可能命中的每个主题都在策略允许范围内
DENY策略过滤器与请求过滤器相交存在至少一个被两者同时命中的主题

对具体主题(发布/生产)的请求,“覆盖”与“相交”等价,即过滤器是否匹配该主题。示例:

  • ALLOW filter foo/+ 不放行 SUBSCRIBE foo/#foo/# 可命中 foo/a/b,超出 foo/+ 的范围。
  • DENY filter secret/# 拒绝 SUBSCRIBE #:两者相交。

literal(精确)

将资源名作为普通字符串精确匹配,+# 视为字面字符而非通配符。literal foo/# 仅匹配资源名恰好为 foo/# 的请求,不匹配 foo/+foo/bar

literal 用于精确禁止某个过宽的订阅。例如,放行对 foo/ 子树的订阅,同时禁止一次性订阅整棵子树 foo/#

ALLOW   filter    foo/#
DENY    literal   foo/#

此时客户端可订阅 foo/+foo/bar 等,而 SUBSCRIBE foo/# 被 DENY 精确拦截(显式拒绝优先)。

动态占位符

资源名中可使用占位符,在裁决时按当次连接的身份与连接信息展开,从而用一条策略覆盖“每个用户只能访问以自己命名的主题”这类规则:

占位符含义
${principal.id}身份标识
${principal.authenticator}通过认证的认证器实例名
${principal.authenticatorType}认证器类型(如 passwordwebhook
${principal.attributes.<名称>}身份属性中的指定项(如 Webhook 下发的属性)
${connection.clientId}协议层客户端标识
${connection.sourceIP}客户端 IP
${connection.protocol}协议名

例如 ALLOW WRITE topic filter user/${principal.id}/#,让每个身份只能向以自身 ID 为前缀的主题发布。取不到的占位符展开为空串。

身份选择(principals)

principals 决定一条策略对哪些身份生效,由以下条件组合:

字段说明
alltrue 时匹配所有身份,忽略其余条件
ids身份标识列表,支持通配符(glob),命中任一即可
authenticators认证器列表(类型 + 名称),须精确命中其一;用于“仅对某认证器认证的身份生效”
attributes属性约束:属性名 → 允许值列表。身份须具备该属性,且取值命中列表之一

匹配规则:

  • all=true 时直接匹配全部身份。
  • 否则,每个非空条件都是一道必须通过的约束(条件之间为“且”);某个条件留空表示不在该维度设限。
  • attributes 中多个属性之间为“且”,同一属性的多个允许值之间为“或”;允许值列表为空表示只要求该属性存在。
  • all=falseidsauthenticatorsattributes 全部为空,则不匹配任何身份。

决策流程

对每一次操作,FlowMQ 按如下顺序裁决:

  1. 若该命名空间未启用授权(enabled=false),直接放行。
  2. 在匹配该身份与资源的策略中,只要存在一条 DENY,立即拒绝(显式拒绝优先)。
  3. 若存在匹配的 ALLOW 策略,则放行。
  4. 没有任何策略匹配时,按命名空间的 deny_if_no_match 裁决:true 拒绝,false 放行。

跨协议资源语义

授权资源按协议独立:MQTT 使用 topic,Kafka 使用 stream,二者互不影响。跨协议互通在路由层通过主题过滤器绑定配置,不共享授权资源。

订阅相关的两条补充规则:

  • 共享订阅按其底层主题过滤器授权,与普通订阅一致。
  • 订阅请求的过滤器不得宽于策略允许的范围,否则订阅被拒绝。

通过 API 管理

策略与授权配置可通过管理 API 维护,基础路由为 /v1/namespaces/{ns}/authorization{ns} 为命名空间,默认 default)。

方法路径说明
GET/policies分页列出策略(cursorlimit
GET/policies/{name}查看单条策略
POST/policies创建策略
PUT/policies/{name}更新策略
DELETE/policies/{name}删除策略
GET/config查看授权配置(enableddeny_if_no_match
PUT/config设置授权配置

策略的 JSON 字段:

字段类型说明
namestring策略名(唯一标识,1–256 字符)
descriptionstring备注
effectstringALLOWDENY,默认 ALLOW
enabledbool是否生效,默认 true
actionsarray<string>动作列表(READWRITEALL 等)
resourcesarray资源列表,每项含 typenamematch
principals_allbool是否匹配所有身份,默认 true
principal_idsarray<string>身份标识列表(支持通配符)
principal_authenticatorsarray认证器列表,每项含 typename
principal_attributesmap<string, array<string>>属性约束

创建策略示例——只允许 team=sensors 的身份向 sensors/ 子树发布:

http
POST /v1/namespaces/default/authorization/policies
Content-Type: application/json

{
  "name": "sensors-can-publish",
  "effect": "ALLOW",
  "actions": ["WRITE"],
  "resources": [
    { "type": "topic", "name": "sensors/#", "match": "filter" }
  ],
  "principals_all": false,
  "principal_attributes": { "team": ["sensors"] }
}

设置授权配置(deny_if_no_match 即上文“无匹配时拒绝”的开关):

http
PUT /v1/namespaces/default/authorization/config
Content-Type: application/json

{ "enabled": true, "deny_if_no_match": true }

策略变更动态生效,无需重启。

Dashboard 操作

在 Dashboard 的 Authorization 页面可以:

  • 为当前命名空间开启/关闭授权,并设置无匹配时的兜底决策(ALLOW / DENY
  • 创建、编辑、启用/停用和删除授权策略
  • 按身份、资源、动作组合定义允许或拒绝规则

授权配置与策略均按命名空间隔离,切换命名空间即查看与管理对应租户的规则。