FreeIPA Authentication Failed

Hello, I’m having issues allowing LDAP authentication to FreeIPA so that I can utilize FreeIPA users in the elkusers group to login to Kibana. I’ve been following the Active Directory and LDAP - Open Distro for Elasticsearch Documentation doc for setting this up but this document seems to be mostly geared towards Windows Active Directory and only partially works for FreeIPA. I am pretty sure I have everything configured correctly to only authenticate the FreeIPA users but it doesn’t even seem like Elasticsearch nor Kibana is even querying FreeIPA for user credentials. Right now for testing I am doing this without the TLS configuration to FreeIPA just to keep things simple. The “bind” user for connecting to FreeIPA for queries is elkuser and the group in FreeIPA that should be allowed to login to Kibana is the elkusers group in FreeIPA. I’m not sure what I am doing wrong or what else I should try at this point? My question is what could I be missing or mis-configured for Elasticsearch and Kibana to not be querying FreeIPA for authentication? Thanks for any assistance.

Note: I can successfully query FreeIPA from the ELK host with ldapsearch so I know that it can talk to FreeIPA.

ldap:
    description: "FreeIPA"
    http_enabled: true
    transport_enabled: true
    order: 1
    http_authenticator:
      type: basic
      challenge: false
    authentication_backend:
      # LDAP authentication backend (authenticate users against a LDAP or Active Directory)
      type: ldap
      config:
        # enable ldaps
        enable_ssl: false
        # 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:
        - 'idm.test.domain:389'
        bind_dn: 'uid=elkuser,cn=users,cn=accounts,dc=test,dc=domain'
        password: 'mypassword'
        userbase: 'cn=elkusers,cn=groups,cn=accounts,dc=test,dc=domain'
        # Filter to search for users (currently in the whole subtree beneath userbase)
        # {0} is substituted with the username
        usersearch: '(uid={0})'
        # Use this attribute from the user as username (if not set then DN is used)
        username_attribute: uid

Hi @John I haven’t tried FreeIPA as off yet, so can’t confirm if it works as expected, but couple of questions to ask.

The above is only for user authentication (authc), therefore no groups will be extracted. Have you configured the authz section? If so could you provide the config.yml file.

Also, can you provide the ldapsearch query you are running and the result you are getting back? (Redact any sensitive info of course)

Are there any logs in elasticsearch when you are trying to connect? If so can you provide here? Authc and authz work separately and query the ldap twice, once for user and second time for groups. Logs should be displaying this, might need to increase the logging to see full details.

@Anthony Thank you for the response. Below is the information that I have for your questions. I’ll be posting the information in the same order in which you asked the questions for readability.

Here, I just included both the authc and authz configuration in full to keep consistency.

ldap:
    description: "FreeIPA"
    http_enabled: true
    transport_enabled: true
    order: 1
    http_authenticator:
      type: basic
      challenge: false
    authentication_backend:
      # LDAP authentication backend (authenticate users against a LDAP or Active Directory)
      type: ldap
      config:
        # enable ldaps
        enable_ssl: false
        # 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:
        - 'idm.test.domain:389'
        bind_dn: 'uid=elkuser,cn=users,cn=accounts,dc=test,dc=domain'
        password: 'mypassword'
        userbase: 'cn=elkusers,cn=groups,cn=accounts,dc=test,dc=domain'
        # Filter to search for users (currently in the whole subtree beneath userbase)
        # {0} is substituted with the username
        usersearch: '(uid={0})'
        # Use this attribute from the user as username (if not set then DN is used)
        username_attribute: uid
authz:
  roles_from_myldap:
    description: "Authorize via FreeIPA"
    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: false
        # 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:
        - 'idm.test.domain:389'
        bind_dn: 'uid=elkuser,cn=users,cn=accounts,dc=test,dc=domain'
        password: 'mypassword'
        rolebase: 'cn=elkusers,cn=groups,cn=accounts,dc=test,dc=domain'
        # 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: '(memberUid={1})'
        # 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: 'memberOf'
        #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: false
        userbase: 'cn=elkusers,cn=groups,cn=accounts,dc=test,dc=domain'
        # 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*/'
          - admin
          - kibanaserver
          - kibanaro
          - logstash
          - readall
          - snapshotrestore
  roles_from_another_ldap:
    description: "Authorize via another Active Directory"
    http_enabled: false
    transport_enabled: false
    authorization_backend:
      type: ldap
      #config goes here ...
#    auth_failure_listeners:
#      ip_rate_limiting:
#        type: ip
#        allowed_tries: 10
#        time_window_seconds: 3600
#        block_expiry_seconds: 600
#        max_blocked_clients: 100000
#        max_tracked_clients: 100000
#      internal_authentication_backend_limiting:
#        type: username
#        authentication_backend: intern
#        allowed_tries: 10
#        time_window_seconds: 3600
#        block_expiry_seconds: 600
#        max_blocked_clients: 100000
#        max_tracked_clients: 100000

Here is the ldapsearch query and the output. If you have something else for me to run in mind, feel free to let me know and I can run another query and post the results.

ldapsearch -x -b 'cn=elkusers,cn=groups,cn=accounts,dc=test,dc=domain' -H 'ldap://idm.test.domain:389'

