[rabbitmq-discuss] Advanced per-user authorization
Matthias Radestock
matthias at rabbitmq.com
Wed Nov 21 17:31:11 GMT 2012
Jonas,
On 21/11/12 16:49, Jonas Schwertfeger wrote:
> On Wed, Nov 21, 2012 at 5:43 PM, Matthias Radestock
> <matthias at rabbitmq.com> wrote:
>> For AMQP, the combination of internal exchanges, exchange-to-exchange
>> bindings, and RabbitMQ's existing permission system provide enough
>> functionality to emulate per-routing-key-pattern access control.
>
> I'm curious, can you give an example of a setup that would allow the following:
>
> User A publishing a message M that only subscribing user B can consume.
>
> What exchanges, queues, bindings and ACLs would you set up?
The general approach is as follows:
1) restricting what messages users can publish
Say that users A and B publish messages to exchange X. Now you want to
restrict them to only publish messages with routing keys matching
'<username>.*'. To do this, you, as a server administrator...
a) create X as an internal exchange, which means that nobody can publish
to it directly, and set permissions s.t. nobody except the administrator
can bind X, i.e. set appropriate 'write' permissions.
b) create an additional exchange per user, say "X.<username>", of the
same type as X
c) set up the permissions s.t. A/B can publish to their own exchange
only, i.e. give each user 'write' permissions to their exchange (only)
d) set up exchange-to-exchange bindings between X and X.A/X.B,
reflecting the publish restriction, i.e., in this case, bind X to X.A
with a binding key of "A.*", and to X.B with a binding of "B.*"
e) get clients to publish to "their" X.<username> exchange instead of X
(the latter is now prohibited by the permissions)
2) restricting what messages users can receive
Say that users A and B bind queues to exchange Y and consume from these
queues. Now you want to restrict them to only be able to receive
messages with routing keys matching '<username>.*'. To do this, you, as
a server administrator...
a) set permissions on Y s.t. nobody except the administrator can bind to
Y, i.e. set appropriate 'read' permissions.
b) create an additional exchange per user, say "Y.<username>", of the
same type as Y
c) set up permissions s.t. A/B can bind to their own exchange only, i.e.
give each user 'read' permissions to their exchange (only)
d) set up exchange-to-exchange bindings between Y.A/Y.B and Y,
reflecting the receive restriction, i.e., in this case, bind Y.A to Y
with a binding key of "A.*", and bind Y.B to Y with with a binding key
of "B.*"
e) get clients to bind their queues to "their" Y.<username> exchange
instead of Y (the latter is now prohibited by permissions)
You'd probably also want to put in place permissions that prevent users
from consuming from each others queues, which is easily done with an
appropriate queue naming convention and read permissions.
Note that the above works for all exchange types, even the exotic ones
like header exchanges that match on message headers rather than routing
keys.
Your example - "User A publishing a message M that only subscribing user
B can consume" - maps straightforwardly onto (2).
An alternative that works in some cases is to rely on the built-in
restrictions for the default exchange, namely that it contains bindings
for all queues, and that clients are not allowed to create bindings to
it directly. So, in your example, if each user has a queue named after
them, and the permission are set up s.t. only the correct user can
create/delete/bind/consume-from their queues, then publishing a message
to the default exchange with the routing key set to the user's queue
guarantees that only the intended user can receive the message.
Regards,
Matthias.
More information about the rabbitmq-discuss
mailing list