ZendHQ Daemon LDAP Authentication and Authorization
LDAP is a lightweight directory access protocol that you can use to authenticate and authorize users in ZendHQ using a central LDAP server like Microsoft Active Directory or OpenLDAP's slapd server. LDAP authentication and authorization complements ZendHQ local Role-Based Access Control (RBAC).
-
There is no requirement to add users to the ZendHQ local RBAC database.
-
Users are authenticated by the remote LDAP server using user name and password.
-
Users are authorized by looking up their group membership on the remote LDAP server:
-
Define a file that maps LDAP group names to local ZendHQ RBAC group names.
-
Add local RBAC groups to the ZendHQ local RBAC database and give the groups access to ZendHQ services.
-
Navigation:
LDAP Authentication and Authorization concepts
Organizations are free to set up their LDAP servers in many different ways, therefore it is not possible to provide a generic ZendHQ LDAP authentication and authorization configuration that would work with all of them. In this document we explain the concept and provide several configuration examples.
In the following example scenario, we use OpenLDAP client programs to demonstrate the steps that the ZendHQ daemon would perform. The hypothetical LDAP server has the following properties:
Property |
Description |
---|---|
ldap.example.com | hostname of the LDAP server |
cn=admin,dc=example.com | service user DN (Distinguished Name) |
1234 | service user password |
cn=Users,dc=example.com | users and groups LDAP tree |
john@example.com | user name |
Service user is a technical user with LDAP search permissions provided by the LDAP server administrator.
The sample user's LDAP record looks like the following:
dn: john,CN=Users,DC=example.com objectClass: person objectClass: user distinguishedName: CN=john,CN=Users,DC=example.com memberOf: CN=Developers,CN=Users,DC=example.com memberOf: CN=Administrators,CN=Builtin,DC=example.com userPrincipalName: john@example.com
When users request to log in, they provide a user name and password. ZendHQ uses the provided user name, provided service user name and password, and performs a search on the remote LDAP server with a configurable search base and filter:
> ldapsearch -H ldap://ldap.example.com \ -D 'cn=admin,dc=example.com' -w 1234 \ -b 'cn=Users,dc=example.com' \ '(&(userPrincipalName=john@example.com)(objectClass=person)(objectClass=user))' \ dn
The search must return one single user entry with the user's distinguished name (DN) for it to be a valid user name:
dn: CN=john,CN=Users,DC=example.com
ZendHQ uses the returned user's DN and the password provided by the user to authenticate the user:
> ldapwhoami -H ldap://ldap.example.com \ -D 'CN=john,CN=Users,DC=example.com' -w '<password>'
When authentication succeeds, ZendHQ performs a search for group names using the provided service user and the user's distinguished name (DN) from the user lookup:
> ldapsearch -H ldap://ldap.example.com \ -D 'cn=admin,dc=example.com' -w 1234 \ -b 'CN=john,CN=Users,DC=example.com' \ '(objectClass=*)' \ memberOf
The search returns zero, one or multiple memberOf attribute values with distinguished names of groups the user is member of:
memberOf: CN=Developers,CN=Users,DC=example.com memberOf: CN=Administrators,CN=Builtin,DC=example.com
ZendHQ uses a map file with regular expressions to match LDAP group names to ZendHQ local RBAC group names:
CN=Developers,.* devel
The LDAP group CN=Developers,CN=Users,DC=example.com matches the regular expression in the map file and the user is assigned to the ZendHQ local RBAC group devel.
ZendHQ LDAP configuration
You find ZendHQ LDAP configuration directives in the zendhqd.ini file located in the $PREFIX/etc/ directory, where $PREFIX is the directory where ZendHQ is installed.
The zendhqd prefix is omitted in the following table; the full directive name is always zendhqd.$DIRECTIVE:
Directive |
Usage |
---|---|
ldap.valid_user_regex | Defines the regular expression for validating user names |
ldap.local_rbac_fallback | Enables local RBAC fall-back |
ldap.server_url | Defines the LDAP server url |
ldap.lookup_user_dn | Enables user lookup |
ldap.service_user_dn | Defines the service user DN |
ldap.service_user_psw | Defines the service user password |
ldap.user_auth_dn | Defines the User DN template for authentication |
ldap.group_lookup_base | Defines the search base for looking up group names |
ldap.group_lookup_filter | Defines the search filter for looking up group names |
ldap.group_lookup_attribute | Defines the group name attribute |
ldap.user_lookup_base | Defines the search base for looking up user names |
ldap.user_lookup_filter | Defines the search filter for looking up user names |
ldap.groups_map | Defines the name of the groups map file |
How to enable ZendHQ LDAP Authentication and Authorization
LDAP authentication and authorization is implemented as a separate ZendHQ extension, which is disabled by default. You must configure LDAP authentication and authorization first before enabling the extension. Failures in configuration automatically disable the LDAP authentication and authorization.
To enable the LDAP authentication and authorization
-
Set all the required configuration directives in the zendhqd.ini file.
-
Uncomment the following line in the ZendHQ configuration file:
zendhqd.extension = zendhq_ldap
-
Restart the ZendHQ daemon now.
The extension and its configuration directives are loaded and enabled.
Templates
Use templates to build LDAP query parameters, like the base DN, filter, etc.
Templates can contain variable names in the form {<name>}, which are expanded to actual values. For example, if the login user name is admin, a template string "CN={user},DC=example.com" is expanded to "CN=admin,DC=example.com".
The following variables are supported:
Variable | Description |
---|---|
{user} | Login user name |
{user_dn} | Distinguished name (DN) of the user from the LDAP lookup |
Directives
The following ZendHQ configuration directives are supported:
-
ldap.valid_user_regex
Defines the regular expression for validating user names. All user names are checked against this regular expression before sending them to the LDAP server. Works as a filter for valid user names and protects against potential LDAP injection attacks.
The default value is undefined.
Example:
zendhqd.ldap.valid_user_regex = "[a-z][.a-z0-9_-]*"
-
ldap.local_rbac_fallback
Defines whether to use local RBAC fall-back if remote LDAP authentication fails. Set it to true or false. With the local RBAC fall-back enabled, users can still log in using the local RBAC database even if the remote LDAP authentication fails. The users must be defined in the local RBAC database.
The default value is false.
Example:
zendhqd.ldap.local_rbac_fallback = false
-
ldap.server_url
Defines a comma- or whitespace-separated list of LDAP server URIs containing only the schema, the host, and the port fields. Apart from ldap, other recognized values of the schema field are ldaps (LDAP over TLS) and ldapi (LDAP over IPC). The first server in the list that responds is used for authentication and authorization.
No default value.
Example:
zendhqd.ldap.server_url = ldap://ldap.example.com
-
ldap.lookup_user_dn
Defines whether to look up users or not.
-
Set this to false to authenticate users directly without LDAP lookup.
-
Set this to true if two-step authentication is required and the user must be looked up first in the LDAP server. If you set this directive to true, then you must also set ldap.service_user_dn, ldap.service_user.psw, ldap.user_lookup_base, ldap.user_lookup_filter, and ldap.user_lookup_attribute directives.
The default value is false
Example:
-
zendhqd.ldap.lookup_user_dn = false
-
ldap.service_user_dn
Defines the service user Distinguished Name (DN). The service user is used to look up users and groups on the LDAP server. Use an empty value for anonymous access or leave undefined to use the user being authenticated.
If theldap.lookup_user_dn directive is set to true, setting the service user (possibly to an empty string for anonymous access) is required.Default value is undefined.
Example:
zendhqd.ldap.service_user_dn = "CN=admin,CN=Users,DC=ldap,DC=example.com"
-
ldap.service_user_psw
Defines the service user password.
The default value is undefined.
Example:
zendhqd.ldap.service_user_psw = "1234"
-
ldap.user_auth_dn
Defines the user DN template used for authentication.
This value is passed to the LDAP server as the Distinguished Name along with the user password when binding to the LDAP directory during the authentication.
Defaults to "{user}" when the ldap.lookup_user_dn directive is false. Defaults to "{user_dn}" when the ldap.lookup_user_dn directive is true.
Example:
zendhqd.ldap.user_auth_dn = "{user}"
-
ldap.group_lookup_base
Defines the LDAP search base template for looking up group names. Used as a search base when looking up group names.
Default value is undefined.
Example:
zendhqd.ldap.group_lookup_base = "{user_dn}"
-
ldap.group_lookup_filter
Defines the LDAP search filter template for looking up group names. Used as a search filter for the specific user when looking up group names.
Default value is undefined.
Example:
zendhqd.ldap.group_lookup_filter = "(objectClass=*)"
-
ldap.group_lookup_attribute
Defines the name of the LDAP attribute containing group names. Values of this attribute are used as group names for the given user. In addition to existing LDAP attributes, dn can be used for the Distinguished Name.
Default value is undefined.
Example:
zendhqd.ldap.group_lookup_attribute = "memberOf"
-
ldap.user_lookup_base
Defines the LDAP search base template for looking up users. Used as a search base when looking up users. If the the ldap.lookup_user_dn directive is set to true, this directive is required.
Default value is undefined.
Example:
zendhqd.ldap.user_lookup_base = "CN=Users,DC=ldap,DC=example.com"
-
ldap.user_lookup_filter
Defines the LDAP search filter template for looking up users. Used as a search filter for the specific user when looking users. If the ldap.lookup_user_dn directive is set to true, this directive is required.
Default value is undefined.
Example:
endhqd.ldap.user_lookup_filter = "(&(userPrincipalName={user}) (objectClass=person) (objectClass=user))"
-
ldap.groups_map
Defines the name of the file that maps LDAP group names to ZendHQ RBAC group names. Each line in the file must contain a regular expression matching LDAP group names followed by a ZendHQ RBAC group name separated by at least two spaces or <TAB> characters.
Default value is $PREFIX/etc/ldap_groups.
Example:
zendhqd.ldap.groups_map = /opt/zend/zendphp/etc/ldap_groups
LDAP groups file
The LDAP groups file maps LDAP group names to ZendHQ local RBAC group names. The map file is a regular text file and must be stored in the location configured with the ldap.groups_map directive.
-
Each line in this file must contain a regular expression matching LDAP group names followed by a ZendHQ RBAC group name separated by at least two spaces or <TAB> characters.
-
Lines starting with ; or # characters are comments and ignored when reading the file.
-
The file can contain multiple lines that are processed in the order they appear in this file. The first regular expression matching the LDAP group name will be used.
Example:
CN=Developers,.* devel
In this example, the ZendHQ RBAC group name devel is used for the LDAP group name "CN=Developers,CN=Users,DC=ldap,DC=example.com".
Examples
The following are ZendHQ LDAP configuration examples for some LDAP servers.
Active Directory without user lookup
A Microsoft Active Directory configured to allow user authentication using the userPrincipalName attribute value.
-
All the users have LDAP search permissions and LDAP service user is not required.
-
Users are expected to log in with their name only without the @domain part and we use the {user}@example.com.org template to build the userPrincipalName attribute value.
-
User LDAP records contain the memberOf attribute with LDAP group names.
Given a user LDAP record for the user john:
dn: CN=john,CN=Users,DC=example.com,DC=org objectClass: person objectClass: user distinguishedName: CN=john,CN=Users,DC=example.com,DC=org memberOf: CN=Developers,CN=Users,DC=example.com,DC=org memberOf: CN=Administrators,CN=Builtin,DC=example.com,DC=org userPrincipalName: john@example.com.org
Use the following ZendHQ LDAP configuration directives:
zendhqd.ldap.lookup_user_dn = false ;zendhqd.ldap.service_user_dn = ;zendhqd.ldap.service_user_psw = zendhqd.ldap.user_auth_dn = "{user}@example.com.org" zendhqd.ldap.group_lookup_base = "CN=Users,DC=example.com,DC=org" zendhqd.ldap.group_lookup_filter = \ "(&(userPrincipalName={user}@example.com.org)(objectClass=person)(objectClass=user))" zendhqd.ldap.group_lookup_attribute = "memberOf"
Active Directory with user lookup
A Microsoft Active Directory configured to require user distinguished name for authentication and a service user to lookup users and groups.
-
Users are expected to log in with their full login name user@domain matching the userPrincipalName LDAP attribute.
-
User LDAP records contain the memberOf attribute with LDAP group names.
Given a user LDAP record for the user john@example.com.org:
dn: CN=john,CN=Users,DC=example.com,DC=org objectClass: person objectClass: user distinguishedName: CN=john,CN=Users,DC=example.com,DC=org memberOf: CN=Developers,CN=Users,DC=example.com,DC=org memberOf: CN=Administrators,CN=Builtin,DC=example.com,DC=org userPrincipalName: john@example.com.org
Use the following ZendHQ LDAP configuration directives:
zendhqd.ldap.lookup_user_dn = true zendhqd.ldap.service_user_dn = cn=admin,dc=example.com,dc=org zendhqd.ldap.service_user_psw = 1234 zendhqd.ldap.user_lookup_base = "CN=Users,DC=example.com,DC=org" zendhqd.ldap.user_lookup_filter = \ "(&(userPrincipalName={user})(objectClass=person)(objectClass=user))" zendhqd.ldap.user_auth_dn = "{user_dn}" zendhqd.ldap.group_lookup_base = "{user_dn}" zendhqd.ldap.group_lookup_filter = "(objectClass=*)" zendhqd.ldap.group_lookup_attribute = "memberOf"
OpenLDAP server with user and group lookup
An OpenLDAP server configured with separate user and group records and requiring a service user for lookup.
-
Users are expected to log in with their user name matching the uid LDAP attribute.
-
Group LDAP records contain member attributes with user distinguished names belonging to that group.
Given a user LDAP record for the user john:
dn: uid:john,ou=users,dc=example.com,dc=org objectClass: person objectClass: inetOrgPerson uid: john
And a group LDAP record for the group developers:
dn: cn=developers,ou=groups,dc=example.com,dc=org objectClass: groupOfNames member: uid=admin,ou=users,dc=example.com,dc=org member: uid=john,ou=users,dc=example.com,dc=org
Use the following ZendHQ LDAP configuration directives:
zendhqd.ldap.lookup_user_dn = true zendhqd.ldap.service_user_dn = cn=admin,dc=example.com,dc=org zendhqd.ldap.service_user_psw = 1234 zendhqd.ldap.user_lookup_base = "ou=users,dc=example.com,dc=org" zendhqd.ldap.user_lookup_filter = \ "(&(uid={user})(objectClass=person)(objectClass=inetOrgPerson))" zendhqd.ldap.user_auth_dn = "{user_dn}" zendhqd.ldap.group_lookup_base = "ou=groups,dc=example.com,dc=org" zendhqd.ldap.group_lookup_filter = \ "(&(member={user_dn})(objectClass=groupOfNames))" zendhqd.ldap.group_lookup_attribute = "dn"