ansible-plugin-lookup_ldap
ansible-plugin-lookup_ldap copied to clipboard
Using delegate_to: breaks plugin?
I have a rather odd issue. I have everything working great to query my LDAP server, retrieve a list of users and do what I need with it. However, if I add delegate_to: locahost
to the task it causes the plugin to error with SSLHandshake() failed: misc. bad certificate (-9825)'
.
So this works:
---
- hosts: fakehost
connection: local
gather_facts: no
vars:
my_users: []
ldap_base: dc=domain,dc=com
people_base: "ou=People,{{ ldap_base }}"
ldap_lookup_config:
url: 'ldaps://ldapserver.domain.com'
base: "{{ people_base }}"
binddn: "uid=myuser,ou=People,{{ ldap_base }}"
bindpw: "mypassword"
ldap_users:
base: "{{ people_base }}"
value: uid
filter: '(!(loginShell=/bin/false))'
tasks:
- name: Fetch LDAP users
set_fact:
my_users: "{{ my_users }} + [ '{{ item }}' ]"
with_ldap:
- context: ldap_users
- myldapgroup
- name: Show users
debug: msg="User {{ my_users }}"
roles:
- quinot.lookup_ldap
but this fails with the SSL cert error:
---
- hosts: fakehost
gather_facts: no
vars:
my_users: []
ldap_base: dc=domain,dc=com
people_base: "ou=People,{{ ldap_base }}"
ldap_lookup_config:
url: 'ldaps://ldapserver.domain.com'
base: "{{ people_base }}"
binddn: "uid=myuser,ou=People,{{ ldap_base }}"
bindpw: "mypassword"
ldap_users:
base: "{{ people_base }}"
value: uid
filter: '(!(loginShell=/bin/false))'
tasks:
- name: Fetch LDAP users
delegate_to: localhost
set_fact:
my_users: "{{ my_users }} + [ '{{ item }}' ]"
with_ldap:
- context: ldap_users
- myldapgroup
- name: Show users
debug: msg="User {{ my_users }}"
roles:
- quinot.lookup_ldap
I wondered if this might be a more general bug in Ansible with delegate_to
but I don't believe so. If I replace with_ldap
with a generic with_items
then it works fine with delegate_to
.
I inserted some debug logging and it's at the lo.simple_bind_s()
stage that it fails when using delegate_to: localhost
.
Also, while yes, it does work with connection: local
instead, that does not solve for my use case. I need to be able to delegate facts to localhost.
Please let me know if I need to provide more details. This is with Ansible 2.7.5, Python 2.7.15 on MacOS High Sierra 10.13.5.
Lookup plugins run on the control machine, ie they already run on local host https://docs.ansible.com/ansible/latest/plugins/lookup.html
Like all templating, these plugins are evaluated on the Ansible control machine, not on the target/remote.
The plugin runs on the control machine, but the resulting facts are tied to the target host. So when I run this across multiple targets it has to repeat the identical lookup request for every host. I just want to query once and have that data accessible for every host in the run.
The point I'm trying to make is you are dealing with limitations of Ansible, not this plugin. Lookups don't support delegation https://github.com/ansible/ansible/issues/14940.
However you can run lookups in the vars section rather than using set_fact I.E. something like this
---
- hosts: fakehost
gather_facts: no
vars:
my_users: []
ldap_base: dc=domain,dc=com
people_base: "ou=People,{{ ldap_base }}"
ldap_lookup_config:
url: 'ldaps://ldapserver.domain.com'
base: "{{ people_base }}"
binddn: "uid=myuser,ou=People,{{ ldap_base }}"
bindpw: "mypassword"
ldap_users:
base: "{{ people_base }}"
value: uid
filter: '(!(loginShell=/bin/false))'
user: "{{ lookup('ldap', 'myldapgroup', context='ldap_users') }}"
the with_
Honestly I don't think this plugin is going to get fixed, there are very few commits and none in over a year. Multiple people have tried to get pull requests to add Python 3 support but the dev won't pull them, and he still uses a weird methodology using the with_
Thanks for the clarification. I'll keep an eye on the new plugin if/when it gets merged, though I think it still doesn't solve the root issue of avoiding a repeat lookup for each target.
My guess is I'll need to do this with local facts and have a separate command to populate the fact file at the start of the run.
It is an issue with Ansible that lookups aren't cached
Just a few comments... I'm still alive :-) The reason why the Python3 support was never merged is because it was done without regard for compatibility with Python2. At that time this was an issue for me. I suspect I could revisit this.
I don't quite get the comment about with_* vs calling lookup(). All lookup plugins support both usages, and as far as I can tell from the Ansible documentation, with_* is not going away.
From https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html:
* We have not deprecated the use of with_<lookup> - that syntax will still be valid for the foreseeable future.
That said, thanks for the pointer to ansible/ansible#52899. Several aspects in the approach there are interesting.
@quinot I made the statement that nothing is happening because PR #26 has been available since December of last year with no comments from you haven't made any updates since April of last year despite Python 3 being the way forward and the default soon in Ansible even and Py2 being EOL in 2 months. Based on that it looked like you had abandoned this project.
I mispoke a bit, you are right with_ is not currently on the deprecated list, but it is no longer best practice and is recommended to move away from it if possible. On the same page they also say
- We added loop in Ansible 2.5. It is not yet a full replacement for with_
, but we recommend it for most use cases. With the release of Ansible 2.5, the recommended way to perform loops is the use the new loop keyword instead of with_X style loops.
Mostly I was just trying to point out to @cfiske his issue is with Ansible limitations not your plugin and a possible way to work around it a bit.