Configure RabbitMQ with LDAP

Integrating LDAP Authentication with RabbitMQ

Posted by Alfus Jaganathan on Thursday, March 28, 2024

Background

If you’re planning to integrate LDAP authentication and authorization with your RabbitMQ server or cluster, this article serves as an excellent source of required basic configurations.

The widespread adoption of Windows Active Directory for authentication and authorization in numerous organizations makes it a favorable choice for RabbitMQ authentication and authorization as well. By utilizing the LDAP protocol, you benefit from a streamlined approach to authentication, leveraging the existing infrastructure and simplifying user management.

Understanding LDAP and Active Directory

Before diving deeper into the configuration process, it’s better to have a quick look at Lightweight Directory Access Protocol(LDAP) and how it works.

LDAP is a protocol used to access and manage directory information over a network. It plays a crucial role in organizing an organization’s various types of information in a centralized, hierarchical directory structure, making it easier to find and manage data across the network.

LDAP in RabbitMQ Authentication and Authorization

Integrating RabbitMQ with LDAP, especially within an Active Directory environment, allows RabbitMQ to utilize this centralized “guest list” for both authenticating users and determining their permissions. When a user attempts to connect to RabbitMQ, the service queries LDAP: Authentication: Is this person on the list? Authorization: What can they do here?" Based on the response—like finding a name and access level in a well-organized directory—RabbitMQ grants the appropriate level of access. This integration streamlines security and user management, leveraging existing infrastructure for efficient and consistent access control across your IT ecosystem.

Integrating LDAP with RabbitMQ

To integrate LDAP authentication and authorization with RabbitMQ, you will need to:

  1. Configure RabbitMQ to Use LDAP: Adjust RabbitMQ’s configuration to accept LDAP as one of the auth backends. This typically involves installing and configuring a plugin with required configuration for authentication and authorization.

  2. Connect to RabbitMQ with windows credentials: Instead of using basic credentials, clients authenticate to RabbitMQ using the windows domain credentials. RabbitMQ validates these against the LDAP server to ensure they are valid and checks the associated Active Directory groups to determine what actions the client is authorized to perform.

Getting Started

Prerequisites

Note: RabbitMQ can be installed through various methods. The configurations should be applicable without issues, provided they are correctly implemented in the rabbitmq.conf file or specified as environment variables.

Configure RabbitMQ to Use LDAP

To configure LDAP, I diligently followed the instructions outlined in the LDAP Support section of RabbitMQ’s official documentation. For comprehensive details and further guidance, I recommend referring directly to the official documentation.

RabbitMQ’s configuration must be updated via the cluster operator as below. Update the existing cluster configuration to include:

Plugin: Add rabbitmq_auth_backend_ldap to the additionalPlugins list.

Auth Backends: Add rabbit_auth_backend_ldap as an auth_backend into additionalConfig. This configuration specifies LDAP as authentication option.

Backend Configuration: Include auth_ldap.servers, auth_ldap.idle_timeout, auth_ldap.use_ssl, auth_ldap.use_starttls, auth_ldap.dn_lookup_bind.user_dn, auth_ldap.dn_lookup_bind.password, auth_ldap.dn_lookup_attribute, auth_ldap.dn_lookup_base and auth_ldap.connection_pool_size in additionalConfig. Other configurations like group_lookup_base, vhost_access_query, resource_access_query, tag_queries, etc. can be added to the advancedConfig section.

Combining all these, the configuration YAML must be updated as shown below. Replace each of the placeholders [place-holder] with the correct values carefully.

Note: I am omitting the existing configuration items for better clarity of changes specific to LDAP configuration.

apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
  name: rabbitmq
  namespace: rabbitmq-clusters
