在多租户系统中如何使RabbitMQ中的队列变得私有/安全?

43

我已阅读RabbitMQ提供的入门指南,甚至为stormed-amqp贡献了第六个示例,因此对AMQP有一点了解。

然而,该指南不够全面,并避免像身份验证和授权等事项。

我们正在设计一个多租户系统,将在其中使用RabbitMQ进行RPC类型的情况。这种RPC实现的不同之处在于远程过程实际上是系统上的其他租户程序。

基本上,我想要隔离数据总线,其中包括以下声明:

  1. 我们的服务器 不会 将数据传递给错误的租户程序(这很容易处理,相关但不受质疑)。
  2. 租户程序无法读取不属于他们的队列中的数据。
  3. 租户程序无法写入不属于他们的队列。

这个问题严格涉及RabbitMQ安全性。我知道RabbitMQ支持SSL,提供端到端加密,也知道RabbitMQ支持用户名/密码身份验证。我不知道这些东西是否适用于私有化队列使用(也就是ACL),即连接可以加密,用户可以验证,但用户可以读取/写入所有队列。

有没有人能为我解释这个更高级的话题?我相信RabbitMQ可以支持这种系统,但不确定。我知道RabbitMQ中有些东西我不知道,例如vhost是什么,它们是否有助于这种情况?在我的当前知识受限于路由键、队列名称和交换机时,我看不到解决方案。

4个回答

19
TLDR: 相关信息可以在这里找到:https://www.rabbitmq.com/access-control.html。然而,由于rabbitmq文档非常冗长,下面我将描述似乎是锁定资源访问的唯一解决方案。
总结
虚拟主机
正如Michael Dillon所提到的,您应该从内部使所有事情发生在vhosts(virtual hosts)中,并完全阻止通用vhost。通用vhost简单地称为“/”,并且在启动rabbitmq服务器时默认是唯一的vhost。
给定的资源(即队列或交换机)必须存在于一个vhost中,且仅存在于一个vhost中。rabbitmq连接还必须明确连接到单个vhost(可以通过将vhost名称附加到rabbitmq URL后来指定)。因此,rabbitmq连接只能访问存在于其连接到的vhost中的队列和交换机。
只需创建与应用程序中逻辑分组数量相同的vhost即可。请记住,一个vhost中的资源不知道并且不能与另一个vhost中的资源通信。通过执行以下操作来创建vhost:
rabbitmqctl add_vhost vhost-name

用户

下一步是创建用户并删除默认的guest用户。每个用户都应该有自己的用户名和密码,只能由他们自己使用。不用说,只有实际的管理员才应该拥有管理员权限。这使他们能够管理其他用户、vhosts和他们的权限。通过执行以下操作来创建用户:

rabbitmqctl add_user "username"

用户可以使用其凭据创建一个RabbitMQ连接,从而连接到vhost。但是,只有当这是用户有权限访问的vhost时,才会批准连接。只有管理员才能授予和修改用户对vhost的访问权限。用户可以被授予对多个vhost的访问权限,并使用他们的凭据同时连接到多个vhost(但不能在同一连接中连接到不同的vhost)。

用户权限

然而,用户对vhost的访问并不仅仅是二进制的。

RabbitMQ区分对资源的配置写入读取操作。 配置操作创建或销毁资源,或更改它们的行为。 写入操作将消息注入资源中。 而读取操作从资源中检索消息。

文档中链接部分有一个漂亮的表格,指示哪些命令属于哪种操作类型,例如queue.bind是一个write操作,而queue.get是一个read操作。 但是,复杂性并不止于此,权限实际上是基于管理员选择的自定义正则表达式(regex)授予每种操作类型的。

例如,正则表达式'.*' '.*' '.*'允许用户在该vhost中对任何资源进行配置、写入和读取。这将被授予如下所示

rabbitmqctl set_permissions -p "vhost-name" "username" ".*" ".*" ".*"

正则表达式'^$' '^(hello).*$' '^(hello|world).*$'不会给用户任何配置权限,但允许他们写入以hello开头的任何资源并从以helloworld开头的任何资源读取。

要点

大量使用vhosts将资源分组,并整体设置这些资源的权限。

资源的命名非常重要,因为这是在给定vhost中配置对该资源访问的唯一方式。

在OP的问题中,每个用户都应该被授权仅基于队列的唯一名称读取和写入其自己的队列。这不一定需要跨多个vhosts,但如果有意义,也可以这样做。


9
在多租户系统中,您需要通过定义用户的权限来保护队列的安全性。请在RabbitMQ管理指南的访问控制部分阅读。首先,确保所有操作都在虚拟主机内进行,并完全禁止通用虚拟主机,即不允许在“/”虚拟主机上声明队列和交换机。

2

我相信这个教程演示了您所尝试做的事情。
回调队列是独占的、自动删除的,并且具有自动生成的名称,这足以提供足够的安全性。


我实际上是在上面链接的 stormed-amqp 库中编写了该示例的实现。我不确定 exclusive 指令是否足够安全,但我会进行实验以查看它是否足够安全。谢谢。 - Brian

0

为了保证Rabbitmq服务器的安全性,RabbitMQ采用了一些安全机制:

  1. 访问控制
  2. SASL身份验证
  3. SSL支持

访问控制和SASL身份验证是相同的吗? - FunctorPrototype

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接