--- - name: Set domain for slapd debconf: name: slapd question: slapd/domain vtype: string value: "{{ ldap_server_domain }}" - name: Set organisation for slapd debconf: name: slapd question: shared/organization vtype: string value: "{{ ldap_server_organization }}" - name: Install slapd apt: name: slapd state: present - name: Allow OpenLDAP user to traverse the directory with TLS private keys user: name: openldap append: true groups: ssl-cert register: openldap_in_ssl_cert - name: Restart slapd if group membership has changed (apply immediatelly) # noqa 503 # [503] Tasks that run when changed should likely be handlers # In order to be able to change LDAP server TLS configuration, it must be # able to read both the private key and certificate. Therefore we need to # immediatelly restart (since configuration is done live on the server. service: name: slapd state: restarted when: openldap_in_ssl_cert.changed - name: Install Python LDAP bindings apt: name: python3-pyldap state: present - name: Set-up LDAP server to listen on legacy SSL port lineinfile: dest: /etc/default/slapd state: present backrefs: true regexp: '^SLAPD_SERVICES=.*' line: 'SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"' notify: - Restart slapd - name: Enable and start slapd service service: name: slapd state: started enabled: true - name: Deploy system logger configuration file for slapd copy: src: slapd_rsyslog.conf dest: /etc/rsyslog.d/slapd.conf owner: root group: root mode: 0644 notify: - Restart rsyslog - name: Deploy configuration file for log rotation of slapd logs copy: src: slapd_logrotate dest: /etc/logrotate.d/slapd owner: root group: root mode: 0644 - name: Change log level for slapd ldap_attr: dn: cn=config state: exact name: olcLogLevel values: "{{ ldap_server_log_level }}" - name: Test if LDAP misc schema has been applied command: "ldapsearch -H ldapi:/// -Q -LLL -A -Y EXTERNAL -b cn=schema,cn=config -s one '(cn={*}misc)' cn" register: ldap_misc_schema_present changed_when: false - name: Deploy LDAP misc schema command: "ldapadd -H ldapi:/// -Q -Y EXTERNAL -f /etc/ldap/schema/misc.ldif" when: not ldap_misc_schema_present.stdout # Technically, the only thing this does is pick the size of DH # parameters to use, with GnuTLS (against which slapd is linked # against under Debian) picking a matching DH parameter from RFC-7919 # (https://www.ietf.org/rfc/rfc7919.txt). - name: Generate the LDAP server Diffie-Hellman parameter openssl_dhparam: owner: root group: openldap mode: 0640 path: "/etc/ssl/private/{{ ansible_fqdn }}_ldap.dh.pem" size: 2048 notify: - Restart slapd - name: Deploy LDAP TLS private key template: src: "ldap_tls_key.j2" dest: "/etc/ssl/private/{{ ansible_fqdn }}_ldap.key" mode: 0640 owner: root group: openldap notify: - Restart slapd - name: Deploy LDAP TLS certificate template: src: "ldap_tls_cert.j2" dest: "/etc/ssl/certs/{{ ansible_fqdn }}_ldap.pem" mode: 0644 owner: root group: root notify: - Restart slapd - name: Deploy configuration file for checking certificate validity via cron copy: content: "/etc/ssl/certs/{{ ansible_fqdn }}_ldap.pem" dest: "/etc/check_certificate/{{ ansible_fqdn }}_ldap.conf" owner: root group: root mode: 0644 # We need to have this hack around TLS configuration because OpenLDAP # expects both private key and certificate to be set at the same # time. # # OpenLDAP server behaviour is a bit weird around this thing, so here # is what happens: # # 1. First we set the private key, but ignore all errors. This has not # yet changed the private key path, though. # # 2. Then we set the certificate. This succeeds, but the private key # path still has the old value. If we haven't done the step (1), # this task would fail too. # # 3. Now we can finally change the private key too, and LDAP server # will be able to validate it against the corresponding certificate. # # See https://github.com/ansible/ansible/issues/25665 for more # information. - name: Configure TLS private key (ignore errors) ldap_attr: dn: cn=config name: olcTLSCertificateKeyFile values: "/etc/ssl/private/{{ ansible_fqdn }}_ldap.key" state: exact failed_when: false - name: Configure TLS certificate ldap_attr: dn: cn=config name: olcTLSCertificateFile values: "/etc/ssl/certs/{{ ansible_fqdn }}_ldap.pem" state: exact - name: Configure TLS private key ldap_attr: dn: cn=config name: olcTLSCertificateKeyFile values: "/etc/ssl/private/{{ ansible_fqdn }}_ldap.key" state: exact - name: Configure DH parameter ldap_attr: dn: cn=config name: olcTLSDHParamFile values: "/etc/ssl/private/{{ ansible_fqdn }}_ldap.dh.pem" state: exact - name: Configure TLS cipher suites ldap_attr: dn: cn=config name: olcTLSCipherSuite values: "{{ ldap_tls_ciphers }}" state: exact - name: Configure SSF for local unix socket connections ldap_attr: dn: cn=config state: exact name: olcLocalSSF values: "{{ ldap_server_ssf }}" - name: Configure required SSF ldap_attr: dn: cn=config state: exact name: olcSecurity values: "ssf={{ ldap_server_ssf }}" - name: Enable the memberof module ldap_attr: dn: "cn=module{0},cn=config" state: present name: olcModuleLoad values: "{1}memberof" - name: Enable the memberof overlay for database ldap_entry: dn: "olcOverlay={0}memberof,olcDatabase={1}mdb,cn=config" objectClass: - olcConfig - olcMemberOf - olcOverlayConfig attributes: olcOverlay: memberof olcMemberOfRefInt: "TRUE" olcMemberOfGroupOC: groupOfUniqueNames olcMemberOfMemberAD: uniqueMember - name: Apply database permissions m_ldap_permissions: filter: "(olcSuffix={{ ldap_server_int_basedn }})" rules: "{{ ldap_permissions }}" - name: Create basic LDAP directory structure ldap_entry: dn: "ou={{ item }},{{ ldap_server_int_basedn }}" objectClass: - organizationalUnit attributes: ou: "{{ item }}" with_items: - people - groups - services - name: Create the entry that will contain mail service information ldap_entry: dn: "ou=mail,ou=services,{{ ldap_server_int_basedn }}" objectClass: - organizationalUnit attributes: ou: mail - name: Create LDAP directory structure for mail service ldap_entry: dn: "ou={{ item }},ou=mail,ou=services,{{ ldap_server_int_basedn }}" objectClass: - organizationalUnit attributes: ou: "{{ item }}" with_items: - domains - aliases - name: Create or remove login entries for services ldap_entry: dn: "cn={{ item.name }},ou=services,{{ ldap_server_int_basedn }}" objectClass: - applicationProcess - simpleSecurityObject attributes: cn: "{{ item.name }}" userPassword: "{{ item.password }}" state: "{{ item.state | default('present') }}" with_items: "{{ ldap_server_consumers }}" - name: Update services login passwords ldap_attr: dn: "cn={{ item.name }},ou=services,{{ ldap_server_int_basedn }}" name: userPassword values: "{{ item.password }}" state: exact with_items: "{{ ldap_server_consumers }}" when: "item.state | default('present') == 'present'" - name: Create or remove user-supplied groups ldap_entry: dn: "cn={{ item.name }},ou=groups,{{ ldap_server_int_basedn }}" objectClass: - groupOfUniqueNames attributes: cn: "{{ item.name }}" uniqueMember: "cn=NONE" state: "{{ item.state | default('present') }}" with_items: "{{ ldap_server_groups }}" - name: Create user-supplied LDAP entries ldap_entry: dn: "{{ item.dn }}" objectClass: "{{ item.attributes.objectClass }}" attributes: "{{ item.attributes }}" state: "{{ item.state | default('present') }}" with_items: "{{ ldap_entries }}" - name: Deploy firewall configuration for LDAP copy: src: "ferm_ldap.conf" dest: "/etc/ferm/conf.d/10-ldap.conf" owner: root group: root mode: 0640 notify: - Restart ferm - name: Deploy temporary file with LDAP admin password template: src: "ldap_admin_password.j2" dest: "/root/.ldap_admin_password" owner: root group: root mode: 0400 changed_when: false - name: Test if LDAP admin password needs to be changed command: "ldapwhoami -H ldapi:/// -D 'cn=admin,{{ ldap_server_int_basedn }}' -x -y /root/.ldap_admin_password" register: ldap_admin_password_check changed_when: ldap_admin_password_check.rc != 0 failed_when: false - name: Update LDAP admin password command: "ldappasswd -Y EXTERNAL -H ldapi:/// 'cn=admin,{{ ldap_server_int_basedn }}' -T /root/.ldap_admin_password" when: ldap_admin_password_check.rc != 0 - name: Remove temporary file with LDAP admin password file: path: "/root/.ldap_admin_password" state: absent changed_when: false - name: Enable backup include: backup.yml when: enable_backup - name: Explicitly run all handlers include: ../handlers/main.yml when: "run_handlers | default(False) | bool()" tags: - handlers