Overview
========

Authorisation is effected by three configuration options:

* vhost_access_query
* resource_access_query
* tag_queries

Each defines a query that will determine whether a user has access to
a vhost, a resource (e.g. exchange, queue, binding) or is considered
an administrator.

The default values are {constant, true}, {constant, true} and
[{administrator, {constant, false}}] respectively, granting all users
access to all objects in all vhosts, but not making them
administrators.

A query can be of one of several types:

Constant Query
--------------

{constant, Bool}

This will always return either true or false, unconditionally granting
or denying access.

Exists Query
------------

{exists, Pattern}

This will substitute variables into the pattern, and return true if
there exists an object with the resulting DN. Substitution occurs with
${} syntax. The vhost_access_query in the example configuration below
therefore allows you to control access to vhosts by controlling the
existence of OUs in a vhosts OU.

Each of the three queries allow different substitutions:

vhost_access_query:
  ${username}
  ${user_dn}
  ${vhost}

resource_access_query:
  ${username}
  ${user_dn}
  ${vhost}
  ${resource} (one of exchange or queue)
  ${name}
  ${permission} (one of configure, write or read)

The terms configure, write and read for resource access have the same
meanings that they do for the built-in RabbitMQ permissions system,
see http://www.rabbitmq.com/access-control.html

tag_queries:
  ${username}
  ${user_dn}

Note that tag_queries consists of a proplist, mapping the name of a
tag to a query to perform to determine whether or not the user has
that tag. You must list queries for all tags that you want your users
to have.

In Group Query
--------------

{in_group, Pattern}
{in_group, Pattern, AttributeName}

Like the Exists Query, substitutes arguments into a pattern to look
for an object. However, this query returns true if the logged in user
is a member; checking either against the "member" attribute, or any
named attribute.

Match Query
-----------

{match, StringSubQuery, RESubQuery}

Takes a string and a regular expression, and checks that the one
matches the other. Note that the string and the regular expression are
both queries in turn.

String Query
------------

{string, Pattern}

Just substitutes arguments into a string. As this returns a string
rather than a boolean it should be used within a match query.

Attribute Query
---------------

{attribute, DNPattern, AttributeName}

Returns the value of an attribute of an object retrieved from LDAP. As
this returns a string rather than a boolean it should be used within a
match query.

For Query
---------

{for, [{Name, Value, SubQuery}, ...]}

This allows you to split up a query and handle different cases with
different subqueries.

Options should be a list of three-tuples, with each tuple containing a
name, value and subquery. The name is the name of a variable
(i.e. something that would go into a ${} substitution). The value is a
possible value for that variable.

So the example:

     {resource_access_query,
      {for, [{resource, exchange,
              {for, [{permission, configure,
                      { in_group, "cn=wheel,ou=groups,dc=example,dc=com" }
                     },
                     {permission, write, {constant, true}},
                     {permission, read,  {constant, true}}
                    ]}},
             {resource, queue, {constant, true}} ]}}

would allow members of the "wheel" group to declare and delete
exchanges, and allow all users to do everything else.

Example Configuration
=====================

TODO improve and explain this

[
  {rabbit, [{auth_backends, [rabbit_auth_backend_ldap]}]},
  {rabbitmq_auth_backend_ldap,
   [ {servers,               ["my-ldap-server"]},
     {user_dn_pattern,       "cn=${username},ou=People,dc=example,dc=com"},
     {vhost_access_query,    {exists,
                              "ou=${vhost},ou=vhosts,dc=example,dc=com"}},
     {resource_access_query,
      {for, [{resource, exchange,
              {for, [
                     %% Only allow "wheel" group to create exchanges
                     {permission, configure,
                      {in_group, "cn=wheel,ou=groups,dc=example,dc=com"}
                     },

                     %% Only allow publishing for people with surnames beginning
                     %% with "Mac"
                     {permission, write,
                      {match, {attribute, "${user_dn}", "sn"}, {string, "^Mac.*"}}
                     },

                     %% Anyone can bind to exchanges
                     {permission, read,  {constant, true}}
                    ]}},
             %% Anyone can do anything with queues
             {resource, queue, {constant, true}} ]}},
     {tag_queries,           [{administrator, {constant, false}}]},
     {use_ssl,               false},
     {port,                  389},
     {log,                   false} ] }
].
