community.general icon indicating copy to clipboard operation
community.general copied to clipboard

ldap_search can not search whole domain

Open JochenKorge opened this issue 2 years ago • 7 comments

Summary

When I specify only the Domain-Component dn: 'DC=example,DC=com' the module bugs out. The Error message differs on scope: 'children/subordinate'

Issue Type

Bug Report

Component Name

ldap_search

Ansible Version

ansible [core 2.12.1]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/jochen/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/dist-packages/ansible
  ansible collection location = /usr/share/ansible/collections:/home/jochen/.ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110]
  jinja version = 3.0.3
  libyaml = True

Community.general Version

# /usr/local/lib/python3.9/dist-packages/ansible_collections
Collection        Version
----------------- -------
community.general 4.3.0  

Configuration

COLLECTIONS_PATHS(/etc/ansible/ansible.cfg) = ['/usr/share/ansible/collections', '/home/jochen/.ansible/collections']
DEFAULT_TIMEOUT(/etc/ansible/ansible.cfg) = 60

OS / Environment

Target is Debian11 Ldap-Server: Synology DSM 6.2.4 (Synology Directory Server 4.4.5, based on Samba 4.4.16)

Steps to Reproduce

- hosts: 'ldap_gatherer'
  tasks:
  - name: 'gather ldap-user'
    community.general.ldap_search:
      bind_dn: '{{ ldap_query_user.name }}'
      bind_pw: '{{ ldap_query_user.password }}'
      dn: 'DC=example,DC=com'
      server_uri: '{{ ldap_url }}'
      scope: 'children'
      filter: '{{ vpn_user_filter }}'
      attrs: 'sAMAccountName'
    register: 'vpn_user'

  - name: 'print'
    ansible.builtin.debug:
      var: vpn_user

Expected Results

print all users where "filter" matches

Actual Results



The full traceback is:
  File "/tmp/ansible_community.general.ldap_search_payload_n5e6yudq/ansible_community.general.ldap_search_payload.zip/ansible_collections/community/general/plugins/modules/ldap_search.py", line 110, in main
  File "/tmp/ansible_community.general.ldap_search_payload_n5e6yudq/ansible_community.general.ldap_search_payload.zip/ansible_collections/community/general/plugins/modules/ldap_search.py", line 158, in main
  File "/tmp/ansible_community.general.ldap_search_payload_n5e6yudq/ansible_community.general.ldap_search_payload.zip/ansible_collections/community/general/plugins/modules/ldap_search.py", line 163, in perform_search
  File "/usr/lib/python3/dist-packages/ldap/ldapobject.py", line 854, in search_s
    return self.search_ext_s(base,scope,filterstr,attrlist,attrsonly,None,None,timeout=self.timeout)
  File "/usr/lib/python3/dist-packages/ldap/ldapobject.py", line 848, in search_ext_s
    return self.result(msgid,all=1,timeout=timeout)[1]
  File "/usr/lib/python3/dist-packages/ldap/ldapobject.py", line 740, in result
    resp_type, resp_data, resp_msgid = self.result2(msgid,all,timeout)
  File "/usr/lib/python3/dist-packages/ldap/ldapobject.py", line 744, in result2
    resp_type, resp_data, resp_msgid, resp_ctrls = self.result3(msgid,all,timeout)
  File "/usr/lib/python3/dist-packages/ldap/ldapobject.py", line 748, in result3
    resp_type, resp_data, resp_msgid, decoded_resp_ctrls, retoid, retval = self.result4(
  File "/usr/lib/python3/dist-packages/ldap/ldapobject.py", line 758, in result4
    ldap_result = self._ldap_call(self._l.result4,msgid,all,timeout,add_ctrls,add_intermediates,add_extop)
  File "/usr/lib/python3/dist-packages/ldap/ldapobject.py", line 331, in _ldap_call
    reraise(exc_type, exc_value, exc_traceback)
  File "/usr/lib/python3/dist-packages/ldap/compat.py", line 44, in reraise
    raise exc_value
  File "/usr/lib/python3/dist-packages/ldap/ldapobject.py", line 315, in _ldap_call
    result = func(*args,**kwargs)
fatal: [srvito01]: FAILED! => {
    "changed": false,
    "details": "{'desc': 'Operations error', 'info': '00002020: Operation unavailable without authentication'}",
    "invocation": {
        "module_args": {
            "attrs": [
                "sAMAccountName"
            ],
            "bind_dn": "CN=ldap.query,CN=Users,DC=example,DC=com",
            "bind_pw": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "dn": "DC=example,DC=com",
            "filter": "(memberof:1.2.840.113556.1.4.1941:=CN=vpn_access,CN=Users,DC=example,DC=com)",
            "referrals_chasing": "anonymous",
            "sasl_class": "external",
            "schema": false,
            "scope": "children",
            "server_uri": "ldap://domaincontroller.example.com",
            "start_tls": false,
            "validate_certs": true
        }
    },
    "msg": "Attribute action failed."
}

When Changing scope to subordinate the error changes to:

"details": "{'desc': 'Protocol error', 'info': '00002021: Protocol error. Invalid scope'}",

Code of Conduct

  • [X] I agree to follow the Ansible Code of Conduct

JochenKorge avatar Jun 24 '22 14:06 JochenKorge

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot avatar Jun 24 '22 14:06 ansibullbot

cc @eryx12o45 @jtyr click here for bot help

ansibullbot avatar Jun 24 '22 14:06 ansibullbot

After some more tests, I realized that "scope: subordinate" does not work at all.

JochenKorge avatar Jun 24 '22 14:06 JochenKorge

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot avatar Nov 07 '22 16:11 ansibullbot

@JochenKorge were you able to get the results through this module if so how?

saikrthk1322 avatar Jun 22 '23 09:06 saikrthk1322

This looks like something on the LDAP server side. The module is quite simple and straightforward. Those responses come from the server. The module is only passing back the answer it receives from the LDAP server.

russoz avatar Jul 07 '23 08:07 russoz

I disagree with russoz. Something is definitely wrong with the ldap_search module when using the scope 'subordinate' on the entire domain. While it is true that the response is being generates by the LDAP server, the testing indicates that the request to the LDAP server is the problem, that is the cause of the errors.

$ ansible-galaxy collection list | grep community.general
community.general      8.4.0

Common variables:

ldap_bind_user: "CN=bind_user,OU=ServiceAccounts,OU=<REDACTED>,DC=pro,DC=<REDACTED>,DC=com"
ldap_bind_password: <REDACTED>
ldap_server_url: ldap://ldap.pro.<redacted>.com
ldap_base_dn: "OU=ServiceAccounts,OU=<REDACTED>,DC=pro,DC=<REDACTED>,DC=com"
ldap_filter: cn=svc_account1

Here are 2 scenerios:

    - name: TEST module
      community.general.ldap_search:
        server_uri: "{{ ldap_server_url }}"     # -H
        bind_dn: "{{ ldap_bind_user }}"         # -D
        bind_pw: "{{ ldap_bind_password }}"     # -w
        dn: "{{ ldap_base_dn }}"                # -b
        scope: onelevel                         # -s
        filter: "{{ ldap_filter }}"
        validate_certs: false
      register: module_out
      ignore_errors: true

    - debug:
        var: module_out

    - name: TEST command line
      ansible.builtin.command: ldapsearch  -s "one" -b "{{ ldap_base_dn }}" -H "{{ ldap_server_url }}" -D "{{ ldap_bind_user }}" -w "{{ ldap_bind_password }}" "({{ ldap_filter }})"
      changed_when: false
      register: command_out

    - debug:
        var: command_out

In this first scenerio both the module and the command line provide the expected results.

   - name: TEST module
      community.general.ldap_search:
        server_uri: "{{ ldap_server_url }}"     # -H
        bind_dn: "{{ ldap_bind_user }}"         # -D
        bind_pw: "{{ ldap_bind_password }}"     # -w
        dn: "{{ ldap_base_dn }}"                # -b
        scope: subordinate                      # -s
        filter: "{{ ldap_filter }}"
        validate_certs: false
        #attrs: memberOf
      register: module_out
      ignore_errors: true

    - debug:
        var: module_out

    - name: TEST command line
      ansible.builtin.command: ldapsearch  -s "sub" -b "{{ ldap_base_dn }}" -H "{{ ldap_server_url }}" -D "{{ ldap_bind_user }}" -w "{{ ldap_bind_password }}" "({{ ldap_filter }})"
      changed_when: false
      register: command_out

    - debug:
        var: command_out

In this second scenerio, the command line provides the expected results, but the module_out is

"module_out": {
        "changed": false,
        "details": "{'msgtype': 101, 'msgid': 4, 'result': 80, 'desc': 'Other (e.g., implementation specific) error', 'ctrls': [], 'info': '00000057: LdapErr: DSID-0C090DA2, comment: Error processing control, data 0, v4563'}",
        "failed": true,
        "msg": "Attribute action failed."
    }

alice-rc avatar May 13 '24 21:05 alice-rc