LDAP login doesnt work

Versions (relevant - OpenSearch/Dashboard/Server OS/Browser):
opensearch 2.18.0
opensearch-dashboards 2.18.0
Server: Debian 12 , packages installed by apt

Describe the issue:
Followed the documentation, but LDAP is not enabled as authentication source.
On page " Authentication and authorization" the “ldap” domain is disabled on htttp and transport as well “http type” is “basic” and “http challenge” is “false”, “backend type” is “ldap”
On authorization , both “roles_from_another_ldap” and “roles_from_myldap” is completely disabled, both backend type is “ldap”.

The configuration show no options for LDAP, the login screen show no option for LDAP login.

There is a logstash server that collects and send the logs to the opensearch. Nobody wants to query and add logs via curl or other CLI tools. ONLY LOGSTASH send logs in.
The users are in AD, all member of a specific group.
The goal is the users member of the specified group can log in to OPENSEARCH-DASHBOARD with the AD login, NOT to Opensearch API-s or other stuff.
That is not working, no feedback on the dashboard interface.
Logging in with AD user gives standard " Invalid username or password. Please try again."

Configuration:
/etc/opensearch/opensearch-security/config.yml




_meta:
  type: "config"
  config_version: 2

config:
  dynamic:
   ...
    http:
      anonymous_auth_enabled: false
      xff:
        enabled: false
        internalProxies: '192\.168\.0\.10|192\.168\.0\.11' # regex pattern
    authc:
    ...
      ldap:
        description: "Authenticate via LDAP or Active Directory"
        http_enabled: true
        transport_enabled: true
        order: 5
        http_authenticator:
          type: basic
          challenge: true
        authentication_backend:
          # LDAP authentication backend (authenticate users against a LDAP or Active Directory)
          type: ldap
          config:
            # enable ldaps
            enable_ssl: true
            # enable start tls, enable_ssl should be false
            enable_start_tls: false
            # send client certificate
            enable_ssl_client_auth: false
            # verify ldap hostname
            verify_hostnames: true
            hosts:
            - ad1:636
            - ad2:636
            bind_dn: _opensearch_user
            password: "password_removed"
            userbase: "DC=company,DC=local"
            # Filter to search for users (currently in the whole subtree beneath userbase)
            # {0} is substituted with the username
            usersearch: '(sAMAccountName={0})'
            # Use this attribute from the user as username (if not set then DN is used)
            username_attribute: 'sAMAccountName'
    authz:
      roles_from_myldap:
        description: "Authorize via LDAP or Active Directory"
        http_enabled: true
        transport_enabled: true
        authorization_backend:
          # LDAP authorization backend (gather roles from a LDAP or Active Directory, you have to configure the above LDAP authentication backend settings too)
          type: ldap
          config:
            # enable ldaps
            enable_ssl: true
            # enable start tls, enable_ssl should be false
            enable_start_tls: false
            # send client certificate
            enable_ssl_client_auth: false
            # verify ldap hostname
            verify_hostnames: false
            hosts:
            - ad1:636
            - ad2:636
            bind_dn: _opensearch_user
            password: "password_removed"
            rolebase: "CN=opensearch_loginz,OU=groups,DC=company,DC=local"
            # Filter to search for roles (currently in the whole subtree beneath rolebase)
            # {0} is substituted with the DN of the user
            # {1} is substituted with the username
            # {2} is substituted with an attribute value from user's directory entry, of the authenticated user. Use userroleattribute to specify the name of the attribute
            rolesearch: '(member={0})'
            # Specify the name of the attribute which value should be substituted with {2} above
            userroleattribute: null
            # Roles as an attribute of the user entry
            # userrolename: disabled
            userrolename: memberOf
            # The attribute in a role entry containing the name of that role, Default is "name".
            # Can also be "dn" to use the full DN as rolename.
            rolename: cn
            # Resolve nested roles transitive (roles which are members of other roles and so on ...)
            resolve_nested_roles: true
            userbase: 'DC=company,DC=local'
            # Filter to search for users (currently in the whole subtree beneath userbase)
            # {0} is substituted with the username
            usersearch: '(uid={0})'
            # Skip users matching a user name, a wildcard or a regex pattern
            #skip_users:
            #  - 'cn=Michael Jackson,ou*people,o=TEST'
            #  - '/\S*/'

/etc/opensearch-dashboard/

opensearch.username: kibanaserver
opensearch.password: kibanaserver
opensearch.requestHeadersWhitelist: [authorization, securitytenant]

opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: [Private, Global]
opensearch_security.readonly_mode.roles: [kibana_read_only]
# Use this setting if you are running opensearch-dashboards without https
opensearch_security.cookie.secure: false
opensearch_security.auth.type: basicauth
opensearch_security.auth.multiple_auth_enabled: true

