Skip to content

ldap_attrs: 'Type or value exists' is fatal when it should be OK #977

@azmeuk

Description

@azmeuk
SUMMARY

This tasks enable the OpenLDAP memberof module:

- name: Enable memberof module
  ldap_attrs:
    dn: cn=module{0},cn=config
    attributes:
      olcModuleLoad: memberof.so
    state: present

The first time it is executed is OK, but the second time it is executed produce this error:

fatal: [myserver.mydomain.tld]: FAILED! => {"changed": false, "details": "{'info': u'modify/add: olcModuleLoad: value #0 already exists', 'desc': u'Type or value exists'}", "msg": "Attribute action failed."}

Type or value exists is something I expect with the state attribute set to present, so I am not sure why this is considered fatal.

Looking at the code, it seems that _is_value_present stays False, and no ldap.ALREADY_EXISTS exception is ever catched.

if state == 'present':
modlist = ldap.add()
elif state == 'absent':
modlist = ldap.delete()
elif state == 'exact':
modlist = ldap.exact()
changed = False
if len(modlist) > 0:
changed = True
if not module.check_mode:
try:
ldap.connection.modify_s(ldap.dn, modlist)
except Exception as e:
module.fail_json(msg="Attribute action failed.", details=to_native(e))

def add(self):
modlist = []
for name, values in self.module.params['attributes'].items():
norm_values = self._normalize_values(values)
for value in norm_values:
if self._is_value_absent(name, value):
modlist.append((ldap.MOD_ADD, name, value))
return modlist

def _is_value_present(self, name, value):
""" True if the target attribute has the given value. """
try:
is_present = bool(
self.connection.compare_s(self.dn, name, value))
except ldap.NO_SUCH_ATTRIBUTE:
is_present = False
return is_present

If this is indeed a bug, I can try to provide a patch.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

ldap_attrs

ANSIBLE VERSION
ansible 2.10.1
  config file = ~/dev/test/ansible.cfg
  configured module search path = ['~/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.8/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.5 (default, Sep  5 2020, 10:50:12) [GCC 10.2.0]
CONFIGURATION

OS / ENVIRONMENT

Host: Archlinux - Target : Debian 10

STEPS TO REPRODUCE

Execute this task twice on a host that has OpenLDAP installed.

- name: Enable memberof module
  ldap_attrs:
    dn: cn=module{0},cn=config
    attributes:
      olcModuleLoad: memberof.so
    state: present
EXPECTED RESULTS

The first time the task is executed, I expect a changed state.
The second time the task is executed, I expect a ok state.

ACTUAL RESULTS

The first time the task is executed, I get a changed state.
The second time the task is executed, I get a fatal state.

task path: ~/dev/test/roles/ldap/tasks/ldap.yml:129
redirecting (type: modules) ansible.builtin.ldap_attrs to community.general.ldap_attrs
Using module file /usr/lib/python3.8/site-packages/ansible_collections/community/general/plugins/modules/ldap_attrs.py
Pipelining is enabled.
<myserver.mydomain.tld> ESTABLISH SSH CONNECTION FOR USER: user<myserver.mydomain.tld> SSH: EXEC ssh -F ssh_config -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="user"' -o ConnectTimeout=10 myserver.mydomain.tld '/bin/sh -c '"'"'sudo -H -S -n  -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-bepsbegxtxjxhqjqqznwpvhyrvozoyyd ; /usr/bin/python'"'"'"'"'"'"'"'"' && sleep 0'"'"''
Escalation succeeded
<myserver.mydomain.tld> (1, b'\n{"msg": "Attribute action failed.", "failed": true, "exception": "WARNING: The below traceback may *not* be related to the actual failure.\\n  File \\"/tmp/ansible_ldap_attrs_payload_2haQFB/ansible_ldap_attrs_payload.zip/ansible_collections/community/general/plugins/modules/ldap_attrs.py\\", line 310, in main\\n  File \\"/usr/lib/python2.7/dist-packages/ldap/ldapobject.py\\", line 629, in modify_s\\n    return self.modify_ext_s(dn,modlist,None,None)\\n  File \\"/usr/lib/python2.7/dist-packages/ldap/ldapobject.py\\", line 602, in modify_ext_s\\n    resp_type, resp_data, resp_msgid, resp_ctrls = self.result3(msgid,all=1,timeout=self.timeout)\\n  File \\"/usr/lib/python2.7/dist-packages/ldap/ldapobject.py\\", line 749, in result3\\n    resp_ctrl_classes=resp_ctrl_classes\\n  File \\"/usr/lib/python2.7/dist-packages/ldap/ldapobject.py\\", line 756, in result4\\n    ldap_result = self._ldap_call(self._l.result4,msgid,all,timeout,add_ctrls,add_intermediates,add_extop)\\n  File \\"/usr/lib/python2.7/dist-packages/ldap/ldapobject.py\\", line 329, in _ldap_call\\n    reraise(exc_type, exc_value, exc_traceback)\\n  File \\"/usr/lib/python2.7/dist-packages/ldap/ldapobject.py\\", line 313, in _ldap_call\\n    result = func(*args,**kwargs)\\n", "details": "{\'info\': u\'modify/add: olcModuleLoad: value #0 already exists\', \'desc\': u\'Type or value exists\'}", "invocation": {"module_args": {"dn": "cn=module{0},cn=config", "ordered": false, "server_uri": "ldapi:///", "start_tls": false, "bind_dn": null, "state": "present", "bind_pw": "", "attributes": {"olcModuleLoad": "memberof.so"}, "validate_certs": true}}}\n', b'')
<myserver.mydomain.tld> Failed to connect to the host via ssh:
The full traceback is:
WARNING: The below traceback may *not* be related to the actual failure.
  File "/tmp/ansible_ldap_attrs_payload_2haQFB/ansible_ldap_attrs_payload.zip/ansible_collections/community/general/plugins/modules/ldap_attrs.py", line 310, in main
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 629, in modify_s
    return self.modify_ext_s(dn,modlist,None,None)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 602, in modify_ext_s
    resp_type, resp_data, resp_msgid, resp_ctrls = self.result3(msgid,all=1,timeout=self.timeout)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 749, in result3
    resp_ctrl_classes=resp_ctrl_classes
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 756, in result4
    ldap_result = self._ldap_call(self._l.result4,msgid,all,timeout,add_ctrls,add_intermediates,add_extop)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 329, in _ldap_call
    reraise(exc_type, exc_value, exc_traceback)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 313, in _ldap_call
    result = func(*args,**kwargs)
fatal: [myserver.mydomain.tld]: FAILED! => {
    "changed": false,
    "details": "{'info': u'modify/add: olcModuleLoad: value #0 already exists', 'desc': u'Type or value exists'}",
    "invocation": {
        "module_args": {
            "attributes": {
                "olcModuleLoad": "memberof.so"
            },
            "bind_dn": null,
            "bind_pw": "",
            "dn": "cn=module{0},cn=config",
            "ordered": false,
            "server_uri": "ldapi:///",
            "start_tls": false,
            "state": "present",
            "validate_certs": true
        }
    },
    "msg": "Attribute action failed."
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions