如何在多租户系统中的 RabbitMQ 中使队列私有/安全?
我已阅读 RabbitMQ 提供的 入门 指南,甚至还向 stormed-amqp,所以我对AMQP。
然而,该指南并不全面,并且避免了身份验证和授权等内容。
我们正在设计一个多租户系统,该系统将在 RPC 类型的情况下使用 RabbitMQ。这种 RPC 实现的不同之处可能在于远程过程实际上是系统上的其他租户程序。
基本上,我想隔离数据总线,其中包括以下断言:
- 我们的服务器不会将数据传递给错误的租户程序(这很容易处理并且相关但不会受到质疑)。
- 租户程序无法从不属于他们的队列中读取数据。
- 租户程序无法写入不属于他们的队列。
这个问题严格来说是关于 RabbitMQ 安全性的。我知道 RabbitMQ 支持 SSL,它提供端到端加密,并且我知道 RabbitMQ 支持用户名/密码身份验证。我不知道这些事情是否适用于私有化队列使用(又名 ACL),即连接可能被加密,并且用户可能被验证,但用户可以从所有队列读取/写入。
有人可以启发我这个更高级的主题吗?我相信 RabbitMQ 可以支持这种系统,但并不完全肯定。我知道 RabbitMQ 中有些东西我只是不知道,例如什么是虚拟主机,它们在这种情况下会有帮助吗?我只是在我目前的知识范围内没有看到解决方案仅限于路由键、队列名称和交换。
I have read the Get Started guide provided by RabbitMQ and have even contributed the sixth example to stormed-amqp, so I have an inkling of knowledge about AMQP.
However, the guide is not comprehensive and avoids things like authentication and authorization.
We're designing a multitenancy system that will use RabbitMQ in an RPC-type of situation. What is perhaps different about this implementation of RPC is that the remote procedures will actually be other tenant programs on the system.
Basically, I want to isolate the data buses, which includes the following assertions:
- Our server will not deliver data to the wrong tenant program (this is handled easily and is relevant but not questioned).
- Tenant programs are not be able to read data from queues that aren't theirs.
- Tenant programs are not be able to write to queues that aren't theirs.
This question is strictly about RabbitMQ security. I know that RabbitMQ supports SSL, which provides end-to-end encryption, and I know RabbitMQ supports username/password authentication. I don't know if these things apply to privatizing queue usage (aka ACL), i.e. the connection may be encrypted, and the user may be verified, but the user can read to / write from all the queues.
Can anybody enlighten me on this more advanced topic? I'm confident that RabbitMQ can support this sort of system but not exactly positive. I know there are things in RabbitMQ that I just don't know about, e.g. what are vhosts and will they help in this situation? I just don't see the solution in my current knowledge limited to routing keys, queue names and exchanges.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
TLDR:相关信息可以在这里找到:https://www.rabbitmq.com/access-control .html。然而,由于rabbitmq文档非常冗长,下面我将描述似乎是锁定资源访问的唯一解决方案。
摘要
虚拟主机
正如 Michael Dillon 提到的,您应该首先让一切发生在
vhosts
中 (虚拟主机)并完全阻止通用vhost
。通用虚拟主机简称为/
,默认情况下是启动rabbitmq 服务器时唯一的vhost
。给定资源(即队列或交换)必须仅存在于一个
vhost
和一个vhost
中。一个rabbitmq连接还必须专门连接到一个vhost
(这可以通过将vhost
名称附加到rabbitmq URL来指定,例如amqp://username:密码@myserver:5672/vhost
)。因此,rabbitmq 连接只能访问位于其所连接的虚拟主机中的队列和交换器。只需创建与应用程序中的逻辑分组一样多的
虚拟主机
即可。请记住,一个vhost
中的资源不知道并且无法与另一vhost
中的资源进行通信。通过以下操作创建vhost
:用户
下一步是创建用户并删除默认的
guest
用户。每个用户都应该有自己的用户名和密码,并且只能由他们使用。不用说,只有实际管理员才应该拥有管理员权限。这使他们能够管理其他用户、虚拟主机及其权限。通过执行以下操作创建用户:用户可以使用其凭据创建rabbitmq连接,从而连接到
vhost
。但是,只有当这是用户有权访问的虚拟主机
时,连接才会被批准。只有管理员可以授予和修改用户对虚拟主机
的访问权限。用户可以被授予对多个vhosts
的访问权限,并使用其凭据同时连接到多个vhosts
(但不能在同一连接中连接到不同的vhosts
) 。用户权限
但是,用户对
虚拟主机
的访问权限并不是简单的二进制。文档的链接部分中有一个很好的表格,它表示什么命令算作什么类型的操作,例如
queue.bind
是一个write
操作,而queue.bind 是一个
是一个write
操作。 getread
操作。然而复杂性并不止于此,实际上是根据自定义正则表达式(正则表达式)管理员选择的。例如,正则表达式
'.*' '.*' '.*'
允许用户分别在该vhost
中的任何资源上进行配置、写入和读取。这将被授予像这样:而正则表达式
'^$' '^(hello).*$' '^(hello|world).*$'
不会向用户授予任何配置权限,但允许他们写入名称以hello< 开头的任何资源/代码> 和从名称以
hello
或world
开头的任何资源中读取。要点
自由地使用
vhosts
将资源分组在一起,并对这些资源作为一个整体设置权限。资源命名非常重要,因为这是在给定
虚拟主机
内配置对该资源的访问的唯一方法。对于OP的问题,每个用户都应该被授予只能根据队列的唯一名称读取和写入自己的队列的权限。这不一定需要跨越多个虚拟主机,但如果有意义的话也可以。
TLDR: The relevant information can be found here: https://www.rabbitmq.com/access-control.html. However, since the rabbitmq documentation is very verbose, below I will describe what seems like the only solution to locking down access to resources.
Summary
Virtual hosts
As Michael Dillon mentions, you should start by making everything happen inside
vhosts
(virtual hosts) and block the genericvhost
entirely. The generic vhost is simply called/
and is by default the onlyvhost
when you start a rabbitmq server.A given resource (i.e. queue or exchange) must live in one
vhost
and onevhost
only. A rabbitmq connection must also specifically connect to a singlevhost
(this can just be specified by appending thevhost
name to the rabbitmq URL e.g.amqp://username:password@myserver:5672/vhost
). Therefore a rabbitmq connection can only access queues and exchanges that live in thevhost
it has connected to.Simply create as many
vhosts
as there are logical groupings in your application. Remember that resources in onevhost
are not aware of and cannot communicate with resources in anothervhost
. Create avhost
by doing:Users
The next step is to create users and remove the default
guest
user. Each user should have their own username and password which should be used only by them. Needless to say, only the actual administrator should have administrator privileges. This allows them to manage other users,vhosts
and their permissions. Create a user by doing:Users can use their credentials to create a rabbitmq connection and thereby connect to a
vhost
. However, the connection is only approved if this is avhost
the user has access to. Only an adminstrator can grant and modify a user's access permissions to avhost
. A user can be granted access to multiplevhosts
and use their credentials to connect to multiplevhosts
simultaneously (but not differentvhosts
within the same connection).User permissions
However, a user's access to a
vhost
is not simply binary.There is a nice table in the linked section of the docs which denotes what command counts as what kind of operation e.g.
queue.bind
is awrite
operation whereasqueue.get
is aread
operation. However the complexity doesn't end there, permissions are actually granted to each operation type based on a custom regular expression (regex) of the administrator's choosing.For instance the regex
'.*' '.*' '.*'
allows the user to configure, write and read respectively on any resource in thatvhost
. This would be granted like so:Whereas the regex
'^$' '^(hello).*$' '^(hello|world).*$'
would not give the user any configuration permissions but would allow them to write to any resource whose name began withhello
and read from any resource whose name began with eitherhello
orworld
.Takeaways
Use
vhosts
liberally to group resources together and set permissions on these resources as a whole.Naming of resources is very important as this is the only way to configure access to that resource within a given
vhost
.In the case of the OP's question, each user should be permissioned to only read and write to their own queue based on the queue's unique name. This does not necessarily need to be across multiple
vhosts
but can be if it makes sense for it to be.在多租户系统中,您可以通过定义用户拥有的权限来确保队列的安全。请在此处阅读 RabbitMQ 管理指南的访问控制部分 http://www.rabbitmq.com/admin-guide.html
首先让所有事情发生在虚拟主机内并完全阻止通用虚拟主机,即不要让任何人在虚拟主机“/”上声明队列和交换。
In a multitenancy system you would make queues secure by defining the permissions that users have. Read the access control section of the RabbitMQ admin guide here http://www.rabbitmq.com/admin-guide.html
Start by making everything happen inside vhosts and block the generic vhost entirely, i.e. don't let anyone declare queues and exchanges on vhost "/".
我相信本教程演示了您正在尝试做的事情。
事实上,回调队列是独占的、自动删除的,并且其名称是自动生成的,这应该提供足够的安全性。
I believe this tutorial demonstrates what you are trying to do.
The fact that the callback queue is exclusive, auto-deletes, and has its name auto-generated should provide enough security.
为了 Rabbitmq 服务器的安全性,RabbitMQ 中有一些安全机制:
For security in Rabbitmq server, there are some security mechanism in RabbitMQ: