--- # Configuración de un dominio en el DIT. # Se distinguen 3 partes en este playbook: # 1) Verificar si el dominio es parte de otro ya existente. # 2) Si el dominio especificado NO es subdominio de otro, se agrega una entrada # correspondiente en cn=config. # 3) Se agrega el usuario admin para el dominio y las OUs # respectivas, por defecto: People, Group, Alias # parte 1: chequear si el dominio es subdominio de otro ----------------------- - name: "(aux) separar DN en componentes" set_fact: # componentes del dominio dcs: "{{ domain.name.split('.') }}" # dominio convertido a DN ddn: "{{ domain.name.split('.')|map('regex_replace','^','dc=')|join(',') }}" - name: "Buscar entradas en cn=config para {{ domain.name }} y superiores" ldap: state: "search" dn: "cn=config" objectClass: "olcDatabaseConfig" filter: "(olcSuffix=*)" bind_dn: "cn=admin,cn=config" bind_pw: "{{ openldap_admin_password }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" register: "sfxsearch" - name: "(aux) matchear resultados de búsqueda" set_fact: sfxmatches: "[ {% for i in range(dcs|length -1, -1, -1) %}\ {% set sdn = dcs[i:]|map('regex_replace','^','dc=')|join(',') %}\ {% for e in sfxsearch.entries if e[1]['olcSuffix'][0] == sdn %}\ {{ { 'dn': sdn, 'name': dcs[i:]|join('.'), 'configdn': e[0] } }},\ {% endfor %}\ {% endfor %}\ ]" - name: "(aux) setear dominio superior y credenciales" set_fact: superd: "{{ sfxmatches | first | default({'name': domain.name, 'dn': ddn}) }}" # DN del admin y clave admindn: "cn={{ domain.admincn | default('admin') }},{{ ddn }}" adminpw: "{{ domain.adminpw | default('password') }}" - name: "(aux) mergear detalles de dominio superior" set_fact: super: "{{ openldap_domains | selectattr('name', 'equalto', superd.name) | \ first | combine(superd) }}" # parte 2: agregar entrada en cn=config --------------------------------------- - name: "Entrada en cn=config para {{ domain.name }}" # Cuando el dominio no es hijo de otro ya existente, crear entrada en cn=config when: "super.dn == ddn" tags: skip_me block: - name: "(aux) setear propiedades" set_fact: olcDbIndex: "{{ domain.index | default(openldap_default_db_index) }}" olcAccess: "{{ domain.access | default(openldap_default_db_access) }}" backup_domains: "{{ backup_domains | default([]) | union([ddn]) }}" - name: "(aux) validar que entryUUID esté en olcDbIndex (necesario para replicar)" when: - "openldap_provider == True" - "olcDbIndex | map('regex_search','entryUUID.* eq$') | reject('equalto',[]) | list | length == 0" set_fact: olcDbIndex: "{{ olcDbIndex | union(['entryUUID eq']) }}" - name: "(aux) propiedad olcAccess (provider)" when: - "openldap_provider == True" - "domain.access_provider is defined" set_fact: olcAccess: "{{ domain.access_provider }}" - name: "(aux) propiedad olcAccess (consumer)" when: - "openldap_consumer == True" - "domain.access_consumer is defined" set_fact: olcAccess: "{{ domain.access_consumer }}" - name: "Directorio para el dominio" command: >- docker exec -u openldap:openldap {{ openldap_container_name }} mkdir "/var/lib/ldap/{{ ddn }}" register: ret failed_when: no changed_when: "ret.rc == 0" - name: "Entrada en cn=config para {{ ddn }}" register: "entry_add" ldap: dn: "olcDatabase=mdb,cn=config" dn_relative: yes filter: "(olcSuffix=\"{{ ddn }}\")" objectClass: - "olcDatabaseConfig" - "olcMdbConfig" attributes: olcDbMaxSize: "1073741824" olcSuffix: "{{ ddn }}" olcDbDirectory: "/var/lib/ldap/{{ ddn }}" olcRootDN: "{{ admindn }}" olcRootPW: "{{ adminpw }}" olcAccess: "{{ olcAccess }}" olcDbCheckpoint: "512 30" olcLastMod: "TRUE" olcDbIndex: "{{ olcDbIndex }}" olcLimits: "{{ domain.limits | default(openldap_default_db_limits) }}" bind_dn: "cn=admin,cn=config" bind_pw: "{{ openldap_admin_password }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" - name: "Overlay memberof para {{ ddn }}" when: "openldap_enable_memberof == True" ldap: dn: "olcOverlay=memberof,{{ entry_add.dn }}" dn_relative: yes objectClass: - "olcOverlayConfig" - "olcConfig" - "olcMemberOf" attributes: olcMemberOfDangling: "ignore" olcMemberOfRefInt: "FALSE" olcMemberOfGroupOC: "groupOfNames" olcMemberOfMemberAD: "member" olcMemberOfMemberOfAD: "memberOf" bind_dn: "cn=admin,cn=config" bind_pw: "{{ openldap_admin_password }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" - name: "Overlay syncprov para {{ ddn }}" when: "openldap_provider == True" ldap: dn: "olcOverlay=syncprov,{{ entry_add.dn }}" dn_relative: yes objectClass: - "olcOverlayConfig" - "olcSyncProvConfig" attributes: olcSpNoPresent: "TRUE" bind_dn: "cn=admin,cn=config" bind_pw: "{{ openldap_admin_password }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" - name: "Overlay accesslog para {{ ddn }}" when: "openldap_provider == True" ldap: dn: "olcOverlay=accesslog,{{ entry_add.dn }}" dn_relative: yes objectClass: - "olcOverlayConfig" - "olcAccessLogConfig" attributes: olcAccessLogDB: "cn=accesslog" olcAccessLogOps: "writes" olcAccessLogPurge: "07+00:00 01+00:00" olcAccessLogSuccess: "TRUE" bind_dn: "cn=admin,cn=config" bind_pw: "{{ openldap_admin_password }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" # EL ORDEN EN LAS SIGUIENTES 2 es importante!!! # solo se soporta UN provider - name: "Configurar cliente de replicacion (1: entrada olcSyncRepl)" when: - "openldap_consumer == True" - "openldap_provider_host | bool == True" ldap_attr: dn: "{{ entry_add.dn }}" name: "olcSyncRepl" state: "exact" values: >- {0}rid=3 provider=ldap://{{ openldap_provider_host }} bindmethod=simple binddn="{{ openldap_replicator_dn }}" credentials="{{ openldap_replicator_password }}" searchbase="{{ openldap_replicator_base }}" logbase="cn=accesslog" logfilter="(&(objectClass=auditWriteObject)(reqResult=0))" schemachecking=on type=refreshAndPersist retry="60 10 300 +" interval=00:00:01:00 syncdata=accesslog bind_dn: "cn=admin,cn=config" bind_pw: "{{ openldap_admin_password }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" - name: "Configurar cliente de replicacion (2: entrada olcUpdateRef)" when: - "openldap_consumer == True" - "openldap_provider_host | bool == True" ldap_attr: dn: "{{ entry_add.dn }}" name: "olcUpdateRef" state: "exact" values: "ldap://{{ openldap_provider_host }}" bind_dn: "cn=admin,cn=config" bind_pw: "{{ openldap_admin_password }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" - name: "Desconfigurar cliente de replicacion (2: entrada olcUpdateRef)" when: "openldap_consumer == False" ldap_attr: dn: "{{ entry_add.dn }}" name: "olcUpdateRef" state: "exact" values: [] bind_dn: "cn=admin,cn=config" bind_pw: "{{ openldap_admin_password }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" - name: "Desconfigurar cliente de replicacion (1: entrada olcSyncRepl)" when: "openldap_consumer == False" ldap_attr: dn: "{{ entry_add.dn }}" name: "olcSyncRepl" state: "exact" values: [] bind_dn: "cn=admin,cn=config" bind_pw: "{{ openldap_admin_password }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" # fin del bloque ------------------------------- # parte 3: agregar entrada en el DIT y crear usuario admin, replicator, OUs --------------- - when: - "openldap_create_dit_entries == True" - "openldap_consumer == False" block: - name: "(aux) credenciales para modificar entradas en {{ super.dn }}" set_fact: rootdn: "cn={{ super.admincn | default('admin') }},{{ super.dn }}" rootpw: "{{ super.adminpw | default(openldap_admmin_password|default('password')) }}" - name: "Entrada para organización {{ ddn }}" ldap: dn: "{{ ddn }}" objectClass: - "dcObject" - "organization" - "top" attributes: o: "{{ domain.name }}" bind_dn: "{{ rootdn }}" bind_pw: "{{ rootpw }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" tags: skip_me - name: "Usuario admin para {{ ddn }}" ldap: dn: "{{ admindn }}" objectClass: - "organizationalRole" - "simpleSecurityObject" attributes: description: "LDAP Administrator role for domain {{ domain.name }}" userPassword: "{{ adminpw }}" bind_dn: "{{ rootdn }}" bind_pw: "{{ rootpw }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" tags: skip_me - name: "Usuario de replicacion para {{ ddn }}" when: - "super.dn == ddn" - "ddn in openldap_replicator_dn" ldap: dn: "{{ openldap_replicator_dn }}" objectClass: - "organizationalRole" - "simpleSecurityObject" attributes: description: "LDAP Replication role for domain {{ domain.name }}" userPassword: "{{ openldap_replicator_password }}" bind_dn: "{{ rootdn }}" bind_pw: "{{ rootpw }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" tags: skip_me - name: "OUs para {{ ddn }}" ldap: dn: "ou={{ item }},{{ ddn }}" objectClass: - "organizationalUnit" - "top" attributes: ou: "{{ item }}" bind_dn: "{{ rootdn }}" bind_pw: "{{ rootpw }}" server_uri: "ldap://localhost:{{ openldap_bind_port }}" loop: "{{ domain.ou | default(openldap_default_domain_ous) }}" tags: skip_me - set_fact: ldap_base_dn: "{{ lookup('vars', 'ldap_base_dn', default=ddn) }}" ldap_admin_dn: "{{ lookup('vars', 'ldap_admin_dn', default=rootdn) }}" ldap_admin_password: "{{ lookup('vars', 'ldap_admin_password', default=rootpw) }}" # fin del bloque -------------------------------