RabbitMQ 鉴权、授权、权限访问
鉴权、授权、访问控制
概览
这部分描述了 RabbitMQ 中的鉴权和授权特性。以及操作着对系统的访问控制。不同的用户可以被授予特定的 vitual host 访问。在每个虚拟主机的具体许可也可以限制。
RabbitMQ 支持两种主要的鉴权机制以及几个认证和授权后端。
基于密码的鉴权有配套的指南。 关于支持 TLS 的内容也包含在专门的指南里。
指南中讨论的其他话题包括:
- 默认虚拟主机和用户
- 对默认用户的连接限制
- 鉴权和授权失败的故障排除
相关术语和定义
鉴权和授权经常被混淆或者互换使用。在 RabbitMQ 中这两个是分开的,互换使用是错误的。简单来说,鉴权是验证用户是谁,而授权是决定用户允许和不被允许做的。
默认虚拟主机和用户
当服务器第一次启动,检测到数据库没有初始化或者被删掉了,它将会使用以下资源初始化一个新的数据库:
- 一个虚拟主机,名字为
/
; - 名为
guest
,默认密码为guest
的用户,并赋予/
虚拟主机的全部权限
这里建议删除 guest
用户或者至少改变其密码为一个合理安全生成的不为大众知道的值。
鉴权:你说你是谁?
在一个应用连接上 RabbitMQ 后,有任何操作之前,必须要经过鉴权,也就是提供并证明它的身份。有了证明的身份,RabbitMQ 节点会查看它的权限并授权访问相应的资源,如虚拟主机,队列,交换机等等。
两个基本的鉴权客户端方式是使用用户密码和 X.509 证书。用户密码方式可以使用多种鉴权后台来验证凭证。
鉴权失败的连接会被关闭,并在服务器日志中记录错误消息。
使用 X.509 证书方式的连接鉴权需要使用内置的插件,rabbitmq-auth-mechanism-ssl
,所有必须启用该插件,客户端也必须配置为使用外部机制
。在该机制下,任何提供密码的的客户端将被忽略。
“guest” 用户只能本地访问
默认情况下,guest
用户禁止同步远程主机连接;它仅可以通过环回接口(如:localhost
)连接。这适用于任何协议的连接。任何其他用户不会有这样的限制(默认)。
在生产系统中,建议通过创建新用户,或者一系列只有访问相应虚拟主机权限的用户。可以通过 CLI tools
,HTTP API 或者 definitions import
。
这是通过配置文件中的 loopback_users
项配置的。
通过设置 loopback_users
为 none
可以使 guest
用户进行远程连接。
一个允许 guest
用户远程连接的最简化RabitMQ config file看起来是这样的:
# DANGER ZONE!
#
# allowing remote connections for default user is highly discouraged
# as it dramatically decreases the security of the system. Delete the user
# instead and create a new one with generated secure credentials.
loopback_users = none
或者经典的配置文件格式(rabbitmq.config):
%% DANGER ZONE!
%%
%% Allowing remote connections for default user is highly discouraged
%% as it dramatically decreases the security of the system. Delete the user
%% instead and create a new one with generated secure credentials.
[{rabbit, [{loopback_users, []}]}].
授权:权限如何工作
当一个 RabbitMQ 客户端建立连接到服务端,然后鉴权,它指定了准备操作的虚拟主机。此时执行第一级访问控制,服务器检查用户是否有访问虚拟主机的权限,否则拒绝连接尝试。
资源,如:交换机和队列,是特定虚拟主机中的命名实体;每个虚拟主机下,即使名字相同也是不同的资源。当在资源上执行某些操作时,执行第二级访问控制。
RabbitMQ 在资源操作上区分配置,写,读。配置操作可以创建或者销毁资源或者改变它们的行为。写操作将消息注入资源中。读操作从资源中获取消息。
用户想在在资源上执行操作就必须被赋予恰当的权限。以下的表格显示了执行权限检查的所有 AMQP 命令在不同资源的类型时需要权限。
AMQP 0-9-1 Operation | configure | write | read | |
---|---|---|---|---|
exchange.declare | (passive=false) | exchange | ||
exchange.declare | (passive=true) | |||
exchange.declare | (with [AE](ae.html)) | exchange | exchange (AE) | exchange |
exchange.delete | exchange | |||
queue.declare | (passive=false) | queue | ||
queue.declare | (passive=true) | |||
queue.declare | (with [DLX](dlx.html)) | queue | exchange (DLX) | queue |
queue.delete | queue | |||
exchange.bind | exchange (destination) | exchange (source) | ||
exchange.unbind | exchange (destination) | exchange (source) | ||
queue.bind | queue | exchange | ||
queue.unbind | queue | exchange | ||
basic.publish | exchange | |||
basic.get | queue | |||
basic.consume | queue | |||
queue.purge | queue |
权限在每个虚拟主机的基础下,由三个正则表达式表示 ---- 依次代表配置,写和读。用户被授予对名称与正则表达式匹配的所有资源进行操作的相应权限。(注:为方便起见,RabbitMQ 在执行权限检查时将默认交换机的空名称映射为 amq.default
。)
正则表达式 ^$
只匹配空字符串,实际上禁止用户对任何资源执行操作。标准的 AMQP 资源名称以 amp
为前缀,服务器生成的名字以 amp.gen
为前缀。举例来说,'^(amq.gen.*|amq.default)$'
表示用户拥有服务器自动生成的名字,以及默认交换机的权限。空字符串 ''
是 '^$'
的同义词,在权限限制上效果是一样的。
RabbitMQ 在每个连接和每个 channel
的基础上缓存访问控制的检查。因此改变用户的权限会在用户重新连接后才能生效。
关于设置访问控制的详细信息,请查阅 rabbitmqctl 手册 的 访问控制部分 部分。
用户标签和管理界面访问
除了上面提到的权限,用户可以有与之相关联的标签。目前只有管理界面的访问由用户标签控制。
便签通过 rabbitmqctl
管理。新创建的用户默认没有任何标签。
请参考管理插件指南来学习更多关于标签的情况,如具体支持的标签内容,以及它们如何限制管理界面的访问。
Topic 授权(Topic Authorisation)
在 3.7.0 的版本,RabbitMQ 支持了为 topic 交换机准备的 topic 授权。发布授权实施时,主题交换机的消息所带的路由键也会进行匹配(如:在 RabbitMQ 默认的后台授权中,路由键与正则表达式比对来决定消息是否可以向下路由。主题授权以 STOMP 和 MQTT 协议为目标,这些协议围绕主题构建,并在幕后使用了主题交换机。
主题授权是对发布者现有检查之外的一层。发布一个消息到主题类型的交换机将会通过 basic.publish
和 路由键两层检查。在前面一层拒绝访问时后面这一层就不会用到了。
主题授权也可以对主题消费者强制执行。请注意,对于不同的协议,它的工作方式也不同。主题授权的概念仅仅会在主题导向的协议,如 MQTT 和 STOMP 下才会有意义。 举例来说,在 AMQP 0-9-1 下,消费者从队列中消费,因此标准资源权限适用。额外的,如果配置了任何主题权限,在 AMQP 0-9-1 协议下的主题交换机和队列/交换机之间绑定路由键也会检查。关于 RabbitMQ 如何处理主题相关授权的更多信息,请查阅 STOMP
和 MQTT
指导文档。
如果没有定义主题权限,在使用默认的授权后端时,发布消息到主题交换机或者从一个主题下消费是不要授权的(在新安装的 RabbitMQ 服务就会出现这样的情况)。此时,主题授权是可选的:你不需要把任何交换机列入白名单。如果要使用主题授权,你需要为一个或多个交换机选择并定义主题权限。详情见 rabbitmqctl 手册。