CLI Authentication and Authorization with LDAP – Reverse Group Membership

A number of basic authentication and authorization options are available in Solace for both CLI users and messaging clients. Those options include internal, radius and LDAP.

Increasingly, LDAP is the preferred approach for authorization, using LDAP group membership to restrict access to members of those LDAP groups.

Due to the way that LDAP based authorization works, membership of a group is insufficient in itself without a “reverse group membership” attribute (also known as “back reference” or “back link”) also being maintained on the LDAP server.

In this blog I will describe an example setup for OpenLDAP and the corresponding Solace configuration for CLI user authentication and authorization.

The Solace configuration for messaging client authentication and authorization using LDAP will be covered in a future blog.

Finally I describe one of the benefits of having users and groups maintained in an external corporate directory – namely managing “Temporary Privileged Access” or TPA.

Authentication

Authentication is the process of verifying that “you are who you say you are”.

In Solace at the time of writing (SolOS 7.1.1) CLI Users may be authenticated using:

  • Basic Authentication (username/password credentials)

When using basic authentication, Solace may be configured to use either of the following to verify the username/password credentials:

  • Internal (username/password are checked against the internal appliance database)
  • RADIUS (username/password are forwarded to an external RADIUS server)
  • LDAP (username/password are forwarded to an external LDAP server)

In this blog I will be describing basic authentication with LDAP.

Authorization

Authorization is the process of verifying that “you are permitted to do what you are trying to do”, and to be authorised “you” must already be authenticated.

For CLI Users, the authentication and authorization methods are inextricably linked and are configured simultaneously through the authentication->user-class cli configuration settings. When you configure the CLI authentication type, you are also configuring the authorization type – there is no separate configuration for CLI authorization type.

In order to authorise a CLI User that user must be associated with a particular access level.

For CLI Users the permitted global access levels are as follows:

  • None
  • Read-only
  • Read-write
  • Admin

Note that per-vpn access levels are also available.

For further details of the available CLI User Access Levels refer to the Solace Messaging Platform Feature Guide – User Access To CLI Commands

If you are using the internal database for CLI user authentication, then the internal CLI user, when it is configured, is directly associated with the appropriate access level – for example username->global-access-level->read-only.

But when you are using LDAP the CLI user credentials are not stored on the appliance, instead they are stored in LDAP. So now how do you associate these users with the appropriate access levels?

The answer is to use LDAP group membership and to associate each LDAP group with access levels on the appliance.

In this paper I will be describing how to use LDAP group membership for authorization.

LDAP Server Implementations and Reverse Group Membership Maintenance

So how does the Solace appliance retrieve group membership information from LDAP?

It does so by searching for the username in LDAP and retrieving a group membership attribute.

This group-membership-attribute-name is separately configurable. By default in Solace it is named memberOf (note that in Solace this is case sensitive).

There are various LDAP server implementations and they vary in the way that they support the group membership attribute.

In general, users are added to groups as members – using a member attribute that contains the dn of the users.

However what we need is a memberOf attribute in the users that contains the dn of the groups.

Unfortunately, just adding the members to the groups does not always automatically result in a corresponding memberOf attribute appearing in the users.

Automatically maintaining these relationships is known as “reverse group membership maintenance”.

ldap-reverse-group-1

ldap-reverse-group-2

For example looking at the two most common LDAP server implementations I have seen in the field: Microsoft Active Directory (AD) and OpenLDAP.

AD natively supports reverse group membership using link-pair relationships defined within the Active Directory schema. A link-pair comprises exactly two attributes, the first is a writable “forward-link” (by default member) and the other is a read-only “back-link” (by default memberOf).

OpenLDAP needs the memberOf overlay. This overlay updates an attribute (by default memberOf) whenever changes occur to the membership attribute (by default member) of entries of the configured objectclass (groupOfNames by default) to trigger updates.

Refer to the OpenLDAP Administrators Guide for more details:
http://www.openldap.org/doc/admin24/guide.html#Reverse%20Group%20Membership%20Maintenance

The trouble with the above reference and most other references is that it describes how to configure the overlay using slapd.conf, which is no longer supported.

Instead, OpenLDAP should be configured using “On Line Configuration” (OLC) – which I describe below.

Note that other LDAP server implementations have similar functionality and need to be setup and configured appropriately to support group membership maintenance (as most do not support it by default).

