Troubleshooting LDAP/AD connection

Versions (relevant - OpenSearch/Dashboard/Server OS/Browser):
OpenSearch 2.11.1

Describe the issue:
I’m trying to configure opensearch for using LDAP to authenticate against an Active Directory server, but I’m having trouble getting it to work. There’s no apparent traffic to the AD server (had one of the sysadmins check the firewall). I wrote a Python script to use the ldap3 library to authenticate, and it works (this does hit the firewall), so it’s reachable. I’m using a docker-compose setup based on the website examples. Authenticating internal users works fine.

I’ve hit a dead-end in troubleshooting. Where would I find log files for this? If I exec into the container, I see logs for the performance analyzer and garbage collection in /usr/share/opensearch/logs, and /var/log has things pertaining to package management, but I can’t find anything pertaining to auth. All I get is the ‘Authentication finally failed’ message on the terminal. Is there somewhere I can find more logs that might point me to what’s wrong?

Configuration:
Here’s my config.yml:

config:
dynamic:
http:
anonymous_auth_enabled: false
authc:
internal_auth:
order: 0
description: “HTTP basic authentication using the internal user database”
http_enabled: true
transport_enabled: true
http_authenticator:
type: basic
challenge: false
authentication_backend:
type: internal
ldap:
order: 1
description: “Authenticate using LDAP”
http_enabled: true
transport_enabled: true
http_authenticator:
type: basic
challenge: false
authentication_backend:
type: ldap
config:
enable_ssl: false
enable_start_tls: false
enable_ssl_client_auth: false
verify_hostnames: true
hosts:
- ad.server.hostname:389
bind_dn: cn=aduser,dc=xxxx,dc=xxxx,dc=xxxx
password: xxxxxxxx
userbase: OU=xxxxx,DC=xxxx,DC=xxxx,DC=xxxx
usersearch: (sAMAccountName={0})
username_attribute: sAMAccountName
authz:
ldap_roles:
description: “Authorize using LDAP”
http_enabled: true
transport_enabled: true
authorization_backend:
type: ldap
config:
enable_ssl: false
enable_start_tls: false
enable_ssl_client_auth: false
verify_hostnames: true
hosts:
- ad.server.hostname:389
bind_dn: cn=aduser,dc=xxxx,dc=xxxx,dc=xxxx
password: xxxxxxxx
userbase: OU=xxxxx,DC=xxxx,DC=xxxx,DC=xxxx
usersearch: (sAMAccountName={0})
username_attribute: sAMAccountName
skip_users:
- admin
- kibanaserver
rolebase: OU=xxxxx,DC=xxxx,DC=xxxx,DC=xxxx
rolesearch: (uniqueMember={0})
userroleattribute: null
userrolename: disabled
rolename: cn
resolve_nested_roles: false

Relevant Logs or Screenshots:
os01-1 | [2024-02-23T22:04:09,907][WARN ][o.o.s.a.BackendRegistry ] [os01] Authentication finally failed for xxxxxxxx from xxxxxxxxx

Hi @mvieths,

Could you run the below and share outputs (please mask any sensitive information):

test LDAP with ldapsearch:

env LDAPTLS_REQCERT=never ldapsearch -b "CN=<USERNAME>,OU=xxxxx,DC=xxxx,DC=xxxx,DC=xxxx" -H ldap://ad.server.hostname:389 -D "cn=aduser,dc=xxxx,dc=xxxx,dc=xxxx" -w "password"

retrieve authinfo:
curl --insecure -u <ldap_user>:<ldap_password> -XGET https://<OS_node>:9200/_plugins/_security/authinfo?pretty

Best,
mj

ldapsearch gives me:

ldap_bind: Invalid credentials (49)
additional info: 80090308: LdapErr: DSID-0C090569, comment: AcceptSecurityContext error, data 52e, v4563

curl gives me no output, with a return value of 0.

Oddly, those same creds work just fine in a Python script I put together to test it:

from ldap3 import Server, Connection, ALL, NTLM

username=“DOMAIN\aduser”
ldap_pw=“XXXXXXXX”

server = Server(‘ad.server.hostname’, get_info=ALL)
conn = Connection(server, user=username, password=ldap_pw, raise_exceptions=True)
conn.bind()
print(conn.result)
print(conn.extend.standard.who_am_i())
print(server.info)

Is your Python script parsing or doing anything with the credentials?

Best,
mj

One of the sysadmins pulled the full AD entry, which had a slightly different DN. That authenticates with ldapsearch, so that was part of the problem. The Python script was using ‘DOMAIN\user’, not a Distinguished Name.

Thanks for your help in narrowing it down.

Curl isn’t authenticating yet, though, so I think I’ve got more work to do.

In the config.yml, how do I determine what to use for:
userbase
usersearch
username_attribute
rolebase
rolesearch

I’ve seen examples using uid, sAMAccountName, and cn for usersearch/username_attribute, but I’ve tried each of those with no luck. I’m assuming these line up with LDAP attributes and DN components, but maybe I’m wrong.

Hi @mvieths,

Here is an example that works for me (with MS AD):
This is resolving AD groups as backend roles.

 ldap:
        description: "Authenticate via LDAP or Active Directory"
        http_enabled: true
        transport_enabled: false
        order: 7
        http_authenticator:
          type: basic
          challenge: true
        authentication_backend:
          type: ldap
          config:
            enable_ssl: false
            enable_start_tls: false
            enable_ssl_client_auth: false
            verify_hostnames: true
            hosts:
            - <hostname>:389
            bind_dn: <userNanem(CN)>
            password: <password>
            userbase: 'OU=<xxxxx>,DC=<xxxx>,DC=<xxxx>,DC=<xxxx>'
            usersearch: '(sAMAccountName={0})'
            username_attribute: givenName
    authz:
      roles_from_myldap:
        description: "Authorize via LDAP or Active Directory"
        http_enabled: true
        transport_enabled: false
        authorization_backend:
          type: ldap
          config:
            enable_ssl: false
            enable_start_tls: false
            enable_ssl_client_auth: false
            verify_hostnames: true
            hosts:
            - <hostname>:389
            bind_dn: <userNanem(CN)>
            password: <password>
            rolebase: 'OU=<xxxxx>,DC=<xxxx>,DC=<xxxx>,DC=<xxxx>'
            rolesearch: '(member={0})'
            userroleattribute: null
            userrolename: disabled
            rolename: cn
            resolve_nested_roles: true
            userbase: 'OU=<xxxxx>,DC=<xxxx>,DC=<xxxx>,DC=<xxxx>'
            usersearch: '(uid={0})'
            skip_users:
              - "kibanaserver"
              - "admin"

Let me know if you have any further questions.

Best,
mj