# extended LDIF
#
# LDAPv3
# base <cn=elkusers,cn=groups,cn=accounts,dc=test,dc=domain> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# elkusers, groups, accounts, test.domain
dn: cn=elkusers,cn=groups,cn=accounts,dc=test,dc=domain
cn: elkusers
objectClass: top
objectClass: groupofnames
objectClass: nestedgroup
objectClass: ipausergroup
objectClass: ipaobject
objectClass: posixgroup
ipaUniqueID: 8cf5e682-b4b8-11eb-889d-b63df467a214
gidNumber: 1351800015

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

This is the only log entry I get for an authentication attempt. Perhaps I need to increase logging to see more details as you recommended? This was from the terminal but in Kibana I have a log entry as well for the same attempt. Not sure if you wanted the json output or just the log entry from the log file on the host? I also included my command for the authentication attempt as well.

curl -XGET https://192.168.2.132:9200 -u testuser@test.domain --insecure

{ "type": "server", "timestamp": "2021-05-24T10:30:07,154-04:00", "level": "WARN", "component": "c.a.o.s.a.BackendRegistry", "cluster.name": "graylog", "node.name": "graylog.test.domain", "message": "Authentication finally failed for testuser@test.domain from 192.168.2.132:55504", "cluster.uuid": "pKhMVB4WQ5eG6WoEnSyVXg", "node.id": "9AG3CV3PTOqzRFhZ7hdIng"  }

Thank you and if I need to adjust anything, please let me know.

The config that works for me after basic installation of FreeIPA on centOS:

authc:
  basic_internal_auth_domain:
    description: "Authenticate via HTTP Basic against internal users database"
    http_enabled: true
    transport_enabled: true
    order: 0
    http_authenticator:
      type: basic
      challenge: false
    authentication_backend:
      type: intern
  ldap:
    description: "Authenticate via LDAP or Active Directory"
    http_enabled: true
    transport_enabled: false
    order: 5
    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: false
        hosts:
          - ipa.example.com
        bind_dn: 'uid=admin,cn=users,cn=accounts,dc=example,dc=com'
        password: <password>
        userbase: 'cn=users,cn=accounts,dc=example,dc=com'
        username_attribute: "uid"
        usersearch: '(uid={0})' 
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: false
    hosts:
      - ipa.example.com
    bind_dn: 'uid=admin,cn=users,cn=accounts,dc=example,dc=com'
    password: <password>
    rolebase: 'cn=roles,cn=accounts,dc=example,dc=com'
    rolesearch: '(member={0})'
    userroleattribute: null
    userrolename: disabled
    rolename: cn
    resolve_nested_roles: false
    userbase: 'cn=users,cn=accounts,dc=example,dc=com'
    usersearch: '(uid={0})'

This returns any roles mapped to user in FreeIPA as backend roles, which can be seen from view roles and identities tab. These can then be mapped to security roles using roles_mapping.yml file.

Hope this helps

Thank you for the information. There were many things that changed and I’m not %100 what particular thing ended up being the “fix” or maybe it was a combination of things that fixed my authentication issue. I am now able to login to Kibana with users from FreeIPA just as long as there are appropriate roles assigned to the user within FreeIPA. Below is my current working config for unencrypted LDAP authentication to FreeIPA.

     basic_internal_auth_domain:
        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

      ldap:
        description: "FreeIPA"
        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: false
            # 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:
            - idm.test.domain
            bind_dn: 'uid=elkuser,cn=users,cn=accounts,dc=test,dc=domain'
            password: 'mypassword'
            userbase: 'cn=users,cn=accounts,dc=test,dc=domain'
            # Filter to search for users (currently in the whole subtree beneath userbase)
            # {0} is substituted with the username
            usersearch: '(uid={0})'
            # Use this attribute from the user as username (if not set then DN is used)
            username_attribute: 'uid'
    authz:
      roles_from_myldap:
        description: "Authorize via FreeIPA"
        http_enabled: true
        transport_enabled: false
        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: false
            # 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:
            - idm.test.domain
            bind_dn: 'uid=elkuser,cn=users,cn=accounts,dc=test,dc=domain'
            password: 'mypassword'
            rolebase: 'cn=roles,cn=accounts,dc=test,dc=domain'
            # 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: memberOf
            #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: false
            userbase: 'cn=users,cn=accounts,dc=test,dc=domain'
            # 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*/'
              - admin
              - kibanaserver
              - kibanaro
              - logstash
              - readall
              - snapshotrestore
      roles_from_another_ldap:
        description: "Authorize via another Active Directory"
        http_enabled: false
        transport_enabled: false
        authorization_backend:
          type: ldap
          #config goes here ...
  #    auth_failure_listeners:
  #      ip_rate_limiting:
  #        type: ip
  #        allowed_tries: 10
  #        time_window_seconds: 3600
  #        block_expiry_seconds: 600
  #        max_blocked_clients: 100000
  #        max_tracked_clients: 100000
  #      internal_authentication_backend_limiting:
  #        type: username
  #        authentication_backend: intern
  #        allowed_tries: 10
  #        time_window_seconds: 3600
  #        block_expiry_seconds: 600
  #        max_blocked_clients: 100000
  #        max_tracked_clients: 100000

My next steps will be to implement either LDAPS or STARTTLS for secure communication from ELK to FreeIPA for authenticating users but that is not currently configured in the above listed config for anyone else that comes across this particular issue. Thank you @Anthony for your assistance and hopefully someone else can benefit from this setup.