Other common LDAP implementations:

  • Oracle Directory Server (needs a memberOf Plugin – attribute name ismemberOf)
  • RedHat Directory Server (needs a memberOf Plugin – attribute name memberOf)

OpenLDAP

OpenLDAP is an Open Source implementation of the LDAP directory service, widely used by many enterprise customers. Linux packages are available and in my final setup as described below, I used yum to install the latest package. Contrary to the warnings on openldap.org, I found this package to be up to date and to include all the various modules and overlays.

The recent versions of OpenLDAP (the last 5 years or so) should be set up using “On Line Configuration” (OLC) which allows dynamic configuration. Earlier versions were configured statically using a slapd.conf file – most of the resources you will find online give examples using slapd.conf – but this approach is no longer supported and so I have taken the OLC approach.

OpenLDAP Installation

I installed OpenLDAP on one of our lab servers (running CentOS 6.7).

To do this I ran yum as root to install the openldap related packages as follows:

# yum install -y openldap openldap-clients openldap-servers

This installed the LDAP server as well as ensuring the LDAP client/support libraries were up to date.

OpenLDAP Base Level Configuration

After installing OpenLDAP as above I found the configuration under /etc/openldap but unlike older versions of OpenLDAP there is no slapd.conf file – instead there is a directory structure under /etc/openldap/slapd.d containing the “On Line Configuration” (OLC) files.

Now there are plenty of links on the internet describing how to configure these files by editing them directly, but this is not the recommended approach.

# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.

Instead of editing these files I started up the LDAP server in its initial configuration state and then used the LDAP client utilities to dynamically configure the server “on line”.

First, I created an LDIF file containing the base level configuration as follows (note the leading spaces, hyphens and blank lines are important):

# cat olc-base-config.ldif
dn: olcDatabase={2}bdb, cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=solacesystems, dc=com
-
replace: olcRootDN
olcRootDN: cn=Manager, dc=solacesystems, dc=com
-
add: olcRootPW
olcRootPW: {SSHA}MsOfEPxo6E13qKnAl8hDlLDTIpq+nP+S

dn: olcDatabase={1}monitor, cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to *  by dn.base="gidNumber=0+uidNumber=0, cn=peercred, cn=exter
 nal, cn=auth" read  by dn.base="cn=Manager, dc=solacesystems, dc=com" read  by * n
 one

This modifies the configuration of the default bdb database as follows:

  • Changes the suffix from the initial value of dc=my-domain, dc=com to a new value of dc=solacesystems, dc=com
  • Changes the root DN from the initial value of cn=Manager, dc=my-domain, dc=com to a new value of cn=Manager, dc=solacesystems, dc=com
  • Sets a root password – using a slappasswd generated hash (see note below)

It also changes the monitor database olcAccess attribute value to match.

Note that these values would vary depending on your particular organizational/domain setup. For example instead of dc=solacesystems you might have dc=mycompany. A secure password is configured using ‘slappasswd –s secret’ to generate a password hash.

To apply the above LDIF file to the LDAP server it had to be started first:

# service slapd start

Then I ran the following as Linux root:

# ldapmodify -Y EXTERNAL -H ldapi:/// -f olc-base-config.ldif

Note the unusual options:

  • -Y EXTERNAL (external SASL for authentication)
  • -H ldapi:/// (connect to LDAP locally over IPC)
  • -f olc-base-config.ldif (file specified)

These options allowed me to apply the modifications to OpenLDAP as Linux root.

Note that although the suffix and root DN are configured there are still no entries, so for example I cannot search for the suffix dc=solacesystems, dc=com, because that entry still needs to be created (see below).

OpenLDAP memberOf Overlay Configuration

For Open LDAP to support reverse group membership maintenance, the memberOf module needs to be loaded and the overlay configured.

To load the module and configure the overlay I created another LDIF file as follows:

# cat olc-overlay-config.ldif
dn: cn=module, cn=config
objectClass: olcModuleList
cn: module
olcModulePath: /usr/lib64/openldap
olcModuleLoad: memberOf

dn: olcOverlay=memberOf, olcDatabase={2}bdb, cn=config
objectClass: olcmemberOf
objectClass: olcOverlayConfig
objectClass: olcConfig
objectClass: top
olcOverlay: memberOf

This modifies the configuration as follows:

  • Sets the path to the directory where the dynamic modules may be found
  • Loads the memberOf module
  • Adds the memberOf overlay to the default bdb database