spec:
  rabbitmq:
    additionalPlugins:
      - rabbitmq_auth_backend_ldap
    additionalConfig: |
      auth_backends.1 = rabbit_auth_backend_ldap
      auth_backends.2 = internal
      auth_ldap.servers.1 = [ldap-server-ip-or-fully-qualified-name]
      auth_ldap.connection_pool_size = 256
      auth_ldap.idle_timeout = 30000
      auth_ldap.use_ssl = false
      auth_ldap.use_starttls = false
      auth_ldap.dn_lookup_bind.user_dn = "[ldap-server-user-dn, e.g. CN=ldapreader,OU=ServiceAccounts,DC=gopivotal,DC=com]"
      auth_ldap.dn_lookup_bind.password = [ldap-server-password]
      auth_ldap.dn_lookup_attribute = [ldap-lookup-attribute-for-username, e.g. userPrincipalName]
      auth_ldap.dn_lookup_base = "[dn-base, e.g. OU=UserAccounts,DC=gopivotal,DC=com]"
      auth_ldap.log = false      
    advancedConfig: |
      [
        {rabbitmq_auth_backend_ldap, [
          {group_lookup_base, "[group-dn, e.g. OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com]"},
          {vhost_access_query, 
            { in_group, "[admin-group-dn, e.g. CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com]" }
          },
          {vhost_access_query, 
            { in_group, "[user-group-dn, e.g. CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com]" }
          },
          {resource_access_query,
            { for, [
              {permission, configure, 
                  {in_group, "[admin-group-dn, e.g. CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com]"}},
              {permission, write, 
                  {in_group, "[admin-group-dn, e.g. CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com]"}},
              {permission, read, 
                  {in_group, "[user-group-dn, e.g. CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com]"}}
            ]}
          },
          {tag_queries, [
            {administrator, { in_group, "[admin-group-dn, e.g. CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com]" }},
            {monitoring,    { in_group, "[user-group-dn, e.g. CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com]", "uniqueMember" }},
            {management,    { constant, true }}
          ]}
        ]}
      ].      

To enhance clarity, provided below is a sample YAML configuration featuring dummy values instead of placeholders. Following this, I will delve into a detailed explanation of each configuration entry, outlining its purpose to ensure a comprehensive understanding of the setup involved.

apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
  name: rabbitmq
  namespace: rabbitmq-clusters
spec:
  rabbitmq:
    additionalPlugins:
      - rabbitmq_auth_backend_ldap
    additionalConfig: |
      auth_backends.1 = rabbit_auth_backend_ldap
      auth_backends.2 = internal
      auth_ldap.servers.1 = 10.10.10.1
      auth_ldap.connection_pool_size = 256
      auth_ldap.idle_timeout = 30000
      auth_ldap.use_ssl = false
      auth_ldap.use_starttls = true
      auth_ldap.dn_lookup_bind.user_dn = "CN=ldapreader,OU=ServiceAccounts,DC=gopivotal,DC=com"
      auth_ldap.dn_lookup_bind.password = ldapPassword
      auth_ldap.dn_lookup_attribute = userPrincipalName
      auth_ldap.dn_lookup_base = "OU=UserAccounts,DC=gopivotal,DC=com"
      auth_ldap.log = false      
    advancedConfig: |
      [
        {rabbitmq_auth_backend_ldap, [
          {group_lookup_base, "OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com"},
          {vhost_access_query, 
            { in_group, "CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com" }
          },
          {vhost_access_query, 
            { in_group, "CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com" }
          },
          {resource_access_query,
            { for, [
              {permission, configure, 
                  {in_group, "CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com"}},
              {permission, write, 
                  {in_group, "CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com"}},
              {permission, read, 
                  {in_group, "CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com"}}
            ]}
          },
          {tag_queries, [
            {administrator, { in_group, "CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com" }},
            {monitoring,    { in_group, "CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com", "uniqueMember" }},
            {management,    { constant, true }}
          ]}
        ]}
      ].      

Auth Backends: This configuration enables RabbitMQ to use two authentication options. The first option authenticates users through LDAP, utilizing an external directory service. The second option uses RabbitMQ’s own internal database for authentication, allowing for straightforward user management directly within RabbitMQ.

auth_backends.1 = rabbit_auth_backend_ldap
auth_backends.2 = internal

LDAP Connection: This configuration provides RabbitMQ with necessary details to connect and communicate with LDAP server.

auth_ldap.servers.1 = 10.10.10.1
auth_ldap.connection_pool_size = 256
auth_ldap.idle_timeout = 30000
auth_ldap.use_ssl = false
auth_ldap.use_starttls = true
auth_ldap.dn_lookup_bind.user_dn = "CN=ldapreader,OU=ServiceAccounts,DC=gopivotal,DC=com"
auth_ldap.dn_lookup_bind.password = ldapPassword
auth_ldap.dn_lookup_attribute = userPrincipalName
auth_ldap.dn_lookup_base = "OU=UserAccounts,DC=gopivotal,DC=com"
auth_ldap.log = false

auth_ldap.servers.1 = 10.10.10.1 sets the IP address of the LDAP server. You can also add additional LDAP servers, if you have one, by adding auth_ldap.servers.2 and so on.

auth_ldap.connection_pool_size and auth_ldap.idle_timeout is set with some defaults, but you can adjust based on your environment’s needs.

auth_ldap.use_ssl, if TLS is enabled on the LDAP server, set to true, else false.

auth_ldap.use_starttls if LDAP server is configured with StartTLS, set to true, else false.

auth_ldap.dn_lookup_bind.user_dn = "CN=ldapreader,OU=ServiceAccounts,DC=gopivotal,DC=com", user ldapreader’s DN (Distinguished Name) with correct DC (Domain Component), OU (Organizational Unit) and CN (Common Name).

auth_ldap.dn_lookup_bind.password = ldapPassword, password for the user ldapreader

auth_ldap.dn_lookup_attribute = userPrincipalName specifies the LDAP attribute to use when searching for users. userPrincipalName is often an email-like identifier for users in an Active Directory. This must be updated based on your environment.

auth_ldap.dn_lookup_base = "OU=UserAccounts,DC=gopivotal,DC=com" defines the starting point in the LDAP directory from which the search for users will begin, targeting the UserAccounts organizational unit within the gopivotal.com domain.

auth_ldap.log = false must be set to true for diagnostic purposes only.

LDAP Authorization: This configuration guides RabbitMQ to use LDAP for authorization, ensuring only authorized users access RabbitMQ services. This leverages LDAP for managing RabbitMQ access and permissions, segregating users into different roles based on their group membership within the LDAP directory, and facilitating a secure, manageable way to control access to RabbitMQ resources.

This integrates RabbitMQ with the connected LDAP server for user authorization.

Understanding LDAP Queries is essential for configuring RabbitMQ’s LDAP integration, as it involves specifying how RabbitMQ queries the LDAP server to authenticate and authorize users.

advancedConfig section of RabbitMQ’s configuration where these LDAP settings are specified, allowing for customized authorization rules based on LDAP attributes and organizational units.

[
  {rabbitmq_auth_backend_ldap, [
    {group_lookup_base, "OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com"},
    {vhost_access_query, 
      { in_group, "CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com" }
    },
    {vhost_access_query, 
      { in_group, "CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com" }
    },
    {resource_access_query,
      { for, [
        {permission, configure, 
            {in_group, "CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com"}},
        {permission, write, 
            {in_group, "CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com"}},
        {permission, read, 
            {in_group, "CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com"}}
      ]}
    },
    {tag_queries, [
      {administrator, { in_group, "CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com" }},
      {monitoring,    { in_group, "CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com", "uniqueMember" }},
      {management,    { constant, true }}
    ]}
  ]}
].

group_lookup_base specifies the base DN (Distinguished Name) within the LDAP directory where RabbitMQ should look for groups. In this case, it’s set to OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com, which targets security groups under the user accounts organizational unit in the gopivotal.com domain.

vhost_access_query defines LDAP queries to determine which users have access to virtual hosts (vhosts) in RabbitMQ. Here, RabbitMQAdmins and RabbitMQUsers groups are specified, where their members are allowed access to all vhosts

Admins: CN=RabbitMQAdmins,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com
Users: CN=RabbitMQUsers,OU=SecurityGroups,OU=UserAccounts,DC=gopivotal,DC=com

resource_access_query outlines the permissions each group or user has regarding configuring, writing, and reading within the RabbitMQ environment. It specifies that,

  • Admins (RabbitMQAdmins) have configure, write, and read permissions.
  • Users (RabbitMQUsers) have read permissions.

tag_queries maps LDAP groups to RabbitMQ user tags, which determine the level of access and permissions users have in RabbitMQ. Here, the configuration defines three tags:

  • administrator assigned to members of the RabbitMQAdmins group.
  • monitoring assigned to members of the RabbitMQUsers group, explicitly mentioning the uniqueMember attribute, which might be specific to certain LDAP configurations.
  • management granted to all users as it’s set to true constantly, allowing basic management capabilities.

Once the above configuration details are adjusted and appended to your original cluster configuration, re-deploy RabbitmqCluster. This command will redeploy the cluster pods. After the deployment is successful, you should be able to log into the management UI using your Windows Credentials. Similarly, if you have an AMQP client, you can use the Windows Service Account Credentials to connect, authenticate and authorize against the RabbitMQ server.

For advanced authentication and authorization configuration, refer to the official documentation - ldap.

Hope you had fun coding!


comments powered by Disqus