Relevant Logs or Screenshots:
[WARN ][o.o.s.a.BackendRegistry ] [node-1] Authentication finally failed for aduser1 from 10.10.10.10:12345

Thank you for your help!

Same error for me and i have no idea how to resolve that.

Looking at my config which is working for auth against AD the difference I see is for authc and authz with ldap I have:

        http_enabled: true
        transport_enabled: true

Set to false for both params.
Additionally - I do have:

        description: "Authenticate via HTTP Basic against internal users database"
        http_enabled: true
        transport_enabled: true
        order: 4
        http_authenticator:
          type: basic
          challenge: true
        authentication_backend:
          type: intern

Set under authc to enable service accounts for things like logstash kibana etc to not hit AD and use the internal opensearch auth instead.

Oddly for dashboards I do not have

opensearch_security.auth.type: basicauth
opensearch_security.auth.multiple_auth_enabled: true

Set in my config.

Also, there wont be an option to auth via LDAP or basic from the UI perspective. It will try the autchc configds based on the order parameter and after the first fails it proceeds to the next iirc.

Hi all,

@repasp it looks like you’re trying to use SSL but have yet to list any cert in your authc or authz for use. This will be needed for company.local.

Could you confirm if company.local is local testing? or it is part of an orgs internal domain.

Lets first test to see if you can get connectivity to AD, and if the AD user is working. Could you test the following two, and send back the output please:

Test if ldap user is working:

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

Also please run ldapsearch and share the output.

Thanks.

Hey @abarocco,

I see you solved your issue with Pablo, that’s good to hear. (LDAP Not Working - #8 by abarocco)

@repasp are you still having an issue or have you managed to get your setup working?

@Leeroy
Sorry to say, but its still not working.
I have checked the LDAP users /authinfo?pretty , but it still displays “Unauthorized”.
The strangest is it seems that the opensearch doesn’t load the LDAP config:

Its disabled and shows a strange config when “View expression” is clicked:

I couldn’t found where the localhost:8389 is configured.

I have copied the LDAP cert to /usr/share/local/ca-certificates and update-ca-certificates.
Added to authz and authc:
pemtrustedcas_filepath: /etc/opensearch/certs/CA.pem

Added the LDAP connection certificate to CA.pem and restarted.
But still not working. That do I miss?

@repasp According to your last screenshot, you’re still running the cluster with a demo security configuration.

When you create the cluster for the first time, the security plugin will create the .opendistro_security index with its configuration. This is possible by setting the following option in the opensearch.yml file.

plugins.security.allow_default_init_securityindex: true

By default, the security plugin will use the files located in /usr/share/opnsearch/config/opensearch-security folder.

This process only happens when the .opendistro_security index doesn’t exist.
When the index exists and you make changes in the security plugin config files, the restart of the OpenSearch service won’t update the configuration in the .opendistro_security index.

The only way to update the security plugin configuration is through securityadmin.sh script.

Hello,
Thank you for your help!

I have set the config.yml and tried to run the securityadmin.sh as:

root@spvsopensearch01:/etc/opensearch# /usr/share/opensearch/plugins/opensearch-security/tools/securityadmin.sh \
-cert kirk.pem \
-key kirk-key.pem \
-f opensearch-security/config.yml \
--host=opensearch.office.local \
-cacert ssl/chain.pem
Security Admin v7
Will connect to opensearch.office.local:9200 ... done
ERR: An unexpected SSLHandshakeException occured: Received fatal alert: certificate_unknown
See https://opensearch.org/docs/latest/clients/java-rest-high-level/ for troubleshooting.
Trace:
javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
See https://opensearch.org/docs/latest/clients/java-rest-high-level/ for troubleshooting.
        at org.opensearch.client.RestClient.extractAndWrapCause(RestClient.java:1241)
        at org.opensearch.client.RestClient.performRequest(RestClient.java:358)
        at org.opensearch.client.RestClient.performRequest(RestClient.java:346)
        at org.opensearch.security.tools.SecurityAdmin.execute(SecurityAdmin.java:575)
        at org.opensearch.security.tools.SecurityAdmin.main(SecurityAdmin.java:165)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
        at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130)
        at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:370)
        at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:287)
        at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:209)
        at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
        at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:736)
        at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:691)
        at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:506)
        at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:482)
        at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:679)
        at org.apache.http.nio.reactor.ssl.SSLIOSession.doUnwrap(SSLIOSession.java:279)
        at org.apache.http.nio.reactor.ssl.SSLIOSession.decryptData(SSLIOSession.java:505)
        at org.apache.http.nio.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:548)
        at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:120)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
        at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591)
        at java.base/java.lang.Thread.run(Thread.java:1583)


root@spvsopensearch01:/etc/opensearch#


Opensearch.yml has the admin_dn (default value):

plugins.security.authcz.admin_dn: ['CN=kirk,OU=client,O=client,L=test,C=de']

