After a client is successfully authenticated by the message broker, it needs to perform some activities in some virtual hosts. In the earlier chapters, we saw that permissions are defined per vhost and live either internally in the message broker or externally. The RabbitMQ LDAP backend plugin that we saw earlier provides you with an ability to store permissions in an LDAP server. The following types of permissions are configured in the message broker:
We already discussed how to manage permissions using the rabbitmqctl
utility and the HTTP API. The following commands can be used from the utility to manage permissions:
set_permissions
: This sets permissions per user per vhostclear_permissions
: This clears permissions per user per vhostlist_permissions
: This lists the users that are granted access to a particular vhost along with their permissionslist_user_permissions
: This lists the permissions of a particular userThe LDAP user that we created earlier by default has all the permissions to the broker (except for being an administrator). Let's suppose that we want to disable the configure
permissions, allow more fine-grained write
permissions only to certain queues (in certain vhosts), or make it an administrator. The RabbitMQ LDAP provides a query mechanism to check permissions as configured in the LDAP server. There are three types of queries that can be specified in the RabbitMQ configuration and further contain different types of subqueries that are executed against the LDAP server:
vhost_access_query
: As users and permissions must be checked against vhosts that must be created in RabbitMQ, we can define vhost entries in the LDAP server against which to check for available permissions and tags. In fact, these entries represent a subset of the existing vhosts in the RabbitMQ server against which we check whether users have further access permissions or not. The default query is {constant, true}
, which specifies that access to all vhosts is given to all the users (the constant
queries are aliases for all, which return true or false for any value checked by vhost_access_query
).resource_access_query
: These are the types of queries that allow you to check whether a user has specific permissions (read, write, or configure) for a particular vhost to which the user has access (as checked by vhost_access_query
). The default is {constant, true}
.tag_queries
: These are the types of queries that allow you to specify the tags that are given to particular users (such as management or administrator). The default is {administrator, {constant, false}}
.The types of subqueries that can be specified for each type of these queries use a simple DSL; you can review the LDAP RabbitMQ plugin documentation for an extensive list of all types of subqueries. We will specify the following access domains for our message broker:
test
user is the vhostguest
user is an administrator and has access to the management consoleMartin
user has access only to the test
vhost and can publish to exchanges starting with the test_
prefixSubscriber
user has access to the test
vhost only and can read messages from queues starting with the test_
prefixThe following diagram specifies the LDAP structure of the organization:
Before we can implement this setup, we need to create the test vhost in RabbitMQ. The following example creates the test vhost using the rabbitmqctl
utility:
rabbitmqctl add_vhost test
You also need to create LDAP entries for the guest
and Subsciber
users in the same manner that we created the entry for the user with the name Martin earlier. Here is a sample ldiff
file (users.ldiff
) for the two users:
## guest user dn: cn=guest,ou=users,dc=example,dc=com objectclass: inetOrgPerson cn: guest sn: guest uid: guest mail: [email protected] ## Subscriber user dn: cn=Subscriber,ou=users,dc=example,dc=com objectclass: inetOrgPerson cn: Subscriber sn: Subscriber uid: Subscriber mail: [email protected]
To import the preceding ldiff file and set a password for the users, you can execute the following set of commands:
ldapadd -x -D "cn=organization,dc=example,dc=com" -W –f users.ldiff ldappasswd -D "cn=organization,dc=example,dc=com" "cn=guest,ou=users,dc=example,dc=com" –W –S ldappasswd -D "cn=organization,dc=example,dc=com" "cn=Subscriber,ou=users,dc=example,dc=com" –W –S
Finally, we need to create the vhosts
group along with an entry for the test
vhost (vhosts.ldiff
):
## Example.com vhosts dn: ou=vhosts,dc=example,dc=com ou: vhosts description: Vhosts in the organization objectClass: organizationalUnit ## test vhost dn: cn=test,ou=vhosts,dc=example,dc=com objectclass: organizationalRole description: test vhost
Execute the following in order to import the preceding entries:
ldapadd -x -D "cn=organization,dc=example,dc=com" -W –f vhosts.ldiff
Note that we are using a predefined object class (organizationalRole
) for the vhost entry in LDAP. You can prefer to create your own object class for the purpose of describing a vhost along with its attributes in your organization. Finally, we need to specify the proper queries for permission checking in the LDAP configuration (as part of the rabbitmq_auth_backend_ldap
section in your RabbitMQ configuration file):
{vhost_access_query, {exists, "cn=${vhost},ou=vhosts,dc=example,dc=com"}}, {resource_access_query, {for, [ {permission, configure, {match, {string, "${username}"},{string, "guest"}}}, {permission, write, {'and', [ {match, {string, "${username}"},{string, "(Martin|guest"}}, {match, {string, "${name}"},{string, "test_*"}}]} }, {permission, read, {'and', [ {match, {string, "${username}"},{string, "(Subscriber|guest)"}}, {match, {string, "${name}"},{string, "test_*"}}]} } ] }}, {tag_queries, [{administrator, {match, {string, "${username}"},{string, "guest"}}}, {management, {constant, true}}]}
The preceding configuration is easy to understand, but it might turn out to be clumsy to write and test. After it is added to the configuration file, you can try to log in with the guest/guest user and check whether it has administrative access. You can try to create an object using the Subscriber
user or send/receive messages using the Martin
/Subscriber
user. In practice, the preceding configuration should be designed carefully based on the organizational LDAP schema in order to prevent security holes.
18.227.10.45