Files @ 8b486fb8e632
Branch filter:

Location: majic-ansible-roles/roles/ldap_server/tasks/main.yml

branko
MAR-149: Install Python 3 pip for tests in the mail_server role.
---

- 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)
  service:
    name: slapd
    state: restarted
  when: openldap_in_ssl_cert.changed
  tags:
    # [ANSIBLE0016] 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.
    - skip_ansible_lint

- name: Install Python LDAP bindings
  apt:
    name: python-ldap
    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 slapd service on boot (workaround for systemctl broken handling of SysV)
  command: "rcconf -on slapd"
  register: result
  changed_when: not result.stderr

- name: Enable slapd service
  service:
    name: slapd
    state: started

- 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

- 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 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