It match the cert’s Subject (kirk.pem) and the kirk.pem & kirk-key.pem has the same modulus

root@spvsopensearch01:/etc/opensearch# certtool -i  < kirk.pem | grep -i Subject:
        Subject: CN=kirk,OU=client,O=client,L=test,C=de
root@spvsopensearch01:/etc/opensearch#

The SSL config is the following in opensearch.yml:

root@spvsopensearch01:/etc/opensearch# grep ssl opensearch.yml
plugins.security.ssl.transport.pemcert_filepath: ssl/opensearch.office.local.pem
plugins.security.ssl.transport.pemkey_filepath: ssl/opensearch.key
plugins.security.ssl.transport.pemtrustedcas_filepath: ssl/chain.pem
plugins.security.ssl.transport.enforce_hostname_verification: false
plugins.security.ssl.http.enabled: true
plugins.security.ssl.http.pemcert_filepath: ssl/opensearch.office.local.pem
plugins.security.ssl.http.pemkey_filepath: ssl/opensearch.key
plugins.security.ssl.http.pemtrustedcas_filepath: ssl/chain.pem
root@spvsopensearch01:/etc/opensearch#

The chain.pem contains the local CA’s CA and intermediate cert, the opensearch.office.local.pem is signed by this intermediate cert, so the chain of trust is ok:

root@spvsopensearch01:/etc/opensearch# openssl verify -CAfile ssl/chain.pem ssl/opensearch.office.local.pem
ssl/opensearch.office.local.pem: OK
root@spvsopensearch01:/etc/opensearch#

Tried with the root-ca.pem as the cacert, but it doesn’t work:
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

What certificate is missing? Where should it be imported?

Thank you!

@repasp I understand that:

  1. Your cluster is running with custom certificates.
  2. kirk.pem, kirk-key.pem and root-ca.pem are demo certificates.
  3. chain.pem contains only RootCA for the custom node http/transport certificate

If that’s the case, kirk.pem and kirk-key.pem won’t work and observed errors are expected.
Initially, you’ve executed securityadmin.sh with demo certificates and your custom RootCA(chain.pem). It failed because demo certificates were not signed by your custom RootCA.

When you replaced the custom RootCA (chain.pem) with demo RootCA (root-ca.pem), the trust between kirk.pem, kirk-pem.key and RootCA was restored but OpenSearch node failed validate the certification path.

This is also expected.

When you run securityadmin.sh with certificate defined in the admin_dn the RootCA must match RootCAs defined in plugins.security.ssl.http.pemcert_filepath.

You have 2 solutions here.

  1. Concatenate root-ca.pem with chain.pem on each OpenSearch node and restart and each node.
  2. Create client certificate and sign with RootCA from chain.pem. Use the same Subject as the demo certificate. This way you’ll avoid node restart.

Hello,

I have generated a key and a certificate with the same subject as configured in plugins.security.authcz.admin_dn, the cert is signed by the same intermediate cert as the http.pemcert_filepath configs value:

opensearch01:/etc/opensearch# certtool -i < ./kirk/kirk-old.cer | grep -i Issuer: | md5sum && certtool -i < ./ssl/opensearch.pem | grep Issuer: | md5sum
c572d74a78c730be186a062fb475f5dd -
c572d74a78c730be186a062fb475f5dd -
sopensearch01:/etc/opensearch#

But running the securityadmin.sh still

javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown

What else can gone wrong? It seems that the match of admin_dn and signed by same CA is not enough.

Thank you!

No one has any advice? What shall I do?

Securityadmin still show this:

javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown

How can I make opensearch trust this cert when its:

  • CN match the admin_dn
  • signed by the same intermediate CA as the port 9200’s tls cert

The documentation is pretty unclean and misleading.

@repasp What is your certificate chain?

Is it RootCA → Intermediate → client cert? Do you have more than one intermediate certificate?

My certificate chain is:

Root CA (Windows Domain PKI) => Intermediate CA

The http/transport TLS cert is signed by this Intermediate.

The cert used in the securityadmin.sh command is also signed by this intermediate CA.

Openssl verify show OK for both http/transport cert and cert used by securityadmin.sh script.

@repasp Where is your CA and Intermediate located in your configuration? Are they both concatenated in the ssl/chain.pem?

@pablo the chain is located in ssl/chain.pem, but turned out, the problem was on another level.

I have generated a new CA in a separate folder, singed my certs with this new, independent CA and configured in opensearch.yml. After restart, it seems to work, I could run the securityadmin.sh with the new cert and CA. Now the LDAP server auth is present in the authentication sequence on the web interface.

I’m going to investigate the Windows AD PKI signing policy, I think the signing process makes something on a different way than I have expected (maybe TLS extension change by PKI policy?)

Thank you for your help, I have learned a lot!

1 Like