Note that I have left the memberOf overlay in its default configuration, which sets the group objectclass to groupOfNames, the forward reference attribute name to member and the back reference attribute name to memberOf by default. Additional attributes are available to change those configurations if desired.

To apply this I ran the following as Linux root (note this is ldapadd not ldapmodify):

# ldapadd -Y EXTERNAL -H ldapi:/// -f olc-overlay-config.ldif

Again note the options which allow me to apply the modifications to OpenLDAP as Linux root:

  • -Y EXTERNAL (external SASL for authentication)
  • -H ldapi:/// (connect to LDAP locally over IPC)
  • -f olc-overlay-config.ldif (file specified)

Once this configuration is applied, the memberOf overlay will dynamically create the linked memberOf back reference attributes whenever any new members are added to groups.

IMPORTANT NOTE: Any group members that were created before this point would have had to be deleted and recreated so that the memberOf overlay can dynamically create the linked memberOf back reference attributes.

ADDITIONAL NOTE: It is also worthwhile configuring the refint overlay. This overlay ensures that when entries are deleted any forward references to them are also removed (I have not done so in this blog).

OpenLDAP Suffix Configuration

To configure the suffix entry for my directory, I created another LDIF file as follows:

$ cat solacesystems.ldif
dn: dc=solacesystems, dc=com
objectClass: dcObject
objectClass: organization
dc: solacesystems
o: solacesystems

Then I ran the following as a regular user (does not need to run as Linux root):

$ ldapadd -x -D cn=Manager, dc=solacesystems, dc=com -W -f solacesystems.ldif
Enter LDAP Password:

At the prompt enter the password you set for the root DN (hashed in olc-base-config.ldif above).

Note the options:

  • -x (use simple authentication instead of SASL)
  • -D cn=Manager, dc=solacesystems, dc=com (bind to the root dn)
  • -W (prompt for simple password)
  • -f solacesystems.ldif (file specified)

Note that I have not specified the ldapuri so it will connect to the localhost on the default LDAP port 389 – if you are running this command remotely you can specify –H for the ldapuri.

Configuring Users

To configure some users – for example for CLI, I created another LDIF file as follows:

$ cat solace-cli-users.ldif
dn: ou=solace-cli-users, dc=solacesystems, dc=com
ou: solace-cli-users
description: Solace CLI Users
objectClass: organizationalUnit

dn: cn=test-cli-user1, ou=solace-cli-users, dc=solacesystems, dc=com
objectClass: person
cn: test-cli-user1
sn: test-cli-user1
userPassword: {SSHA}yRi7Q5ido56674L2O7X+qOr8KbS0P0uF

dn: cn=test-cli-user2, ou=solace-cli-users, dc=solacesystems, dc=com
objectClass: person
cn: test-cli-user2
sn: test-cli-user2
userPassword: {SSHA}n5tJMssIPH+T/6/LDw2v1Bh5z5iA2CYA

dn: cn=test-cli-user3, ou=solace-cli-users, dc=solacesystems, dc=com
objectClass: person
cn: test-cli-user3
sn: test-cli-user3
userPassword: {SSHA}swoKYLzNmf0DacVmuVbBXWLI3ijAkmAo

This contains the following:

  • One ou=solace-cli-users entry as a base for the cli-users
  • Three example cli-user entries
  • Note that the passwords are hashed using slappasswd as above)

Then I ran the following as a regular user:

$ ldapadd -x -D cn=Manager, dc=solacesystems, dc=com -W -f solace-cli-users.ldif
Enter LDAP Password:

At the prompt enter the password you set for the root DN (hashed in olc-base-config.ldif above).

Note the options:

  • -x (use simple authentication instead of SASL)
  • -D cn=Manager, dc=solacesystems, dc=com (bind to the root dn)
  • -W (prompt for simple password)
  • -f solace-cli-users.ldif (file specified)

Again, if you are running this command remotely you can specify –H for the ldapuri.

Configuring Groups

To configure groups – for example some groups for CLI, I created another LDIF file as follows:

$ cat solace-cli-groups.ldif
dn: ou=solace-cli-groups, dc=solacesystems, dc=com
ou: solace-cli-groups
description: Solace CLI Groups
objectClass: organizationalUnit

dn: cn=cli-group-admin, ou=solace-cli-groups, dc=solacesystems, dc=com
cn: cli-group-admin
description: CLI admin group
objectClass: groupOfNames
member: cn=test-cli-user1, ou=solace-cli-users, dc=solacesystems, dc=com

