.. title:: Configuring Kafka Client Authentication with LDAP
.. meta::
:description: Describes how to use LDAP to configure Kafka Client authentication across clusters that use SASL/PLAIN
.. _client-auth-with-ldap:
Configuring |ak| Client Authentication with LDAP
------------------------------------------------
.. important:: This software is available under a
`Confluent enterprise license `__. You can use
this software for a 30-day trial period without a license key. If you are a subscriber, contact
Confluent Support at support@confluent.io for more information. Note that this license applies
to |ak| brokers. |ak| clients do not require a license.
.. end-license
You can use Active Directory (AD) or LDAP to configure |ak| client authentication
across all of your |ak| clusters that use SASL/PLAIN. The SASL/PLAIN binding to
LDAP requires a password provided by the |ak| client.
* Confluent does not recommend using SASL/PLAIN with LDAP for interbroker
communication because intermittent LDAP errors can cause significant broker
performance issues. Instead, keep authentication internal to the |ak| cluster
(using mTLS, SALS/PLAIN with no Callback Handler, or other options).
* Note that you cannot bind SASL/SCRAM to LDAP because |ak| client credentials
(the password) cannot be sent by the |ak| client.
You must set up an LDAP server (for example, AD) before starting up the |ak|
cluster. The configuration that follows is based on the assumption that you have
an LDAP server at the URL ``LDAPSERVER.EXAMPLE.COM:3268`` that is accessible using DNS
lookup from the host where the broker is run. While the configuration expects a
Kerberos-enabled LDAP server, Kerberos is not required; you can perform a
simple bind if your LDAP supports it. These security settings must match your LDAP server configuration.
If your LDAP server authenticates |ak| clients using Kerberos, the keytab file
and principal should be updated in authorizer JAAS configuration option
``ldap.sasl.jaas.config``.
If you wish to disable LDAP group authorization you can set the flag ``ldap.group.authorization.enable``
to ``false``.
.. tip::
The approach to configuring |ak| client authentication with LDAP depends in large
part on the LDAP mechanism you want to use:
**Kafka requests that the LDAP server validate credentials (recommended)**
Using this method, |ak| takes user-specified LDAP login credentials, converts
the username into an LDAP-formatted name (such as ``DN=JDoe,OU=eng,DC=org,DC=com``),
then uses the LDAP-formatted name and user-supplied password to log in to LDAP
as the identified user. This is known as a **simple bind**. This method
may result in many new connections/binds to LDAP, but is considered more secure
because |ak| does not need access to user passwords stored in LDAP.
If you want to avoid local comparisons and have the LDAP server perform
validation by having |ak| perform simple binds on behalf of users, then do
not specify a value for ``ldap.user.password.attribute``.
**Kafka performs a local password comparison**
Using this method, |ak| fetches local LDAP entries that have a hashed password
in the user entry of the ``ldap.user.password.attribute`` property. |ak| takes
the password supplied by the user and performs a local hash and compares it to
what is stored in the LDAP user entry.
If you want |ak| to fetch user passwords stored in ``ldap.user.object.class``
from the LDAP server and perform credential validation locally, specify
``ldap.user.password.attribute`` to indicate the LDAP attribute in your schema
that contains the user's password. Note that this is not recommended, secure,
or a best practice because |ak| must have permission to read hashed passwords
from LDAP, and may have compatibility issues if, for example, the LDAP server
uses a hash function that |ak| does not recognize.
To configure |ak| client authentication with AD/LDAP:
#. Start the LDAP server.
#. Add the user name and password to LDAP:
::
dn: uid=client,ou=people,dc=planetexpress,dc=com
userPassword: client-secret
#. Enable LDAP authentication for |ak| clients by adding the LDAP callback handler
to ``server.properties`` in the broker.
Add the SASL configuration:
::
listener.name.sasl_plaintext.sasl.enabled.mechanisms=PLAIN
listener.name.sasl_plaintext.plain.sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required;
listener.name.sasl_plaintext.plain.sasl.server.callback.handler.class=
io.confluent.security.auth.provider.ldap.LdapAuthenticateCallbackHandler
If you want to use LDAP authentication for interbroker communication, then
you must include the broker's user name and password in your SASL configuration.
Add the LDAP configuration:
::
ldap.java.naming.provider.url=ldap://openldap:389
# Authenticate to LDAP
ldap.java.naming.security.principal=CN=admin,DC=planetexpress,DC=com
ldap.java.naming.security.credentials=GoodNewsEveryone
ldap.java.naming.security.authentication=simple
# Locate users
ldap.user.search.base=ou=people,dc=planetexpress,dc=com
ldap.user.name.attribute=uid
ldap.user.object.class=user
.. note::
Only include the attribute ``ldap.user.password.attribute`` when your LDAP
server does not support simple bind. Otherwise, be aware that if you include
``ldap.user.password.attribute``, simple bind is disabled.
#. Restart the |ak| broker.
::
/bin/kafka-server-start etc/kafka/server.properties
#. Specify the |ak| client configuration in ``producer.properties`` and ``consumer.properties``:
::
sasl.mechanism=PLAIN
security.protocol=SASL_PLAINTEXT
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule
required username="client" password="client-secret";
It's recommended that you encrypt the password in your |ak| client configuration
using :ref:`secrets`. The following example shows an encrypted |ak| client
configuration:
::
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule
required username="client" password=${securepass:/secretsDemo/server.properties:server.properties/sasl.jaas.config/=org.apache.kafka.common.security.plain.PlainLoginModule /password};
.. note::
Credentials are sent in PLAIN text, so be sure to use TLS with LDAP.
.. _test-ldap-client-authentication:
Testing and Troubleshooting LDAP Client Authentication
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This section provides basic troubleshooting tips to address common errors that
can occur when configuring LDAP client authentication.
Test your LDAP client configuration using the following steps.
#. Verify LDAP connectivity:
.. code-block:: text
# Ping the LDAP host to verify connectivity
ping ldap.hostname.com
# Connect to the LDAP host (this command uses the default port)
telnet ldap.hostname.com 389
#. Install the ``ldapsearch`` tool to conduct subsequent tests:
.. code-block:: text
sudo yum install openldap-clients -y
#. Verify basic access without specifying any credentials:
.. code-block:: text
ldapsearch -LLL -x -H ldap://ldap.hostname.com -s "base" -b "" supportedSASLMechanisms
This command should return either a success response or an authentication
error. Any other errors indicate that LDAP not set up correctly.
A success response looks like the following:
.. code-block:: text
ldapsearch -LLL -x -H ldap://localhost -s "base" -b "" supportedSASLMechanisms
dn:
supportedSASLMechanisms: GS2-IAKERB
supportedSASLMechanisms: GS2-KRB5
supportedSASLMechanisms: SCRAM-SHA-1
supportedSASLMechanisms: SCRAM-SHA-256
supportedSASLMechanisms: GSS-SPNEGO
supportedSASLMechanisms: GSSAPI
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: OTP
supportedSASLMechanisms: NTLM
supportedSASLMechanisms: CRAM-MD5
An authentication error looks like the following:
.. code-block:: text
ldapsearch -LLL -x -W -H ldap://localhost -s "base" -b "" supportedSASLMechanisms
Enter LDAP Password:
ldap_bind: Invalid credentials (49)
In cases where you are unable to communicate with an LDAP server, and/or the
LDAP server is not set up correctly to accept LDAP requests, the error looks
like the following:
.. code-block:: text
ldapsearch -LLL -x -H ldap://localhost:8090 -s "base" -b "" supportedSASLMechanisms
ldap_sasl_bind(SIMPLE): Can't contact LDAP server (-1)
#. Verify basic credential-based access using the same user specified in
``ldap.java.naming.security.principal`` in ``server.properties``:
.. code-block:: text
ldapsearch -LLL -x -H ldap://ldap.hostname.com -s "base" -b "" -D CN=kafka_user,CN=Users,DC=hostname,DC=com -w 'pa55word' supportedSASLMechanisms
If the value of ``ldap.java.naming.security.principal`` points to a Kerberos
principal, be sure to specify the corresponding user from LDAP.
If the preceding verification tests work, then :ref:`MDS ` can
authenticate against LDAP.
When configuring |ak| to communicate over LDAPS, verify TLS connectivity to the
LDAP server as follows:
.. code-block:: text
# To verify the LDAP configuration
ldapsearch -LLL -x -H ldaps://ldap.hostname.com -s "base" -b "" supportedSASLMechanisms
# If using self-signed certificates from the LDAP server
LDAPTLS_CACERT=/path/to/CA.cert ldapsearch -LLL -x -H ldaps://ldap.hostname.com -s "base" -b "" supportedSASLMechanisms
When configuring |ak| to authenticate to LDAP using Kerberos, verify
authentication to the LDAP server as follows:
.. code-block:: text
# To verify the Kerberos configuration
kinit -k -t ./filename.keytab kafka_broker/kafka1.hostname.com@EXAMPLE.COM
ldapsearch -LLL -Y GSSAPI -H ldap://ldap.hostname.com -s "base" -b "" supportedSASLMechanisms