Ansible modules for talking to LDAP servers https://github.com/unchained-capital/ansible-ldap-modules
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. # Ansible LDAP Modules
  2. For whatever reasons, Ansible doesn't include modules to manipulate an
  3. LDAP server in its
  4. [core](http://docs.ansible.com/ansible/modules_by_category.html).
  5. Peter Sagerson implemented a pair of modules and has
  6. [attempted to get them into Ansible](http://grokbase.com/t/gg/ansible-devel/148892tek3/ldap-modules),
  7. but no luck yet. He's instead hosted his code on
  8. [Bitbucket](https://bitbucket.org/psagers/ansible-ldap).
  9. This repository is a fork of his original work with some additions
  10. (and cosmetic improvements) hosted on GitHub.
  11. # Installation
  12. The `python-ldap` library is required on whatever host is executing
  13. these modules. This can be confusing if you use both
  14. `local_action`-type tasks and tasks which run on remote hosts and both
  15. need to talk do an LDAP server -- you'll need to install `python-ldap`
  16. both locally on your controller as well as remotely on the hosts you
  17. run the tasks on.
  18. In addition, you'll need to clone this repository itself to your
  19. controller and put it somewhere `ansible` can find it.
  20. ## python-ldap Installation
  21. Install it locally via the following commands:
  22. ```
  23. $ cd ansible-ldap-modules
  24. $ sudo pip -r requirements.txt
  25. ```
  26. You may need to install some system dependencies first:
  27. ```
  28. $ sudo apt-get install python-dev libsasl2-dev libldap2-dev libssl-dev
  29. ```
  30. For remote hosts, this can be automated via Ansible:
  31. ```yaml
  32. # in prepare_remote_ldap_host.yml, for example
  33. - name: Install dependencies
  34. apt: name="{{ item }}" state=present
  35. with_items:
  36. - python-pip
  37. - libsasl2-dev
  38. - libldap2-dev
  39. - libssl-dev
  40. - name: Upgrade pip
  41. command: pip install --upgrade pip
  42. - name: Install python-ldap
  43. pip: name=python-ldap state=present
  44. ```
  45. ## Modules Installation
  46. You'll need to clone this repository somewhere on your controller
  47. machine so that `ansible` can find it.
  48. ```
  49. $ git clone https://github.com/unchained-capital/ansible-ldap-modules
  50. ```
  51. Now either set the `ANSIBLE_LIBRARY` environment variable or the
  52. `library` entry within the `defaults` section of your `ansible.cfg` to
  53. include this repository's directory.
  54. # Usage
  55. Remember, if you run these tasks locally, you need `python-ldap`
  56. installed locally. If you run them on a remote machine, you need
  57. `python-ldap` installed on that remote machine.
  58. ## Shared Behavior
  59. All the modules in this repository share some behaviors. This section
  60. describes those behaviors. The next section describes each module in
  61. detail.
  62. ### Specifying an LDAP Server
  63. Here is a simple example of creating an entry (more details on this
  64. below):
  65. ```yaml
  66. - hosts: server0
  67. tasks:
  68. - name: Ensure an LDAP entry exists for ou=People
  69. ldap_entry:
  70. dn: "ou=People,dc=example,dc=com"
  71. ou: People
  72. objectClass: organizationalUnit
  73. description: A bunch of Ansible-lovers.
  74. ```
  75. The target host of an LDAP operation is assumed to be the same host as
  76. the Ansible task is executing so the above task would attempt to talk
  77. to LDAP server running on `server0` listenting on port 389. This example:
  78. ```yaml
  79. - hosts: server0
  80. tasks:
  81. - name: Ensure an LDAP entry exists for ou=People
  82. ldap_entry:
  83. server_uri: ldapi://server1/
  84. dn: "ou=People,dc=example,dc=com"
  85. ou: People
  86. objectClass: organizationalUnit
  87. description: A bunch of Ansible-lovers.
  88. ```
  89. would target an LDAP server at `server1`.
  90. ### Choosing Credentials
  91. Without any credentials (as in the above examples), the request will
  92. be made via a SASL `EXTERNAL` bind (similar to `ldapadd ... -Y
  93. EXTERNAL ...` on the command-line).
  94. Credentials can be specified as well:
  95. ```yaml
  96. - hosts: server0
  97. tasks:
  98. - name: Ensure an LDAP entry exists for ou=People
  99. ldap_entry:
  100. bind_dn: "cn=admin,dc=example,dc=com"
  101. bind_pw: "password"
  102. dn: "ou=People,dc=example,dc=com"
  103. ou: People
  104. objectClass: organizationalUnit
  105. description: A bunch of Ansible-lovers.
  106. ```
  107. ## Modules
  108. This repository provides four different modules:
  109. ### ldap_entry
  110. Ensures that an entry with a given `dn` exists/doesn't exist. If
  111. missing, it creates it. It present it does nothing. In particular,
  112. even if the entry has different attributes from those specified in
  113. Ansible, `ldap_entry` does nothing. You can, however, use
  114. `ldap_entry` to remove LDAP entries if you specify `state=absent`.
  115. #### Creating an entry
  116. ```yaml
  117. - name: Ensure an LDAP entry exists for ou=People
  118. ldap_entry:
  119. dn: "ou=People,dc=example,dc=com"
  120. ou: People
  121. objectClass: organizationalUnit
  122. description: A bunch of Ansible-lovers.
  123. ```
  124. If the `ou=People,dc=example,dc=com` entry has its `description` field
  125. changed, this task will not update it. It's therefore best to only
  126. specify the minimal number of fields required to successfully create
  127. the entity, given its LDAP `objectClass` values and later use
  128. `ldap_attr` to explicitly declare the expected state for each
  129. attribute individually. Or use `ldap_upsert`.
  130. #### Removing an entry
  131. ```yaml
  132. - name: Ensure an LDAP entry exists for ou=People
  133. ldap_entry:
  134. dn: "ou=People,dc=example,dc=com"
  135. state: absent
  136. ```
  137. ### ldap_attr
  138. Ensures that an attribute with a given value exists/doesn't exist for
  139. a given entry. If the entry does not exist, it throws an error. If
  140. the doesn't exist, it creates it. If it exists but has a different
  141. value, it updates it. You can use `ldap_attr` to remove LDAP
  142. attributes if you specify `state=absent`.
  143. #### Specifying an attribute exactly
  144. Here's a simple example.
  145. ```yaml
  146. - name: Ensure description is correct for ou=People
  147. ldap_attr:
  148. dn: "ou=People,dc=example,dc=com"
  149. name: description
  150. state: exact
  151. values: A bunch of Ansible-lovers.
  152. - name: Ensure members are correct for cn=Admins,ou=Groups
  153. ldap_attr:
  154. dn: "cn=Admins,ou=Groups,dc=example,dc=com"
  155. name: member
  156. state: exact
  157. values:
  158. - cn=joe,ou=People,dc=example,dc=com
  159. - cn=bob,ou=People,dc=example,dc=com
  160. ```
  161. This is a lot of work for many entries with many attributes. Consider
  162. `ldap_upsert` in these cases.
  163. #### Appending to an attribute
  164. ```yaml
  165. - name: Ensure members are present in cn=Admins,ou=Groups
  166. ldap_attr:
  167. dn: "cn=Admins,ou=Groups,dc=example,dc=com"
  168. name: member
  169. state: present
  170. values:
  171. - cn=joe,ou=People,dc=example,dc=com
  172. - cn=bob,ou=People,dc=example,dc=com
  173. ```
  174. The user `cn=mike,ou=People,dc=example,dc=com` could still be a
  175. `member` of `cn=Admins,ou=Groups,dc=example,dc=com` after this task
  176. runs.
  177. #### Removing an attribute
  178. ```yaml
  179. - name: Ensure user's password is not set
  180. ldap_attr:
  181. dn: "cn=joe,ou=People,dc=example,dc=com"
  182. state: absent
  183. name: userPassword
  184. ```
  185. ### ldap_upsert
  186. Ensures both that an entry exists as well as that its attributs have
  187. particular values. You cannot use `ldap_upsert` to remove entries or
  188. their attributes, but it useful when creating lots of entities with
  189. their attributes.
  190. ```yaml
  191. - name: Create a user
  192. ldap_upsert:
  193. dn: "uid=joe1234,ou=People,dc=example,dc=com"
  194. objectClass:
  195. - account
  196. - posixAccount
  197. cn: "Joe Smith"
  198. gn: "Joe"
  199. sn: "Smith"
  200. uid: "joe1234"
  201. homeDirectory: "/home/joe1234"
  202. userPassword: "..."
  203. ```
  204. ### ldap_search
  205. Perform an LDAP search. Useful in combination with Ansible's
  206. `register` keyword.
  207. This example performs a task for each LDAP user `account`:
  208. ```yaml
  209. - name:
  210. ldap_search:
  211. base: "ou=People,dc=example,dc=com"
  212. scope: onelevel
  213. filter: "(objectClass=account)"
  214. register: ldap_user_search
  215. - name: View search results
  216. debug: var=ldap_user_search
  217. - name: Do something for each user
  218. # ...
  219. with_items: "{{ ldap_user_search.results }}"
  220. ```