[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