Files
Cactidocumentation/Settings-Auth-LDAP.md
TheWitness 5b2763b8f6 docs(auth): document LDAP OTP/MFA single-bind behavior and configuration (#231)
* docs(auth): document LDAP OTP/MFA single-bind behavior and configuration

Adds a One-Time Passwords (OTP / MFA) note to the LDAP authentication page
explaining that Cacti binds the user's password only once, that the DN
lookup never uses the user's password, and that OTP/MFA deployments should
use Specific Searching with a service account and a single server.

* docs(auth): recommend resilient DNS load balancer for LDAP OTP; qualify single-bind for failover; clarify No Searching
2026-09-30 16:47:01 -04:00

424 lines
18 KiB
Markdown

# LDAP Authentication
Cacti supports using LDAP authentication to access the Cacti GUI.
There are several different ways to use LDAP, which will be described in the
following sections.
## Be Aware
New authentication settings may not take effect immediately. We recommend to
open a **new** private browser window to test configuration changes.
## Defining some terms
Before proceeding, please ensure you are familiar with the following terms:
1. _LDAP_ - A communication language, or protocol. It is a defined structure
of how to ask questions of, and receive responses from, a directory.
It also defines what questions there exist to be asked, and what responses
there exist to be returned. LDAP is not a directory; it is a way to query
a directory.
2. _Directory_ - A database of objects, accompanied with other attributes.
Commonly, these objects are user identities, accompanied with passwords.
Sometimes, the objects are groups, accompanied by a list of members.
Usually the objects are stored in some type of hierarchical structure
for organizational and management purposes.
3. _DN_ - Short for _distinguished name_, a string that represents a
unique object in the directory. There can not be two DNs alike
in a directory. In Microsoft's _Active Directory_, this is a string
like 'CN=Joseph,OU=Accounting,OU=Users,DC=corp,DC=example,DC=com'.
4. _Search_ - A type of LDAP request, in which the client sends
some criteria to the server in an attempt to receive back a
list of directory objects that meet the search criteria.
5. _Bind_ - A type of LDAP request, in which the client sends the server a
username and a password in an attempt to confirm whether the password is
correct for that user.
6. _sAMAccountName_ - An attribute found in Microsoft's _Active Directory_
directory, and is what we casually know as a _username_. The _sAMAccountName_
does not uniquely represent an object in the Active Directory,
whereas the _DN_ does.
## Configuring LDAP
### LDAP General Settings
![LDAP Settings Page](images/ldap-settings.png)
#### Mode
There are three basic routines that Cacti can execute when handling an
LDAP authentication.
1. _No Searching_ - In this routine, Cacti simply binds to the LDAP server
using the credentials that were entered during login. Cacti performs a
transformation upon the username before binding, that which is specified
in the _Distinguished Name (DN)_ field. This transformation is useful,
for example, to add a fully-qualified domain name suffix, or to add a NetBIOS
domain name prefix. For example:
```<username>@example.com```
or
```domain\<username>```
2._Anonymous Searching_ - In this routine, Cacti connects to LDAP with no
authentication and attempts to perform a search for the _username_, in an
attempt to retrieve the specific DN associated with the username. Once
the specific DN of the username is found, Cacti binds to LDAP using the DN of
the user and the password that was entered during login. Please note, by
default, Microsoft's Active Directory does not permit anonymous searches, and
will refuse the search request.
3.Specific Searching_- In this routine, Cacti binds to LDAP using a service
account that was provided beforehand, then performs a search for the
_username_, in an attempt to retrieve the specific DN associated with the
username. Once the specific DN of the username is found, Cacti binds to LDAP
using the DN of the user and the password that was entered during login.
#### Encryption
1. _None_ - This is plain-text, normally on port tcp/389. Passwords are
transmitted over the network in clear text between Cacti and the directory.
2. _SSL_ - Commonly known as LDAPS, this is just like LDAP, but encrypted. This
normally runs on port tcp/636. Please note, this is not enabled by default for
Microsoft's Active Directory because it requires an encryption key and
certificate to be installed on the AD controller(s).
3. _TLS_ - This is plain LDAP, but a START_TLS command is sent by the client to
the server to initiate encryption. Normally runs on port tcp/389 and can be
entered into during a regular LDAP session.
Please note that some directories will limit the request types to which they
respond when there is no encryption on the LDAP communication.
#### Referrals
An LDAP Referral is a field returned in an LDAP response message. The referral
provides a list of alternate sources from which directory information can be
obtained. In the case of a replicated directory such as Microsoft's Active
Directory, the referral may contain an LDAP URL which could resolve to any
participating LDAP server, whether correctly configured or not.
### LDAP Group Settings
Cacti can enforce that a user be a member of a specific directory group to be
granted access to Cacti. This is useful when your directory contains a mix of
users who should and should not be granted access to Cacti. For Cacti to
require that the user be apart of a group, Cacti will send a _compare_ request
to the directory server asking the server if a specific group has any
parameters that contain a specific username. As an example, a compare requests
asks the following type of question:
Does there exist a group named
`CN=cacti-admins,OU=Admin_Groups,OU=Groups,DC=corp,DC=company,DC=com`, attached
to which there is an attribute named `member`, where the value of the attribute
is `CN=Joseph,OU=Admins,DC=example,DC=com`?
The following three settings determine the content of the compare request.
1. _Group Distinguished Name (DN)_ - The DN of the group into which the
directory server should search for attributes. For example:
```html
CN=cacti-admins,OU=Admin_Groups,OU=Groups,DC=corp,DC=company,DC=com
```
2.Group Member Attribute_ - The name of the attribute into which the
directory server should search for the user. For example:
```bash
member
```
3.Group Member Type_ - The format of the text string which should represent
the user.
### Specific Search Settings
1. _Search Base_ - The portion of the directory hierarchy inside which the
server should perform the search. When the directory contains many objects,
the time and resources required to search the directory are greater. The
_search base_ setting is useful to reduce the portion of the directory that is
searched, thus increasing speed and reducing processor load on the directory
server. This setting is also useful if you want to restrict access to Cacti to
users who exist in a particular location in the director heierarchy.
2. _Search Filter_ - The criteria for which the directory server should search.
Any parameters that the server is capable of understanding are permitted here.
Cacti will perform a substitution for the phrase `<username>` in the search
filter, and will replace it with the username. This field must be in
acceptable LDAP syntax. A useful example of a search filter would be:
```bash
(sAMAccountName=<username>)
```
But more complex filers are also permitted, such as:
```bash
(&(sAMAccountName=<username>)(memberOf=CN=cacti-admins,OU=Admin_Groups,OU=Groups
,DC=corp,DC=company,DC=com))
```
3.Search Distinguished Name (DN)_ - The username of the service account with
which Cacti will bind to the directory.
4.Search Password_ - The password of the service account with which Cacti
will bind to the directory.
### LDAP CN Settings
#### Mapping an LDAP user to a Cacti user
Cacti stores many personal preferences and settings into its database that make
it easier to use Cacti. For example, the GUI Theme, the Default View Mode, and
the User Language are a few of these user settings. These settings are not
stored in the LDAP directory, so they are not returned in the LDAP response.
Therefore, Cacti will create a local user identity for each LDAP user who logs
in. When Cacti creates a local user, it can automatically populate the
following two parameters from the LDAP directory. If Cacti sees a local user
already exists, it will not attempt to update the user with values from the
directory.
1. _Full Name_ - The LDAP attribute name which contains a user's full name.
Some common examples are 'displayname' or 'cn'.
2. _Email_ - The LDAP attribute name which contains a user's email address.
One common example is 'mail'.
**Always user lower case**. No matter if the directory's attribute name contains
uppercase characters (e.g. `fullName`), the respective field must be filled
out in lower-case (`fullname`).
## A few notes
### One-Time Passwords (OTP / MFA)
Cacti supports directories where users authenticate with a One-Time Password
(OTP) or another Multi-Factor Authentication (MFA) token, but the LDAP _Mode_
must be chosen so that the user's single-use credential is presented to the
directory only once.
On a single-server authentication path, Cacti binds the user's password exactly
once, during the final authentication step. The Distinguished Name (DN) lookup
that precedes it never uses the user's password (see the note on multi-server
failover below):
- _No Searching_ performs no bind during the lookup (the DN is built from the
template), then binds once as the user.
- _Anonymous Searching_ binds anonymously to locate the DN, then binds once as
the user.
- _Specific Searching_ binds with the service account to locate the DN, then
binds once as the user.
Group membership checks, when enabled, reuse the connection that was already
bound with the user's credential and do not perform a second bind.
Because Active Directory refuses anonymous searches by default, an OTP/MFA
deployment on AD should use _Specific Searching_ with a dedicated service
account. The service account performs the directory search so that the user's
one-time code is preserved for the single authentication bind. _No Searching_
is also safe for OTP when the DN template alone identifies the user, since it
performs no directory lookup; choose _Specific_ or _Anonymous Searching_ only
when a lookup is actually required to resolve the DN.
Finally, for OTP/MFA do not use the _Server(s)_ space-delimited multi-server
list. That field fails over from left to right, so if the first server consumes
the one-time password and then returns an error, Cacti re-attempts the bind
against the next server with an already-spent code, which will fail. Instead,
point the _Server(s)_ field at a single, resilient DNS name fronted by a DNS
load balancer (VIP). Treat that DNS/load-balancer layer as the resilient,
highly-available entry point: it handles backend failover transparently, so
Cacti only ever performs one authentication bind per login and the single-use
code is never replayed.
### Certificate verification
When using LDAPS or STARTTLS, the Cacti server (as an LDAP client) must trust
the certificate presented by the directory server. PHP's LDAP functions use the
system OpenLDAP library, which reads its certificate configuration from
`/etc/ldap/ldap.conf` (Debian/Ubuntu) or `/etc/openldap/ldap.conf`
(RHEL/Rocky/AlmaLinux).
#### Adding a CA certificate on Linux
If the directory server uses a certificate signed by an internal CA or a
self-signed certificate, install the CA certificate on the Cacti server and
configure the OpenLDAP client library to trust it.
**Debian/Ubuntu:**
```shell
# Copy the CA certificate
cp /path/to/internal-ca.crt /usr/local/share/ca-certificates/internal-ca.crt
# Update the system trust store
update-ca-certificates
```
Add the following line to `/etc/ldap/ldap.conf` if not already present:
```console
TLS_CACERT /etc/ssl/certs/ca-certificates.crt
```
**RHEL/Rocky/AlmaLinux:**
```shell
# Copy the CA certificate
cp /path/to/internal-ca.crt /etc/pki/ca-trust/source/anchors/internal-ca.crt
# Update the system trust store
update-ca-trust extract
```
Add the following line to `/etc/openldap/ldap.conf` if not already present:
```console
TLS_CACERT /etc/pki/tls/cert.pem
```
#### Controlling certificate verification strictness
By default, the OpenLDAP library requires a valid, trusted certificate
(`TLS_REQCERT demand`). You can relax this for testing, but do not disable
verification in production; it exposes the LDAP bind to interception.
```console
# /etc/ldap/ldap.conf or /etc/openldap/ldap.conf
# Require a valid certificate (default, recommended for production)
TLS_REQCERT demand
# Accept certificates signed by the configured CA even if the hostname
# does not match (useful if the LDAP server has an internal hostname)
TLS_REQCERT allow
# Disable certificate verification entirely — DO NOT use in production
TLS_REQCERT never
```
#### Verifying the configuration
Test the LDAP TLS connection from the Cacti server before enabling it in Cacti:
```shell
# Test LDAPS (port 636)
openssl s_client -connect ldap.example.com:636 -CAfile /path/to/ca.crt
# Test STARTTLS (port 389)
openssl s_client -connect ldap.example.com:389 -starttls ldap -CAfile /path/to/ca.crt
```
> **Note**: `openssl s_client` verifies the certificate chain but does not
> check the server hostname. Use `ldapsearch` or a dedicated TLS testing tool
> (e.g. `testssl.sh`) to confirm hostname validation.
```shell
# Full LDAP query over TLS using ldapsearch (-W prompts for password)
ldapsearch -H ldaps://ldap.example.com -b "dc=example,dc=com" \
-D "cn=service,dc=example,dc=com" -W "(cn=testuser)"
```
A successful `CONNECTED` and `Verify return code: 0 (ok)` in the `openssl`
output confirms the Cacti server trusts the certificate.
#### Adding a CA certificate on Windows (IIS)
On Windows, PHP's LDAP extension uses the Windows Certificate Store. Import the
CA certificate using the Microsoft Management Console:
1. Open `mmc.exe`, go to **File > Add/Remove Snap-in**, add
**Certificates** for the **Computer account**.
2. Expand **Trusted Root Certification Authorities > Certificates**.
3. Right-click, select **All Tasks > Import**, and follow the wizard to import
the CA certificate (`.crt` or `.cer` file).
4. Restart the IIS service (`net stop w3svc && net start w3svc`) for the
change to take effect.
### Search Result Reference (Referrals)
In Microsoft's Active Directory, LDAP response messages may contain a referral
to other directory servers. If you are using LDAPS and have installed a
certificate on some LDAP servers and not others, LDAP lookups will fail
intermittently because LDAPS negotiations will succeed with some directory
servers while failing with other directory servers. If you are experiencing
intermittent LDAP failures, ensure that the Cacti server has network access to
all directory servers, and that all directory servers are properly configured.
## Common Scenarios
These following scenarios are designed to help you see the different ways to
harness the power of LDAP and build a working LDAP configuration in your
environment.
### A small office where everyone has access to Cacti
In this scenario, a small LDAP directory contains users who are all granted
access to Cacti (there are no users denied from Cacti). Some may be
administrators, while others are read-only users.
To handle this scenario, start by creating a new local user in Cacti with
read-only permissions. Name the user 'MyLdapTemplate'. Next, in Cacti's
Authentication settings, set the `User Template` field to 'MyLdapTemplate'.
Set the `Mode` to 'No Searching'. Set the `Distinguished Name (DN)` field to
```<username>@example.com'```, where 'example.com' is the name of your domain.
When any user logs in to Cacti, their password will be checked against the LDAP
directory and they'll be granted access to Cacti with read-only access (from
the LDAP template user). Once a new user logs in, Cacti will create a local
user where the user's `Realm` is 'LDAP'. You may then optionally promote that
user to an administrator by visiting the `Users` page, locating the account for
the LDAP user, and granting additional permissions to that user.
### A large office where you only want a subset of users to access Cacti
In this scenario, a large LDAP directory contains a mix of users who should,
and should not, be granted access to Cacti.
There are two ways to handle this scenario. You may either manually authorize
users within Cacti, or you may use a group in the directory to define the
authorized users.
To handle this scenario by manually authorizing users within Cacti, navigate to
the Authentication settings, and set the `User Template` field to 'No User'.
Set the `Mode` to 'No Searching'. Set the `Distinguished Name (DN)` field t
```<username>@example.com```, where 'example.com' is the name of your domain.
Next, navigate to the `Users` page and create a new user where the username
matches the username in the directory. Set the user's `Realm` to 'LDAP'.
Grant your desired permissions to the user. When that user logs in to Cacti,
their password will be checked against the LDAP directory and they'll be
granted access to Cacti based upon their local account.
To handle the large office scenario by using group membership, start by
creating a user in the directory that can be used for searching the directory
(this is sometimes referred to as a Service Account). Under normal
circumstances, this directory user does not need elevated permissions. Next,
create a group in the directory that contains all the users who should be
granted access to Cacti. Next, in Cacti, create a new local user named
'MyLdapTemplate', with administrator permissions. In Cacti's Authentication
settings, set the `User Template` field to 'MyLdapTemplate'. Set the `Mode` to
'Specific Searching'. Leave the `Distinguished Name (DN)` field blank. Set
the `Require Group Membership` field to enabled. Set the `Group Distinguished
Name (DN)` to the name of the group. Set `Group Member Attribute` to 'member'.
Set `Group Member Type` to 'Distinguished Name'. Set `Search Base` to the DN
of the hierarchical structure in the directory which contains all the users,
such as 'OU=Users,DC=example,DC=com'. Set `Search Filter` to
```'sAMAccountName=<username>'```. Set `Search Distinguished Name (DN)` to the
username of the service account you created in the directory. Set `Search
Password` to the password for the service account. Optionally, set `Full Name`
to the directory attribute that contains the user's name, such as 'cn', and
also set `Email` to the directory attribute that contains the user's email
address, such as 'mail'.
---
Copyright (c) 2004-2026 The Cacti Group