---
- name: ldap Set defaults for slapd
  tags: ldap
  become: true
  ansible.builtin.debconf:
    name: slapd
    question: slapd/internal/adminpw
    value: "{{ ldap_admin_config_pw }}"
    vtype: select
  when: init_ldap | default('false') | bool
  # do not log passwords
  diff: false

- name: ldap Install slapd and ldap-utils
  tags: ldap
  become: true
  ansible.builtin.apt:
    pkg:
      - slapd
      - ldap-utils
    state: present
  when: init_ldap | default('false') | bool

# stop ldap
- name: ldap stop for initial setup
  tags: ldap
  become: true
  ansible.builtin.service:
    name: slapd
    state: stopped
  when: init_ldap | default('false') | bool

# purge everything from ldap
- name: ldap purge database
  tags: ldap
  become: true
  ansible.builtin.shell: 'rm /var/lib/ldap/*.mdb'
  when: init_ldap | default('false') | bool

# start ldap
- name: start ldap for initial setup
  tags: ldap
  become: true
  ansible.builtin.service:
    name: slapd
    state: started
  when: init_ldap | default('false') | bool

- name: ldap get installed schemes before
  tags: ldap
  ansible.builtin.shell: 'ldapsearch -x -s base -b "" +'
  register: ldap_schemata
  # this works only on fresh installation:
  ignore_errors: true

#- debug:
#    var: ldap_schemata.stdout_lines
#  tags: ldap


- name: set hosttype
  tags: ldap
  set_fact:
     hosttype: "{{ inventory_hostname | regex_search('(devel)|(prod)|(localdev)') }}"

- name: set hostnames
  tags: ldap
  set_fact:
    name_login: "perfact-login-{{ hosttype }}"
    name_mail: "perfact-mail-{{ hosttype }}"
    name_file: "perfact-file-{{ hosttype }}"

- name: ldap fix /etc/hosts
  tags: ldap
  become: true
  ansible.builtin.copy:
    dest: /etc/hosts
    content: |
      127.0.0.1	localhost
      127.0.1.1	{{ inventory_hostname }}

      # The following lines are desirable for IPv6 capable hosts
      #::1     localhost ip6-localhost ip6-loopback
      #ff02::1 ip6-allnodes
      #ff02::2 ip6-allrouters

      # LDAP should not depend on DNS
      {{ hostvars[name_login]['ip_address'] }} perfact-login-{{ hosttype }}.perfact.de
      {{ hostvars[name_mail]['ip_address']}} perfact-mail-{{ hosttype }}.perfact.de
      {{ hostvars[name_file]['ip_address'] }} perfact-file-{{ hosttype }}.perfact.de
  notify: restart slapd.service


#####################
###   setup SSL   ###
#####################
- name: ldap mkdir /etc/ldap/ssl
  tags: ldap
  become: true
  ansible.builtin.file:
    path: "/etc/ldap/ssl/"
    state: directory
    owner: openldap
    group: openldap
    mode: '0750'
  when: init_ldap | default('false') | bool

### certs and keys are locally stored in ./internalit/roles/ldap/files
- name: ldap ssl copy CA cert
  tags: ldap
  become: true
  ansible.builtin.copy:
    src: "CA_PerFact_InternalIT.pem"
    dest: "/etc/ldap/ssl/CA_PerFact_InternalIT.pem"
    owner: root
    group: openldap
    mode: '0644'
  when: init_ldap | default('false') | bool

- name: ldap ssl copy SSL cert
  tags: ldap
  become: true
  ansible.builtin.copy:
    src: "{{ inventory_hostname }}.perfact.de.crt"
    dest: "/etc/ldap/ssl/{{ inventory_hostname }}.perfact.de.crt"
    owner: openldap
    group: openldap
    mode: '0644'
  when: init_ldap | default('false') | bool

- name: ldap ssl copy SSL key
  tags: ldap
  become: true
  ansible.builtin.copy:
    src: "{{ inventory_hostname }}.perfact.de.key"
    dest: "/etc/ldap/ssl/{{ inventory_hostname }}.perfact.de.key"
    owner: openldap
    group: openldap
    mode: '0600'
  when: init_ldap | default('false') | bool


########################
###   ldap schemes   ###
########################

### copy schemes we will use from ansible-repo (we will always use the same scheme)
- name: ldap copy all schemes we will use
  tags: ldap
  ansible.builtin.template:
    src: "schemes/{{ item }}"
    dest: "/tmp/{{ item }}"
    mode: '0600'
  with_items:
    # - core.ldif
    # - inetorgperson.ldif
    # - nis.ldif
    - postfix_scheme.ldif
    #- perfact_scheme.ldif
    - misc.ldif
  when: init_ldap | default('false') | bool

# install all ldap shemes
- name: ldap import all schemes we will use
  tags: ldap
  become: true
  ansible.builtin.shell: ldapadd -Y EXTERNAL -H ldapi:/// -f /tmp/{{ item }}
  with_items:
    # - core.ldif            # already added by debian
    # - inetorgperson.ldif   # already added by debian
    # - nis.ldif             # already added by debian
    - postfix_scheme.ldif
    # - perfact_scheme.ldif  # actual not required
    # for eMail aliases:
    - misc.ldif
  when: init_ldap | default('false') | bool
  ignore_errors: true

#  - name: debug installed schemes from ldap after
#    tags: ldap
#    shell: 'ldapsearch -x -s base -b "" +'
#    register: ldap_schemata_after
#
#  - debug:
#      var: ldap_schemata_after.stdout_lines
#    tags: ldap

##########################
###   configure ldap   ###
##########################
# copy template configs
- name: ldap copy configuration ldifs
  tags: ldap
  ansible.builtin.template:
    src: "{{ item }}.j2"
    dest: '/tmp/{{ item }}'
    mode: '0600'
  with_items:
    - tls.ldif
    - db.ldif
    - base.ldif
    - replication.ldif
    - manage-users.ldif
  when: init_ldap | default('false') | bool

- name: ldap only listen to interface of DNS-Name and localhost
  tags: ldap
  become: true
  ansible.builtin.lineinfile:
     path: /etc/default/slapd
     regexp: '^SLAPD_SERVICES='
     line: 'SLAPD_SERVICES="ldap://{{ ip_address }} ldap://127.0.0.1 ldapi:///"'
  notify: restart slapd.service

- name: ldap add tls config tls.ldif
  tags: ldap
  become: true
  ansible.builtin.shell: ldapadd -Y EXTERNAL -H ldapi:/// -f /tmp/tls.ldif
  when: init_ldap | default('false') | bool
  # for repeated execution only:
  ignore_errors: true
  # do not log passwords
  diff: false
  notify: restart slapd.service

- name: ldap enable debug to /var/log/slapd.log
  tags: ldap
  ansible.builtin.include_tasks: ldap_debug.yml

- name: ldap add root config db.ldif
  tags: ldap
  become: true
  ansible.builtin.shell: ldapadd -Y EXTERNAL -H ldapi:/// -f /tmp/db.ldif
  when: init_ldap | default('false') | bool
  # for repeated execution only:
  ignore_errors: true
  # do not log passwords
  diff: false

- name: ldap add base config base.ldif
  tags: ldap
  become: true
  ansible.builtin.shell: ldapadd -x -D cn=admin,{{ ldap_basedn }} -w {{ vault_ldap_perfact_pw }} -f /tmp/base.ldif
  when:
    - init_ldap | default('false') | bool
  # for repeated execution only:
  ignore_errors: true
  # do not log passwords
  #diff: false

# add perfact-useradmin in ou=Manager
# add [mail|file]AccountReader ou=[mail|file] will be synced to slave
- name: add manager users on perfact-login
  tags: ldap
  become: true
  ansible.builtin.shell: ldapadd -x -D cn=admin,{{ ldap_basedn }} -w {{ ldap_perfact_pw }} -f /tmp/manage-users.ldif
  when:
    - init_ldap | default('false') | bool
    - ('perfact-login-' in  inventory_hostname )
  # for repeated execution only
  ignore_errors: true
  # do not log passwords
  diff: false

- name: ldap add replication.ldif
  tags: ldap
  become: true
  ansible.builtin.shell: ldapadd -Y EXTERNAL -H ldapi:/// -f /tmp/replication.ldif
  when: init_ldap | default('false') | bool
  # for repeated execution only:
  ignore_errors: true
  # do not log passwords
  diff: false

### this allows examination of the data environment
#  # debug dynamic datadir users
#  # will be loaded by roles/perfact-mail/ldap/meta/main.yml (dependencies:   - role: load_users)
#  - name: ldap debug datadir users
#    tags: ldap
#    ansible.builtin.debug:
#      msg: "{{ users }}"

#  - name: ldap debug dictionary mailusers
#    tags: ldap
#    ansible.builtin.debug:
#      msg: "{{ mailusers }}"

#  - name: ldap debug dictionary other_mails
#    tags: ldap
#    ansible.builtin.debug:
#      msg: "{{ other_mails }}"

#  - name: debug access to other_mails-datenschutz.mail_address
#    tags: ldap
#    ansible.builtin.debug:
#      msg: "{{ other_mails.datenschutz.mail_address }}"