dn: cn=cli-group-read-only, ou=solace-cli-groups, dc=solacesystems, dc=com
cn: cli-group-read-only
description: CLI read-only group
objectClass: groupOfNames
member: cn=test-cli-user2, ou=solace-cli-users, dc=solacesystems, dc=com

This contains the following:

  • One ou=solace-cli-groups entry as a base for the cli-groups
  • Two example cli-group entries
  • The first group-admin contains test-cli-user1 as a member
  • The second group-read-only contains test-cli-user2 as a member

Then I ran the following as a regular user:

$ ldapadd -x -D cn=Manager, dc=solacesystems, dc=com -W -f solace-cli-groups.ldif
Enter LDAP Password:

At the prompt enter the password you set for the root DN (hashed in olc-base-config.ldif above).

Note the options:

  • -x (use simple authentication instead of SASL)
  • -D cn=Manager, dc=solacesystems, dc=com (bind to the root dn)
  • -W (prompt for simple password)
  • -f solace-cli-groups.ldif (file specified)

Again, if you are running this command remotely you can specify –H for the ldapuri.

Verifying Reverse Group Membership is working

To check that the overlay was configured correctly and working I ran the following search.

$ ldapsearch -LLL -x -b ou=solace-cli-users, dc=solacesystems, dc=com '(cn=*)' memberOf
dn: cn=test-cli-user1, ou=solace-cli-users, dc=solacesystems, dc=com
memberOf: cn=cli-group-admin, ou=solace-cli-groups, dc=solacesystems, dc=com

dn: cn=test-cli-user2, ou=solace-cli-users, dc=solacesystems, dc=com
memberOf: cn=cli-group-read-only, ou=solace-cli-groups, dc=solacesystems, dc=com

dn: cn=test-cli-user3, ou=solace-cli-users, dc=solacesystems, dc=com

The memberOf attribute is an operational attribute, so it must be requested explicitly.

Note the output lists the 3 user entries with the memberOf attribute set to the dn of the group those entries are members of. This is generated automatically thanks to the memberOf overlay!

Remember, if you are running this command remotely you can specify –H for the ldapuri.

Configuring Solace

CLI/SEMP Authentication and Authorization

Now we have our LDAP server installed and configured it is time to configure Solace to use it.

In the previous section I have configured a set of users and groups for CLI authentication and authorization.

To configure Solace to use these I ran the following commands on the appliance to create an ldap-profile:

! LDAP PROFILE FOR CLI
home
enable
configure
authentication
create ldap-profile cli_users_profile
ldap-server ldap://192.168.32.40 index 1
search base-dn ou=solace-cli-users, dc=solacesystems, dc=com
search filter (cn=$CLIENT_USERNAME)
no shutdown
exit
exit

I have named the ldap-profile cli_users_profile.

I have specified the same search base and filter we used to test the LDAP configuration above.

Note that I did not configure an admin dn or password or configure tls (which would be recommended to improve security)

Also note that I have only configured 1 ldap-server (up to 3 are recommended for resilience).

Then I ran the following CLI commands to configure the authentication for CLI:

! CLI AUTHENTICATION
home
enable
configure
authentication
user-class cli
auth-type ldap cli_users_profile
access-level
default
global-access-level "none"
exit
ldap
group-membership-attribute-name "memberOf"
create group cn=cli-group-admin, ou=solace-cli-groups, dc=solacesystems, dc=com
global-access-level "admin"
exit
create group cn=cli-group-read-only, ou=solace-cli
groups, dc=solacesystems, dc=com
global-access-level "read-only"
exit
exit
exit
exit
exit

I have configured authentication for user-class cli to use the ldap-profile defined above.

Notice I have set the default access-level to “none” – this means that if the user successfully authenticates (that is they exist in LDAP and provide the correct password) but is not the member of any group they will get this level of authorization.

Then I have defined 2 groups corresponding to the groups I have configured in LDAP and matched those to appropriate global-access-level in Solace.

Note that you could also define groups for individual message-vpn access-levels for which you would need corresponding groups created in LDAP (I have not done so in this blog).

Trying out the CLI Login

To try out this setup I logged in as each of the users that were configured in LDAP above.

First, logged in as test-cli-user1 which is a memberOf cli-group-admin:

login as: test-cli-user1
Using keyboard-interactive authentication.
Password:

System Software. SolOS-TR Version 7.1.1.614

Copyright 2004-2015 Solace Systems,  Inc. All rights reserved.

solace> show authentication current-user

Access Level of Current User:
Global Access Level: admin
Message VPN                      Access-Level
-------------------------------- ------------
#config-sync                     read-write
...
...
solace>

Notice that as test-cli-user1 the current user has a Global Access Level: admin.

Second, logged in as test-cli-user2 which is a memberOf cli-group-read-only:

login as: test-cli-user2
Using keyboard-interactive authentication.
Password:

System Software. SolOS-TR Version 7.1.1.614

Copyright 2004-2015 Solace Systems,  Inc. All rights reserved.

solace> show authentication current-user

Access Level of Current User:
Global Access Level: read-only
Message VPN                      Access-Level
-------------------------------- ------------
#config-sync                     read-only
...
...
solace>

Notice that as test-cli-user2 the current user has a Global Access Level: read-only.

Third, logged in as test-cli-user3 which is not a memberOf any groups:

login as: test-cli-user3
Using keyboard-interactive authentication.
Password:

System Software. SolOS-TR Version 7.1.1.614

Copyright 2004-2015 Solace Systems,  Inc. All rights reserved.

solace> show authentication current-user

Access Level of Current User:
Global Access Level: none
solace>

Notice that as test-cli-user3 the current user has a Global Access Level: none.

Temporary Privileged Access

Now we have our users in LDAP we can put in place standard security related processes such as for example “Temporary Privileged Access” (TPA).

Under normal operation users might be members of the read-only group.

Then, only if they need to make an administrative change they would be temporarily “promoted” to the admin group.

This is easy for us now as we have our users and groups in LDAP.

For example to promote test-cli-user2 to admin we only need apply the following LDIF:

$ cat test-cli-user2-promote.ldif
dn: cn=cli-group-admin, ou=solace-cli-groups, dc=solacesystems, dc=com
changetype: modify
add: member
member: cn=test-cli-user2, ou=solace-cli-users, dc=solacesystems, dc=com

As follows:

$ ldapmodify -x -D cn=Manager, dc=solacesystems, dc=com -W -f test-cli-user2-promote.ldif
Enter LDAP Password:

Note that there is no need to remove them from the lower group as the higher privileged group applies (also note that groups in ldap cannot be empty).

Now, login as test-cli-user2 to see the difference:

login as: test-cli-user2
Using keyboard-interactive authentication.
Password:

System Software. SolOS-TR Version 7.1.1.614

Copyright 2004-2015 Solace Systems,  Inc. All rights reserved.

solace> show authentication current-user

Access Level of Current User:
Global Access Level: admin
Message VPN                      Access-Level
-------------------------------- ------------
#config-sync                     read-write
...
...
solace>

Notice that as test-cli-user2 the current user now has a Global Access Level: admin.

To “demote” them back to read-only you only need to delete them as a member from the admin group:

For example to demote test-cli-user2 from admin we only need apply the following LDIF:

$ cat test-cli-user2-demote.ldif
dn: cn=cli-group-admin, ou=solace-cli-groups, dc=solacesystems, dc=com
changetype: modify
delete: member
member: cn=test-cli-user2, ou=solace-cli-users, dc=solacesystems, dc=com

As follows:

$ ldapmodify -x -D cn=Manager, dc=solacesystems, dc=com -W -f test-cli-user2-demote.ldif
Enter LDAP Password:

Login as test-cli-user2 again, to see the change back to read-only:

login as: test-cli-user2
Using keyboard-interactive authentication.
Password:

System Software. SolOS-TR Version 7.1.1.614

Copyright 2004-2015 Solace Systems,  Inc. All rights reserved.

solace> show authentication current-user

Access Level of Current User:
Global Access Level: read-only
Message VPN                      Access-Level
-------------------------------- ------------
#config-sync                     read-only
...
...
solace>

Notice that as test-cli-user2 the current user now has a Global Access Level: read-only.

Finally note that your access-level does not change if you are already logged-in when the group membership is modified – only on your next login.

Solace Documentation

For more details on CLI User Authentication and Authorization on a Solace message router, refer to the Solace Messaging Platform Feature Guide – CLI User Authentication and Authorization.

For more details on Client Authentication and Authorization on a Solace message router, refer to the Solace Messaging Platform Feature Guide – Client Authentication and Authorization.