########################################
######   ldap import of userdata   #####
########################################
#     init_user is set to true
#     and
#     on ldap-master only
- when:
    - (init_users | default('false') | bool)
    - ('perfact-login-' in  inventory_hostname )
  tags: ldap
  block:
    # compile list of users with subkeys
    - name: ldap compile list of users with subkeys
      set_fact:
        users_mail_virtual: "{{ users | map_dict_values_to_subkey('mail_virtual') }}"
        # will create:
        #"ansible_facts": {
        #  "users_mail_virtual": {
        #      "mmustermann": [
        #          "mmustermann@perfact.de",
        #          "mmu@perfact.de"
        #      ],
      changed_when: False

    #  # debug dynamic datadir users
    #  - name: debug dynamic datadir users
    #    tags: ldap
    #    debug:
    #      msg: "{{ users_mail_virtual }}"

    # inital ldif of real user - never run on production system - passwords will be resettet
    - name: ldap create ldif for first import user-import.ldif
      ansible.builtin.template:
        src: mail-user-import.ldif.j2
        dest: /tmp/mail-user-import.ldif
        mode: '0600'
      when: init_users | default('false') | bool
      # do not log passwords
      diff: false

    # import real user ldif - never run on production system - passwords will be resettet
    - name: ldap import from mail-user-import.ldif
      become: true
      ansible.builtin.shell: ldapadd -x -D "cn=admin,{{ ldap_basedn }}" -w "{{ vault_ldap_perfact_pw }}" -H ldap:// -f /tmp/mail-user-import.ldif
      when: init_users | default('false') | bool
      # do not log passwords
      diff: false

    # initial ldif for file users
    - name: set filename to import on prod
      when: ('-prod' in inventory_hostname )
      ansible.builtin.set_fact:
        importfilename: vault-ldap-import-file-prod.ldif

    - name: set filename to import on devel
      when: not ('-prod' in inventory_hostname )
      ansible.builtin.set_fact:
        importfilename: vault-ldap-import-file-devel.ldif

    - name: copy ldap-import-file to system
      ansible.builtin.copy:
        src: '{{ importfilename }}'
        dest: '/tmp/{{ importfilename }}'
        mode: '0600'
      diff: false

    - name: ldap import from vault-ldap-import-file-*.ldif
      become: true
      ansible.builtin.shell: ldapadd -x -D "cn=admin,{{ ldap_basedn }}" -w "{{ vault_ldap_perfact_pw }}" -H ldap:// -f "/tmp/{{ importfilename }}"
      when: init_users | default('false') | bool
      # do not log passwords
      diff: false

# end block add userdata (master only)

####################
#####   ACLs   #####
####################
# ACLs are not completed yet
# but wee need access for user 'ldap_sync_to_mail'
- name: ldap create acls.ldif for master and slave
  tags: ldap, ldap_acls
  ansible.builtin.template:
    src: acls.ldif.j2
    dest: /tmp/acls.ldif
    mode: 0600

- name: ldap add ACLs
  tags: ldap, ldap_acls
  become: true
  ansible.builtin.shell: ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/acls.ldif

### TODO activate this before golive
# #####   Cleanup   #####
# - name: ldap remove ldif from /tmp/
#   ansible.builtin.file:
#     path: /tmp/{{ item }}
#     state: absent
#   with_items:
#    - db.ldif
#    - base.ldif
#    - user-import.ldif
#    - acls.ldif
#    - replication.ldif
#    - ldap-debug.ldif
#    - tls.ldif
#    - "{{ importfilename }}"

- name: create ldap backup folder
  tags: [ ldap, ldap-backup ]
  become: true
  ansible.builtin.file:
    path: /vol/backup/ldap
    owner: root
    group: root
    mode: '0700'
    state: directory

- name: setup ldap backup files with right modes
  tags: [ ldap, ldap-backup ]
  become: true
  ansible.builtin.file:
    path: "/vol/backup/ldap/{{ item }}"
    owner: root
    group: root
    mode: '0600'
    state: touch
  with_items:
    - slapcat-n0.ldif
    - slapcat-n1.ldif

- name: create /opt/perfact/custom if not exists
  tags: [ ldap, ldap-backup ]
  become: true
  ansible.builtin.file:
    path: /opt/perfact/custom
    owner: root
    group: root
    state: directory
    recurse: yes

- name: create ldap backup script
  tags: [ ldap, ldap-backup ]
  become: true
  ansible.builtin.copy:
    dest: /opt/perfact/custom/ldap-backup.sh
    mode: '0700'
    content: |
      #!/bin/bash
      #
      # managed by ansible - do not edit manually
      #
      # create backup of ldap database 0 and 1
      /usr/sbin/slapcat -n 0 > /vol/backup/ldap/slapcat-n0.ldif
      chmod 0600 /vol/backup/ldap/slapcat-n0.ldif
      /usr/sbin/slapcat -n 1 > /vol/backup/ldap/slapcat-n1.ldif
      chmod 0600 /vol/backup/ldap/slapcat-n1.ldif


- name: create cronjob ldap backup
  tags: [ ldap, ldap-backup ]
  become: true
  ansible.builtin.copy:
    dest: /etc/cron.d/ldap-backup
    content: |
      # managed by ansible - do not edit manually
      #
      # create backup of ldap database 0 and 1
      50 18 * * * root  /opt/perfact/custom/ldap-backup.sh
