diff --git a/README.md b/README.md index 7b5ad76..13f7a20 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,7 @@ [![CircleCI status](https://img.shields.io/circleci/project/github/uubk/auth-server/master.svg?style=shield)](https://circleci.com/gh/uubk/auth-server/tree/master) ![License](https://img.shields.io/github/license/uubk/auth-server.svg?style=popout) -Set up 389ds and MIT Kerberos to authenticate users. Tested on Debian 11. - -Warning: This role only supports Debian 11 - for 9/10, you'll want to use the old code on the buster branch. +Set up 389ds to authenticate users. ## Description This role sets up 389ds in multi-master mode. @@ -19,9 +17,6 @@ This role sets up 389ds in multi-master mode. | `auth_ldap_sync_pwd` | `False` | The LDAP syncrepl user password | | `auth_ldap_group` | `core` | The group of hosts this role is applied to | | `auth_ldap_init_source` | `False` | The name of the host that should be used as a LDAP data source when adding new hosts. | -| `auth_kerberos_ldap_password` | `False` | The kerberos LDAP service account password | -| `auth_kerberos_database_master_key` | `False` | The initial kerberos database master key | -| `auth_kerberos_enctypes` | `aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128` | Which encryption modes to enable? The default is for recent versions of Kerberos and no Windows clients only. | | `auth_ldap_have_tls` | `True` | Whether to enable SSL/TLS support in openLDAP | | `auth_ldap_ssl_cert_path` | `/etc/ldap/server.pem` | Path to openLDAP's certificate | | `auth_ldap_ssl_key_path` | `/etc/ldap/server.key` | Path to openLDAP's certificate's key| @@ -32,9 +27,6 @@ This role sets up 389ds in multi-master mode. | `auth_ldap_service_bases` | (see defaults/main.yml) | LDAP containers to create for services | | `auth_ldap_service_accounts` | (see defaults/main.yml) | Kerberos services to generate. This will also write out a keytab for each service. | | `auth_ldap_permissions` | (see defaults/main.yml) | ACIs to set on the directory | -| `auth_kerberos_admin_privs` | `[]` | Kerberos principals to grant administrative permissions to (see defaults/main.yml for format) | -| `auth_ldap_store_pam` | `True` | Whether to actually store the generated 389ds PAM config. Useful if you want to customize it using another role | -|`auth_kerberos_curves` | `edwards25519` | Curves to use for kerberos SPAKE | | `auth_ldap_use_memberof_plugin` | `False` | Whether to enable the `memberOf` LDAP plugin. | Users can be created by putting them into `auth_ldap_users` as a dict with the following format: diff --git a/defaults/main.yml b/defaults/main.yml index fc2a9bb..fb1b7b9 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -8,7 +8,7 @@ auth_ldap_domain_subdomains: [] # If your LDAP servers are not mutually reachable via their FQDN, set this for # replication -auth_ldap_use_external_domain: False +auth_ldap_use_external_domain: false auth_ldap_external_domain: None # LDAP admin credentials (you need to change these) @@ -18,22 +18,13 @@ auth_ldap_sync_pwd: None # LDAP init source (you need to change this) # Init source designates the ldap server whose contents should be copied to all # other servers on iniy -auth_ldap_init_source: False - -# Kerberos admin credentials (you need to change these) -auth_kerberos_ldap_password: False -auth_kerberos_database_master_key: False -# Principals to be granted admin rights -auth_kerberos_admin_privs: [] -# - principal: foo@EXAMPLE.ORG -# privileges: '*' -# target: '*' - -# Group that all LDAP/kerberos servers are in (you probably need to change this) +auth_ldap_init_source: false + +# Group that all LDAP servers are in (you probably need to change this) auth_ldap_group: core # TLS for openLDAP -auth_ldap_have_tls: True +auth_ldap_have_tls: true auth_ldap_ssl_cert_path: /etc/ldap/server.pem auth_ldap_ssl_key_path: /etc/ldap/server.key auth_ldap_ssl_ca_path: /etc/ldap/ca.pem @@ -42,12 +33,6 @@ auth_ldap_ssl_ca_path_src: /etc/dirsrv/ca.pem auth_ldap_ssl_cn: "{{ ansible_fqdn }}" auth_ldap_ssl_desc: "PKI" -# Enctypes for recent kerberos -auth_kerberos_enctypes: "aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96" - -# Elliptic curves for SPAKE -auth_kerberos_curves: "edwards25519" - # Users to create auth_ldap_users: [] @@ -136,11 +121,8 @@ auth_ldap_user_objectclasses: - top - inetOrgPerson -# Whether to actually store the pam kerberos passthrough config -auth_ldap_store_pam: True - # Whether to enable the memberOf plugin -auth_ldap_use_memberof_plugin: False +auth_ldap_use_memberof_plugin: false # For additional schemas # auth_ldap_additional_schema: @@ -151,7 +133,3 @@ auth_ldap_use_memberof_plugin: False # auth_ldap_eq_indexes: # - attribute: customAttr # database: userRoot - -# Gokrb5 on Debian Buster _also_ fails preauth when not setting this explicitly. On bullseye it works with the same -# binary. To enable the workaround, change from -1 to your real preauth type (e.g. 20 for aes256-cts-hmac-sha384-192). -auth_kerberos_fixed_preauth: -1 diff --git a/handlers/main.yml b/handlers/main.yml index 78a8a8c..6d4ba5f 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,29 +1,14 @@ --- - - name: restart kdc - become: True - service: - name: krb5-kdc - state: restarted - enabled: yes - notify: restart kadmind +- name: Restart dirsrv + become: true + service: + name: "dirsrv@{{ auth_ldap_shortname }}" + state: restarted + enabled: true - - name: restart kadmind - become: True - service: - name: krb5-admin-server - state: restarted - enabled: yes - - - name: restart dirsrv - become: True - service: - name: "dirsrv@{{ auth_ldap_shortname }}" - state: restarted - enabled: yes - - - name: restart haproxy - become: True - service: - name: haproxy - state: restarted - enabled: yes +- name: Restart haproxy + become: true + service: + name: haproxy + state: restarted + enabled: true diff --git a/tasks/389-acl.yml b/tasks/389-acl.yml index 2664854..c7f4c16 100644 --- a/tasks/389-acl.yml +++ b/tasks/389-acl.yml @@ -1,70 +1,70 @@ --- - - name: Restrict anonymous bind to RootDN - ldap_attrs: - dn: "cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: exact - attributes: - nsslapd-allow-anonymous-access: 'rootdse' - notify: restart dirsrv +- name: Restrict anonymous bind to RootDN + community.general.ldap_attrs: + dn: "cn=config" + server_uri: "{{ auth_ldap_ansible_url }}" + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: exact + attributes: + nsslapd-allow-anonymous-access: 'rootdse' + notify: Restart dirsrv - - name: Create LDAP system users - run_once: true - ldap_entry: - dn: "cn={{ item.name }},ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" - server_uri: "{{ auth_ldap_ansible_url }}" - objectClass: "{{ auth_ldap_user_objectclasses }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: present - attributes: - uid: "{{ item.id }}" - uidNumber: "{{ item.uid }}" - gidNumber: "{{ item.gid }}" - userPassword: "{{ item.initialPassword }}" - homeDirectory: "/dev/null" - sn: "{{ item.name }}" - givenName: "Serviceaccount" - mail: "root@{{ auth_ldap_domain }}" - with_items: - - "{{ auth_ldap_system_users }}" - no_log: True +- name: Create LDAP system users + run_once: true + community.general.ldap_entry: + dn: "cn={{ item.name }},ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" + server_uri: "{{ auth_ldap_ansible_url }}" + objectClass: "{{ auth_ldap_user_objectclasses }}" + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: present + attributes: + uid: "{{ item.id }}" + uidNumber: "{{ item.uid }}" + gidNumber: "{{ item.gid }}" + userPassword: "{{ item.initialPassword }}" + homeDirectory: "/dev/null" + sn: "{{ item.name }}" + givenName: "Serviceaccount" + mail: "root@{{ auth_ldap_domain }}" + with_items: + - "{{ auth_ldap_system_users }}" + no_log: true - - name: Create LDAP reader group - run_once: true - ldap_entry: - dn: "cn=sys_ldap_readers,ou=Groups,{{ auth_ldap_domain_ldap }}" - objectClass: groupOfNames - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - server_uri: "{{ auth_ldap_ansible_url }}" - attributes: - member: "{{ item }}" - with_items: "{{ auth_ldap_allow_read|first }}" +- name: Create LDAP reader group + run_once: true + community.general.ldap_entry: + dn: "cn=sys_ldap_readers,ou=Groups,{{ auth_ldap_domain_ldap }}" + objectClass: groupOfNames + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + server_uri: "{{ auth_ldap_ansible_url }}" + attributes: + member: "{{ item }}" + with_items: "{{ auth_ldap_allow_read | first }}" - - name: Add LDAP reader group members - run_once: true - ldap_attrs: - dn: "cn=sys_ldap_readers,ou=Groups,{{ auth_ldap_domain_ldap }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - server_uri: "{{ auth_ldap_ansible_url }}" - state: exact - attributes: - member: "{{ auth_ldap_allow_read }}" +- name: Add LDAP reader group members + run_once: true + community.general.ldap_attrs: + dn: "cn=sys_ldap_readers,ou=Groups,{{ auth_ldap_domain_ldap }}" + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + server_uri: "{{ auth_ldap_ansible_url }}" + state: exact + attributes: + member: "{{ auth_ldap_allow_read }}" - - name: Configure LDAP ACLs - ldap_attrs: - dn: "{{ item.target }}" - bind_dn: "cn=Directory Manager" - bind_pw: '{{ auth_ldap_admin_pwd }}' - server_uri: "{{ auth_ldap_ansible_url }}" - attributes: - aci: "{{ item.acls }}" - state: exact - when: item.target != "cn=Kerberos,{{ auth_ldap_domain_ldap }}" - with_items: "{{ auth_ldap_permissions }}" - tags: - - skip_ansible_lint +- name: Configure LDAP ACLs + ldap_attrs: + dn: "{{ item.target }}" + bind_dn: "cn=Directory Manager" + bind_pw: '{{ auth_ldap_admin_pwd }}' + server_uri: "{{ auth_ldap_ansible_url }}" + attributes: + aci: "{{ item.acls }}" + state: exact + when: item.target != "cn=Kerberos,{{ auth_ldap_domain_ldap }}" + with_items: "{{ auth_ldap_permissions }}" + tags: + - skip_ansible_lint diff --git a/tasks/389-replication.yml b/tasks/389-replication.yml index 9642b83..585e941 100644 --- a/tasks/389-replication.yml +++ b/tasks/389-replication.yml @@ -1,118 +1,118 @@ --- - - name: Create replication user - ldap_entry: - dn: "cn=replication manager,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - objectClass: - - top - - person - - inetorgperson - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: present - attributes: - cn: replication manager - sn: RM - userPassword: "{{ auth_ldap_sync_pwd }}" - passwordExpirationTime: 20990119031407Z +- name: Create replication user + community.general.ldap_entry: + dn: "cn=replication manager,cn=config" + server_uri: "{{ auth_ldap_ansible_url }}" + objectClass: + - top + - person + - inetorgperson + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: present + attributes: + cn: replication manager + sn: RM + userPassword: "{{ auth_ldap_sync_pwd }}" + passwordExpirationTime: 20990119031407Z - - name: Create supplier replicas - ldap_entry: - dn: "cn=replica,cn=\"{{ auth_ldap_domain_ldap }}\",cn=mapping tree,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - objectClass: - - top - - extensibleObject - - nsds5replica - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: present - attributes: - cn: replica - nsds5replicaroot: "{{ auth_ldap_domain_ldap }}" - nsds5replicaid: "{{ auth_ldap_server_id }}" - nsds5replicatype: 3 - nsds5flags: 1 - nsds5ReplicaPurgeDelay: 604800 - nsds5ReplicaBindDN: "cn=replication manager,cn=config" +- name: Create supplier replicas + community.general.ldap_entry: + dn: "cn=replica,cn=\"{{ auth_ldap_domain_ldap }}\",cn=mapping tree,cn=config" + server_uri: "{{ auth_ldap_ansible_url }}" + objectClass: + - top + - extensibleObject + - nsds5replica + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: present + attributes: + cn: replica + nsds5replicaroot: "{{ auth_ldap_domain_ldap }}" + nsds5replicaid: "{{ auth_ldap_server_id }}" + nsds5replicatype: 3 + nsds5flags: 1 + nsds5ReplicaPurgeDelay: 604800 + nsds5ReplicaBindDN: "cn=replication manager,cn=config" - - name: Create replication agreements - ldap_entry: - dn: "cn={{ item[0] }}-to-{{ item[1] }},cn=replica,cn=\"{{ auth_ldap_domain_ldap }}\",cn=mapping tree,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - objectClass: - - top - - nsds5replicationagreement - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: present - attributes: - cn: "{{ item[0] }}-to-{{ item[1] }}" - nsds5replicahost: "127.0.0.1" - nsds5replicaport: "{{ 60389 + hostvars[item[0]]['auth_ldap_server_id'] }}" - nsds5ReplicaBindDN: "cn=replication manager,cn=config" - nsds5replicabindmethod: SIMPLE - nsds5replicaroot: "{{ auth_ldap_domain_ldap }}" - description: "agreement to replicate {{ item[1] }} to {{ item[0] }}" - nsds5replicacredentials: "{{ auth_ldap_sync_pwd }}" - when: (item[0] != item[1]) and (item[1] == ansible_fqdn) - with_cartesian: - - "{{ groups[auth_ldap_group] }}" - - "{{ groups[auth_ldap_group] }}" - register: repchanged - no_log: true +- name: Create replication agreements + community.general.ldap_entry: + dn: "cn={{ item[0] }}-to-{{ item[1] }},cn=replica,cn=\"{{ auth_ldap_domain_ldap }}\",cn=mapping tree,cn=config" + server_uri: "{{ auth_ldap_ansible_url }}" + objectClass: + - top + - nsds5replicationagreement + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: present + attributes: + cn: "{{ item[0] }}-to-{{ item[1] }}" + nsds5replicahost: "127.0.0.1" + nsds5replicaport: "{{ 60389 + hostvars[item[0]]['auth_ldap_server_id'] }}" + nsds5ReplicaBindDN: "cn=replication manager,cn=config" + nsds5replicabindmethod: SIMPLE + nsds5replicaroot: "{{ auth_ldap_domain_ldap }}" + description: "agreement to replicate {{ item[1] }} to {{ item[0] }}" + nsds5replicacredentials: "{{ auth_ldap_sync_pwd }}" + when: (item[0] != item[1]) and (item[1] == ansible_fqdn) + with_cartesian: + - "{{ groups[auth_ldap_group] }}" + - "{{ groups[auth_ldap_group] }}" + register: repchanged + no_log: true - - name: Create reinit script - become: True - template: - src: 389-reinit.ldif.j2 - dest: /etc/ldap/ansible/reinit.ldif - owner: root - group: root - mode: 0640 +- name: Create reinit script + become: true + ansible.builtin.template: + src: 389-reinit.ldif.j2 + dest: /etc/ldap/ansible/reinit.ldif + owner: root + group: root + mode: "0640" - - name: Reinit replication peers from master - when: ansible_fqdn == auth_ldap_init_source and repchanged.changed - become: True - expect: - command: /bin/bash -c "/usr/bin/ldapmodify -x -D cn=Directory\ Manager -W < /etc/ldap/ansible/reinit.ldif" - responses: - (Enter LDAP Password): "{{ auth_ldap_admin_pwd }}" - no_log: true - tags: - - skip_ansible_lint +- name: Reinit replication peers from master + when: ansible_fqdn == auth_ldap_init_source and repchanged.changed + become: true + expect: + command: /bin/bash -c "/usr/bin/ldapmodify -x -D cn=Directory\ Manager -W < /etc/ldap/ansible/reinit.ldif" + responses: + (Enter LDAP Password): "{{ auth_ldap_admin_pwd }}" + no_log: true + tags: + - skip_ansible_lint - - name: Give replication some time - when: repchanged.changed - pause: - seconds: 5 - tags: - - skip_ansible_lint +- name: Give replication some time + when: repchanged.changed + pause: + seconds: 5 + tags: + - skip_ansible_lint - - name: Enable Retro Changelog Plugin - ldap_attrs: - dn: "cn=Content Synchronization,cn=plugins,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: exact - attributes: - nsslapd-pluginEnabled: 'on' - notify: restart dirsrv +- name: Enable Retro Changelog Plugin + community.general.ldap_attrs: + dn: "cn=Content Synchronization,cn=plugins,cn=config" + server_uri: "{{ auth_ldap_ansible_url }}" + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: exact + attributes: + nsslapd-pluginEnabled: 'on' + notify: Restart dirsrv # Disable replication of the memberOf field in multi master setup # this should be done according to the documentation [here](https://access.redhat.com/solutions/28282) - - name: Configure replication for memberOf plugin - ldap_attrs: - dn: "cn={{ item[0] }}-to-{{ item[1] }},cn=replica,cn={{ auth_ldap_domain_ldap | replace(\"=\", \"\\=\") | replace(\",\", \"\\,\")}},cn=mapping tree,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: exact - attributes: - nsds5replicatedattributelist: (objectclass=*) $ EXCLUDE memberof - when: (item[0] != item[1]) and (item[1] == ansible_fqdn) - with_cartesian: - - "{{ groups[auth_ldap_group] }}" - - "{{ groups[auth_ldap_group] }}" - notify: restart dirsrv +- name: Configure replication for memberOf plugin + community.general.ldap_attrs: + dn: "cn={{ item[0] }}-to-{{ item[1] }},cn=replica,cn={{ auth_ldap_domain_ldap | replace(\"=\", \"\\=\") | replace(\",\", \"\\,\") }},cn=mapping tree,cn=config" + server_uri: "{{ auth_ldap_ansible_url }}" + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: exact + attributes: + nsds5replicatedattributelist: (objectclass=*) $ EXCLUDE memberof + when: (item[0] != item[1]) and (item[1] == ansible_fqdn) + with_cartesian: + - "{{ groups[auth_ldap_group] }}" + - "{{ groups[auth_ldap_group] }}" + notify: Restart dirsrv diff --git a/tasks/389-schema.yml b/tasks/389-schema.yml index a7e1dd9..6887633 100644 --- a/tasks/389-schema.yml +++ b/tasks/389-schema.yml @@ -1,38 +1,38 @@ --- - - name: Check whether {{ item.name }} schema has been imported - expect: - command: /bin/bash -c "ldapsearch -Z -x -W -D cn=Directory\ Manager -b cn=schema objectClasses | grep {{ item.checkattr }}" - responses: - (Enter LDAP Password): "{{ auth_ldap_admin_pwd }}" - no_log: true - register: check - failed_when: False - changed_when: False +- name: Check whether {{ item.name }} schema has been imported + ansible.builtin.expect: + command: /bin/bash -c "ldapsearch -Z -x -W -D cn=Directory\ Manager -b cn=schema objectClasses | grep {{ item.checkattr }}" + responses: + (Enter LDAP Password): "{{ auth_ldap_admin_pwd }}" + no_log: true + register: check + failed_when: false + changed_when: false - - name: Create ansible schema dir - become: True - file: - path: /etc/ldap/ansible - owner: root - group: root - mode: 0640 - state: directory +- name: Create ansible schema dir + become: true + ansible.builtin.file: + path: /etc/ldap/ansible + owner: root + group: root + mode: "0640" + state: directory - - name: Upload {{ item.name }} schema - become: True - copy: - src: "{{ item.file }}" - dest: "/etc/ldap/ansible/{{ item.file | basename }}" - owner: root - group: root - mode: 0640 - register: upload_schema +- name: Upload {{ item.name }} schema + become: true + ansible.builtin.copy: + src: "{{ item.file }}" + dest: "/etc/ldap/ansible/{{ item.file | basename }}" + owner: root + group: root + mode: "0640" + register: upload_schema - - name: Import {{ item.name }} schema - when: check.rc == 1 or upload_schema is changed - become: True - expect: - command: /bin/bash -c "/usr/bin/ldapmodify -Z -x -D cn=Directory\ Manager -W < /etc/ldap/ansible/{{ item.file | basename }}" - responses: - (Enter LDAP Password): "{{ auth_ldap_admin_pwd }}" - no_log: true +- name: Import {{ item.name }} schema + when: check.rc == 1 or upload_schema is changed + become: true + ansible.builtin.expect: + command: /bin/bash -c "/usr/bin/ldapmodify -Z -x -D cn=Directory\ Manager -W < /etc/ldap/ansible/{{ item.file | basename }}" + responses: + (Enter LDAP Password): "{{ auth_ldap_admin_pwd }}" + no_log: true diff --git a/tasks/389-setup.yml b/tasks/389-setup.yml index 0b9aa72..a5887b9 100644 --- a/tasks/389-setup.yml +++ b/tasks/389-setup.yml @@ -1,295 +1,306 @@ --- - - name: Check whether directory instance has already been created - become: True - stat: - path: "/etc/dirsrv/slapd-{{ auth_ldap_shortname }}" - register: linst - - - name: Ensure config directory has the right owner - # Turns out that if /etc/dirsrv is not owned by dirsrv as a group, slapd will simply segfault - become: True - file: - path: /etc/dirsrv - group: dirsrv - - - name: Generate setup file - become: True - when: not linst.stat.exists - template: - src: setup.inf.j2 - dest: /etc/dirsrv/setup.inf - owner: root - group: root - mode: 0600 - no_log: True - - - name: Install directory instance - become: True - when: not linst.stat.exists - command: dscreate from-file /etc/dirsrv/setup.inf - - - name: Check whether server cert is installed - become: True - shell: certutil -d "/etc/dirsrv/slapd-{{ auth_ldap_shortname }}" -L | grep -E '{{ ansible_fqdn }}|Server-Cert' - register: certsrvout - failed_when: False - changed_when: False - - - name: stop dirsrv - become: True - when: certsrvout.rc == 1 - service: - name: "dirsrv@{{ auth_ldap_shortname }}" - state: stopped - - - name: Load certificate store password - become: True - when: certsrvout.rc == 1 - slurp: - src: "/etc/dirsrv/slapd-{{ auth_ldap_shortname }}/pwdfile.txt" - register: pinout - no_log: True - - - name: Concat certificates - become: True - when: certsrvout.rc == 1 - command: 'openssl pkcs12 -export -out server.pfx -inkey {{ auth_ldap_ssl_key_path }} -in {{ auth_ldap_ssl_cert_path }} -certfile {{ auth_ldap_ssl_ca_path }} -passout pass:{{ pinout.content|b64decode }}' - args: - chdir: /etc/dirsrv - - - name: Install server certificate - become: True - when: certsrvout.rc == 1 - command: 'pk12util -i server.pfx -d"/etc/dirsrv/slapd-{{ auth_ldap_shortname }}" -K {{ pinout.content|b64decode }} -W {{ pinout.content|b64decode }} -name Server-Cert -n Server-Cert' - args: - chdir: /etc/dirsrv - notify: restart dirsrv - - # Depending on, I don't know, the state of the moon or something, pk12util - # will sometimes ignore the -n argument and name the cert after the CN. - # Depending on the state of the sun or something, 389-ds will deem to - # consider this being a valid certificate or not (the docs say that it only - # consideres certificates named after nsSSLPersonalitySSL, which would have - # been the CN when I wrote this, but the docs are definitely wrong). Fix - # this by always renaming the certificate to 'Server-Cert', forcing - # nsSSLPersonalitySSL to the same value and ignoring errors... - - name: Rename the server certificate in case pk12util decided to ignore it's arguments again - become: True - when: certsrvout.rc == 1 - command: 'certutil --rename -d/etc/dirsrv/slapd-{{ auth_ldap_shortname }} -n "{{ auth_ldap_ssl_cn }}" --new-n Server-Cert' - args: - chdir: /etc/dirsrv - notify: restart dirsrv - failed_when: False - - - name: Get CA certificate nickname - become: True - when: certsrvout.rc == 1 - shell: "certutil -L -d\"/etc/dirsrv/slapd-{{ auth_ldap_shortname }}\" | grep \"{{ auth_ldap_ssl_desc }}\" | sed -E 's/ .*//g'" - register: caout - - - name: Trust CA certificate for CA purposed - become: True - when: certsrvout.rc == 1 - command: 'certutil -M -d"/etc/dirsrv/slapd-{{ auth_ldap_shortname }}" -n "{{ caout.stdout }}" -t "CT,," -f /etc/dirsrv/slapd-{{ auth_ldap_shortname }}/pwdfile.txt' - notify: restart dirsrv - - - name: Remove setup files - become: True - file: - path: "/etc/dirsrv/{{ item }}" - state: absent - with_items: - - server.pfx - - setup.inf - - # If we installed a certificate, this will restart the server - - meta: flush_handlers - - - name: Configure certificate location - ldap_entry: - dn: "cn=RSA,cn=encryption,cn=config" - server_uri: "ldap://127.0.0.1" - objectClass: - - 'nsEncryptionModule' - - 'top' - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: present - attributes: - nsSSLPersonalitySSL: "Server-Cert" # Used to be the fqdn but got ignored sometimes... - nsSSLActivation: on - nsSSLToken: "internal (software)" - cn: RSA - notify: restart dirsrv - - - name: Configure SSL - ldap_attrs: - dn: "cn=encryption,cn=config" - server_uri: "ldap://127.0.0.1" - state: exact - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - attributes: - nsSSLClientAuth: "off" - nsSSL3: "off" - nsSSL2: "off" - nsSSLSessionTimeout: "0" - notify: restart dirsrv - - - name: Enable SSL - ldap_attrs: - dn: "cn=config" - server_uri: "ldap://127.0.0.1" - state: exact - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - attributes: - nsslapd-security: "on" - notify: restart dirsrv - - # If we changed the SSL config, this will restart the server and activate it - - meta: flush_handlers - - - name: Ensure that ldap config directory exists - become: True - when: auth_ldap_have_tls | bool - file: - path: /etc/ldap - state: directory - owner: root - group: root - mode: 0755 - - - name: Copy TLS CA to ldap config directory - become: True - when: auth_ldap_have_tls | bool - copy: - src: "{{ auth_ldap_ssl_ca_path_src }}" - dest: /etc/ldap/ca.pem - owner: root - group: root - mode: 0644 - remote_src: True - - - name: Configure TLS CA in ldap.conf - become: True - when: auth_ldap_have_tls | bool - template: - src: ldap.conf.j2 - dest: /etc/ldap/ldap.conf - owner: root - group: root - mode: 0644 - - - name: Set URL to SSL - when: auth_ldap_have_tls | bool - set_fact: - auth_ldap_ansible_url: "ldaps://{{ ansible_fqdn }}" - - - name: Actually create the BaseDN - ldap_entry: - dn: "{{ auth_ldap_domain_ldap }}" - objectClass: - - organization - - dcObject - - top - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - server_uri: "{{ auth_ldap_ansible_url }}" - attributes: - dc: "{{ auth_ldap_domain_suffix }}" - o: "{{ auth_ldap_domain_suffix|upper }}" - - - name: Configure LDAP containers - ldap_entry: - dn: "ou={{ item }},{{ auth_ldap_domain_ldap }}" - objectClass: organizationalUnit - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - server_uri: "{{ auth_ldap_ansible_url }}" - with_items: - - Users - - Groups - - TechnicalUsers - - - include_tasks: 389-schema.yml - tags: - - ldap - with_items: - - name: Kerberos - file: kerberos.ldif - checkattr: krbPrincipalName - - name: DNS - file: dns.ldif - checkattr: idnsTemplateObject - - name: Mail - file: mail.ldif - checkattr: postfixConfiguration - - - name: Configure LDAP service containers - ldap_entry: - dn: "ou={{ item }},ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" - objectClass: organizationalUnit - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - server_uri: "{{ auth_ldap_ansible_url }}" - with_items: "{{ auth_ldap_services }}" - - - name: Configure LDAP service bases - ldap_entry: - dn: "cn={{ item.name }},{{ auth_ldap_domain_ldap }}" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - objectClass: "{{ item.objectClass }}" - attributes: - cn: "{{ item.name }}" - with_items: "{{ auth_ldap_service_bases }}" - - - name: Assemble HAProxy certificates - when: auth_ldap_have_tls | bool - become: True - shell: cat /etc/dirsrv/{{ item }}.crt /etc/dirsrv/{{ item }}.key > /etc/dirsrv/{{ item }}.pem && chown root:root /etc/dirsrv/{{ item }}.pem && chmod 600 /etc/dirsrv/{{ item }}.pem - changed_when: False - with_items: - - server - - client - - - name: Add HAproxy dropin - when: auth_ldap_have_tls | bool - become: True - template: - src: haproxy-dropin.conf.j2 - dest: /etc/haproxy/conf.d/30-ldap.conf - owner: root - group: root - mode: 0644 - notify: restart haproxy - - - name: Enable Retro Changelog Plugin - ldap_attrs: - dn: "cn=Retro Changelog Plugin,cn=plugins,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: exact - attributes: - nsslapd-pluginEnabled: 'on' - nsslapd-attribute: 'nsuniqueid:targetUniqueId' - nsslapd-exclude-suffix: 'cn=config' - notify: restart dirsrv - - - name: Enable or disable Memberof Plugin - ldap_attrs: - dn: "cn=MemberOf Plugin,cn=plugins,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: exact - attributes: - nsslapd-pluginEnabled: "{% if auth_ldap_use_memberof_plugin %}on{% else %}off{% endif %}" - notify: restart dirsrv - - # If we changed the haproxy config, this will restart the server and activate it - - meta: flush_handlers +- name: Check whether directory instance has already been created + become: true + ansible.builtin.stat: + path: "/etc/dirsrv/slapd-{{ auth_ldap_shortname }}" + register: linst + +- name: Ensure config directory has the right owner + # Turns out that if /etc/dirsrv is not owned by dirsrv as a group, slapd will simply segfault + become: true + ansible.builtin.file: + path: /etc/dirsrv + group: dirsrv + +- name: Generate setup file + become: true + when: not linst.stat.exists + ansible.builtin.template: + src: setup.inf.j2 + dest: /etc/dirsrv/setup.inf + owner: root + group: root + mode: "0600" + no_log: true + +- name: Install directory instance + become: true + when: not linst.stat.exists + ansible.builtin.command: dscreate from-file /etc/dirsrv/setup.inf + +- name: Check whether server cert is installed + become: true + ansible.builtin.shell: set -o pipefail && certutil -d "/etc/dirsrv/slapd-{{ auth_ldap_shortname }}" -L | grep -E '{{ ansible_fqdn }}|Server-Cert' + register: certsrvout + failed_when: false + changed_when: false + +- name: Stop dirsrv + become: true + when: certsrvout.rc == 1 + ansible.builtin.service: + name: "dirsrv@{{ auth_ldap_shortname }}" + state: stopped + +- name: Load certificate store password + become: true + when: certsrvout.rc == 1 + slurp: + src: "/etc/dirsrv/slapd-{{ auth_ldap_shortname }}/pwdfile.txt" + register: pinout + no_log: true + +- name: Concat certificates + become: true + when: certsrvout.rc == 1 + ansible.builtin.command: 'openssl pkcs12 -export -out server.pfx -inkey {{ auth_ldap_ssl_key_path }} -in {{ auth_ldap_ssl_cert_path }} -certfile {{ auth_ldap_ssl_ca_path }} -passout pass:{{ pinout.content | b64decode }}' + args: + chdir: /etc/dirsrv + +- name: Install server certificate + become: true + when: certsrvout.rc == 1 + ansible.builtin.command: 'pk12util -i server.pfx -d"/etc/dirsrv/slapd-{{ auth_ldap_shortname }}" -K {{ pinout.content | b64decode }} -W {{ pinout.content | b64decode }} -name Server-Cert -n Server-Cert' + args: + chdir: /etc/dirsrv + notify: Restart dirsrv + + # Depending on, I don't know, the state of the moon or something, pk12util + # will sometimes ignore the -n argument and name the cert after the CN. + # Depending on the state of the sun or something, 389-ds will deem to + # consider this being a valid certificate or not (the docs say that it only + # consideres certificates named after nsSSLPersonalitySSL, which would have + # been the CN when I wrote this, but the docs are definitely wrong). Fix + # this by always renaming the certificate to 'Server-Cert', forcing + # nsSSLPersonalitySSL to the same value and ignoring errors... +- name: Rename the server certificate in case pk12util decided to ignore it's arguments again + become: true + when: certsrvout.rc == 1 + ansible.builtin.command: 'certutil --rename -d/etc/dirsrv/slapd-{{ auth_ldap_shortname }} -n "{{ auth_ldap_ssl_cn }}" --new-n Server-Cert' + args: + chdir: /etc/dirsrv + notify: Restart dirsrv + failed_when: false + +- name: Get CA certificate nickname + become: true + when: certsrvout.rc == 1 + ansible.builtin.shell: "set -o pipefail && certutil -L -d\"/etc/dirsrv/slapd-{{ auth_ldap_shortname }}\" | grep \"{{ auth_ldap_ssl_desc }}\" | sed -E 's/ .*//g'" + register: caout + +- name: Trust CA certificate for CA purposed + become: true + when: certsrvout.rc == 1 + ansible.builtin.command: 'certutil -M -d"/etc/dirsrv/slapd-{{ auth_ldap_shortname }}" -n "{{ caout.stdout }}" -t "CT,," -f /etc/dirsrv/slapd-{{ auth_ldap_shortname }}/pwdfile.txt' + notify: Restart dirsrv + +- name: Remove setup files + become: true + ansible.builtin.file: + path: "/etc/dirsrv/{{ item }}" + state: absent + with_items: + - server.pfx + - setup.inf + +# If we installed a certificate, this will restart the server +- name: Flush handlers + ansible.builtin.meta: flush_handlers + +- name: Configure certificate location + community.general.ldap_entry: + dn: "cn=RSA,cn=encryption,cn=config" + server_uri: "ldap://127.0.0.1" + objectClass: + - 'nsEncryptionModule' + - 'top' + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: present + attributes: + nsSSLPersonalitySSL: "Server-Cert" # Used to be the fqdn but got ignored sometimes... + nsSSLActivation: "on" + nsSSLToken: "internal (software)" + cn: RSA + notify: Restart dirsrv + +- name: Configure SSL + community.general.ldap_attrs: + dn: "cn=encryption,cn=config" + server_uri: "ldap://127.0.0.1" + state: exact + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + attributes: + nsSSLClientAuth: "off" + nsSSL3: "off" + nsSSL2: "off" + nsSSLSessionTimeout: "0" + notify: Restart dirsrv + +- name: Enable SSL + community.general.ldap_attrs: + dn: "cn=config" + server_uri: "ldap://127.0.0.1" + state: exact + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + attributes: + nsslapd-security: "on" + notify: Restart dirsrv + +# If we changed the SSL config, this will restart the server and activate it +- name: Flush handlers + ansible.builtin.meta: flush_handlers + +- name: Ensure that ldap config directory exists + become: true + when: auth_ldap_have_tls | bool + ansible.builtin.file: + path: /etc/ldap + state: directory + owner: root + group: root + mode: "0755" + +- name: Copy TLS CA to ldap config directory + become: true + when: auth_ldap_have_tls | bool + ansible.builtin.copy: + src: "{{ auth_ldap_ssl_ca_path_src }}" + dest: /etc/ldap/ca.pem + owner: root + group: root + mode: "0644" + remote_src: true + +- name: Configure TLS CA in ldap.conf + become: true + when: auth_ldap_have_tls | bool + ansible.builtin.template: + src: ldap.conf.j2 + dest: /etc/ldap/ldap.conf + owner: root + group: root + mode: "0644" + +- name: Set URL to SSL + when: auth_ldap_have_tls | bool + ansible.builtin.set_fact: + auth_ldap_ansible_url: "ldaps://{{ ansible_fqdn }}" + +- name: Actually create the BaseDN + community.general.ldap_entry: + dn: "{{ auth_ldap_domain_ldap }}" + objectClass: + - organization + - dcObject + - top + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + server_uri: "{{ auth_ldap_ansible_url }}" + attributes: + dc: "{{ auth_ldap_domain_suffix }}" + o: "{{ auth_ldap_domain_suffix | upper }}" + +- name: Configure LDAP containers + community.general.ldap_entry: + dn: "ou={{ item }},{{ auth_ldap_domain_ldap }}" + objectClass: organizationalUnit + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + server_uri: "{{ auth_ldap_ansible_url }}" + with_items: + - Users + - Groups + - TechnicalUsers + +- name: Create LDAP schemata + ansible.builtin.include_tasks: 389-schema.yml + tags: + - ldap + with_items: + - name: Kerberos + file: kerberos.ldif + checkattr: krbPrincipalName + - name: DNS + file: dns.ldif + checkattr: idnsTemplateObject + - name: Mail + file: mail.ldif + checkattr: postfixConfiguration + +- name: Apply additional ldif + ansible.builtin.include_tasks: 389-schema.yml + tags: + - ldap + with_items: "{{ auth_ldap_additional_schema }}" + when: auth_ldap_additional_schema is defined + +- name: Configure LDAP service containers + community.general.ldap_entry: + dn: "ou={{ item }},ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" + objectClass: organizationalUnit + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + server_uri: "{{ auth_ldap_ansible_url }}" + with_items: "{{ auth_ldap_services }}" + +- name: Configure LDAP service bases + community.general.ldap_entry: + dn: "cn={{ item.name }},{{ auth_ldap_domain_ldap }}" + server_uri: "{{ auth_ldap_ansible_url }}" + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + objectClass: "{{ item.objectClass }}" + attributes: + cn: "{{ item.name }}" + with_items: "{{ auth_ldap_service_bases }}" + +- name: Assemble HAProxy certificates + when: auth_ldap_have_tls | bool + become: true + ansible.builtin.shell: cat /etc/dirsrv/{{ item }}.crt /etc/dirsrv/{{ item }}.key > /etc/dirsrv/{{ item }}.pem && chown root:root /etc/dirsrv/{{ item }}.pem && chmod 600 /etc/dirsrv/{{ item }}.pem + changed_when: false + with_items: + - server + - client + +- name: Add HAproxy dropin + when: auth_ldap_have_tls | bool + become: true + ansible.builtin.template: + src: haproxy-dropin.conf.j2 + dest: /etc/haproxy/conf.d/30-ldap.conf + owner: root + group: root + mode: "0644" + notify: Restart haproxy + +- name: Enable Retro Changelog Plugin + community.general.ldap_attrs: + dn: "cn=Retro Changelog Plugin,cn=plugins,cn=config" + server_uri: "{{ auth_ldap_ansible_url }}" + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: exact + attributes: + nsslapd-pluginEnabled: 'on' + nsslapd-attribute: 'nsuniqueid:targetUniqueId' + nsslapd-exclude-suffix: 'cn=config' + notify: Restart dirsrv + +- name: Enable or disable Memberof Plugin + community.general.ldap_attrs: + dn: "cn=MemberOf Plugin,cn=plugins,cn=config" + server_uri: "{{ auth_ldap_ansible_url }}" + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: exact + attributes: + nsslapd-pluginEnabled: "{% if auth_ldap_use_memberof_plugin %}on{% else %}off{% endif %}" + notify: Restart dirsrv + +# If we changed the haproxy config, this will restart the server and activate it +- name: Flush handlers + meta: flush_handlers diff --git a/tasks/content.yml b/tasks/content.yml index 920ffba..5096d98 100644 --- a/tasks/content.yml +++ b/tasks/content.yml @@ -1,28 +1,20 @@ --- - - name: Create LDAP user - run_once: true - ldap_entry: - dn: "uid={{ item.id }},ou=Users,{{ auth_ldap_domain_ldap }}" - server_uri: "{{ auth_ldap_ansible_url }}" - objectClass: "{{ auth_ldap_user_objectclasses }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: present - attributes: - uid: "{{ item.id }}" - uidNumber: "{{ item.uid }}" - gidNumber: "{{ item.gid }}" - homeDirectory: "/home/{{ item.id }}" - sn: "{{ item.sn }}" - givenName: "{{ item.givenName }}" - mail: "{{ item.mail }}" - cn: "{{ item.name }}" - register: userchanged - - - name: Kerberize LDAP user - run_once: true - when: userchanged.changed - become: True - command: kadmin.local addprinc -randkey -x dn="uid={{ item.id }},ou=Users,{{ auth_ldap_domain_ldap }}" +requires_preauth -allow_svr "{{ item.id }}" - tags: - - skip_ansible_lint +- name: Create LDAP user + run_once: true + community.general.ldap_entry: + dn: "uid={{ item.id }},ou=Users,{{ auth_ldap_domain_ldap }}" + server_uri: "{{ auth_ldap_ansible_url }}" + objectClass: "{{ auth_ldap_user_objectclasses }}" + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: present + attributes: + uid: "{{ item.id }}" + uidNumber: "{{ item.uid }}" + gidNumber: "{{ item.gid }}" + homeDirectory: "/home/{{ item.id }}" + sn: "{{ item.sn }}" + givenName: "{{ item.givenName }}" + mail: "{{ item.mail }}" + cn: "{{ item.name }}" + register: userchanged diff --git a/tasks/kerberos.yml b/tasks/kerberos.yml deleted file mode 100644 index 1fa4f82..0000000 --- a/tasks/kerberos.yml +++ /dev/null @@ -1,207 +0,0 @@ ---- - - name: Configure kerberos client settings - become: True - template: - src: krb5.conf.j2 - dest: /etc/krb5.conf - owner: root - group: root - mode: 0644 - notify: restart kdc - - - name: Store kerberos LDAP credentials - become: True - expect: - command: "kdb5_ldap_util stashsrvpw -f /etc/krb5kdc/ldap.cred cn=krbbind,ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" - creates: /etc/krb5kdc/ldap.cred - responses: - (cn\=krbbind): "{{ auth_kerberos_ldap_password }}" - - - name: Fix kerberos LDAP credentials permissions - become: True - file: - path: /etc/krb5kdc/ldap.cred - owner: root - group: root - mode: 0640 - - - name: Configure KDC - become: True - template: - src: kdc.conf.j2 - dest: /etc/krb5kdc/kdc.conf - owner: root - group: root - mode: 0640 - notify: restart kdc - - - name: Figure out whether realm has been created yet - expect: - command: /bin/bash -c "ldapsearch -Z -x -W -D cn=Directory\ Manager -b {{ auth_ldap_domain_ldap }} cn=Kerberos | grep dn:" - responses: - (Enter LDAP Password): "{{ auth_ldap_admin_pwd }}" - no_log: true - register: krbrealmcheck - failed_when: False - changed_when: False - - - name: Create Kerberos realm - run_once: true - become: True - when: krbrealmcheck.rc == 1 - expect: - command: kdb5_ldap_util -D "cn=Directory Manager" create -subtrees "ou=Users,{{ auth_ldap_domain_ldap }}:ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" -r "{{ auth_ldap_domain|upper }}" -s - responses: - (cn\=Directory\ Manager): "{{ auth_ldap_admin_pwd }}" - (database master key): "{{ auth_kerberos_database_master_key }}" - - - name: Configure LDAP ACLs (Kerberos) - ldap_attrs: - dn: "{{ item.target }}" - bind_dn: "cn=Directory Manager" - bind_pw: '{{ auth_ldap_admin_pwd }}' - server_uri: "{{ auth_ldap_ansible_url }}" - attributes: - aci: "{{ item.acls }}" - state: exact - when: item.target == "cn=Kerberos,{{ auth_ldap_domain_ldap }}" - with_items: "{{ auth_ldap_permissions }}" - tags: - - skip_ansible_lint - - - name: Fetch master database secret to control node - when: krbrealmcheck.rc == 1 - become: True - fetch: - src: "/etc/krb5kdc/.k5.{{ auth_ldap_domain|upper }}" - dest: "fetch/krb5secret" - flat: yes - validate_checksum: yes - fail_on_missing: no - failed_when: False - - - name: Upload master database secret to kerberos nodes - when: krbrealmcheck.rc == 1 - become: True - copy: - src: "fetch/krb5secret" - dest: "/etc/krb5kdc/.k5.{{ auth_ldap_domain|upper }}" - owner: root - group: root - mode: 0600 - notify: restart kdc - - - meta: flush_handlers - - - name: Create default ticket policy - when: krbrealmcheck.rc == 1 - run_once: True - command: kadmin.local addpol -minlength 8 -minclasses 3 -maxfailure 3 -failurecountinterval "60 sec" -lockoutduration "600 sec" default - - - name: Create anonymous prinicpal for PKINIT/FAST - when: krbrealmcheck.rc == 1 - run_once: True - command: kadmin.local -q 'addprinc -randkey WELLKNOWN/ANONYMOUS' - - - name: Grant admin permissions to specific principals - become: True - when: auth_kerberos_admin_privs != [] - template: - src: kadm5.acl.j2 - dest: /etc/krb5kdc/kadm5.acl - owner: root - group: root - mode: 0644 - notify: - - restart kdc - - restart kadmind - - - include_tasks: serviceaccount.yml - with_items: "{{ auth_ldap_service_accounts }}" - - - name: Reconfigure 389ds to support GSSAPI - become: True - template: - src: dirsrv.j2 - dest: /etc/default/dirsrv - owner: root - group: root - mode: 0644 - notify: restart dirsrv - - - name: Remove default SASL Kerberos mapping entries - ldap_entry: - dn: "cn={{ item }},cn=mapping,cn=sasl,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: absent - with_items: - - Kerberos uid mapping - - # Quote: "There is no way to specify the order that mappings are processed. - # However, there is a way to control how SASL mappings are processed: the - # name. The Directory Server processes SASL mappings in reverse ASCII order." - - name: Add normal people SASL UID mapping - ldap_entry: - dn: "cn=User Map,cn=mapping,cn=sasl,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: present - objectClass: - - top - - nsSaslMapping - attributes: - cn: User Map - nsSaslMapRegexString: '([^/]*)@(.*)\.(.*)' - nsSaslMapBaseDNTemplate: uid=\1,ou=Users,dc=\2,dc=\3 - nsSaslMapFilterTemplate: (objectclass=posixAccount) - - - name: Add service account SASL UID mapping - ldap_entry: - dn: "cn=z_Service Map,cn=mapping,cn=sasl,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: present - objectClass: - - top - - nsSaslMapping - attributes: # Hint: For reasons unknown, 389ds drops the domain on these tickets... - nsSaslMapRegexString: ([^/]+)/(.+) - cn: z_Service Map - nsSaslMapBaseDNTemplate: "uid=\\2,ou=\\1,ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" - nsSaslMapFilterTemplate: (objectclass=*) - - - name: Add PAM passthrough auth for normal users - ldap_attrs: - dn: "cn=PAM Pass Through Auth,cn=plugins,cn=config" - server_uri: "{{ auth_ldap_ansible_url }}" - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: exact - attributes: - nsslapd-pluginenabled: 'on' - pamMissingSuffix: ERROR - pamExcludeSuffix: cn=config - pamIncludeSuffix: "ou=Users,{{ auth_ldap_domain_ldap }}" - pamIDMapMethod: 'ENTRY' - pamIDAttr: uid - pamFallback: 'FALSE' - pamSecure: 'TRUE' - pamService: ldapkrb - notify: restart dirsrv - - - name: Configure ldapkrb pam service - become: True - when: auth_ldap_store_pam | bool - template: - src: ldapkrb.j2 - dest: /etc/pam.d/ldapkrb - owner: root - group: root - mode: 0644 - - # If we changed the config, restart the server as we might need GSSAPI... - - meta: flush_handlers diff --git a/tasks/main.yml b/tasks/main.yml index f55c452..8a690e3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,67 +1,54 @@ --- - - name: Install software - become: True - apt: - state: present - update_cache: yes - cache_valid_time: 1800 - name: - - python3-ldap - - krb5-kdc-ldap - - krb5-kdc - - krb5-admin-server - - krb5-pkinit - - sasl2-bin - - libsasl2-modules-gssapi-mit - - 389-ds-base - - libnss3-tools - - libldap-common - - libpam-krb5 - - python3-pexpect - tags: - - ldap - - kerberos - - - import_tasks: variable-initialisation.yml - tags: - - ldap - - - import_tasks: 389-setup.yml - tags: - - ldap - - - import_tasks: 389-replication.yml - tags: - - ldap - - - import_tasks: 389-acl.yml - tags: - - ldap - - - include_tasks: kerberos.yml - tags: - - kerberos - - - name: Configure LDAP users - include_tasks: content.yml - with_items: - - "{{ auth_ldap_users }}" - tags: - - ldap - - kerberos - - - name: Apply additional ldif - include_tasks: 389-schema.yml - tags: - - ldap - with_items: "{{ auth_ldap_additional_schema }}" - when: auth_ldap_additional_schema is defined - - - name: Apply additional indexes - include_tasks: 389-index.yml - tags: - - ldap - with_items: "{{ auth_ldap_eq_indexes }}" - when: auth_ldap_eq_indexes is defined - - - meta: flush_handlers +- name: Install software + become: true + ansible.builtin.apt: + state: present + update_cache: true + cache_valid_time: 1800 + name: + - python3-ldap + - sasl2-bin + - libsasl2-modules-gssapi-mit + - 389-ds-base + - libnss3-tools + - libldap-common + - python3-pexpect + tags: + - ldap + +- name: Initialise variables + ansible.builtin.import_tasks: variable-initialisation.yml + tags: + - ldap + +- name: Setup dirsrv instance + ansible.builtin.import_tasks: 389-setup.yml + tags: + - ldap + +- name: Setup replication + ansible.builtin.import_tasks: 389-replication.yml + tags: + - ldap + +- name: Setup ACLs + ansible.builtin.import_tasks: 389-acl.yml + tags: + - ldap + +- name: Configure LDAP users + ansible.builtin.include_tasks: content.yml + with_items: + - "{{ auth_ldap_users }}" + tags: + - ldap + +- name: Apply additional indexes + ansible.builtin.include_tasks: 389-index.yml + tags: + - ldap + with_items: "{{ auth_ldap_eq_indexes }}" + when: auth_ldap_eq_indexes is defined + +- name: Flush handlers + ansible.builtin.meta: flush_handlers diff --git a/tasks/serviceaccount.yml b/tasks/serviceaccount.yml index 8d79737..fc7ccc8 100644 --- a/tasks/serviceaccount.yml +++ b/tasks/serviceaccount.yml @@ -1,51 +1,51 @@ --- - - name: Create LDAP service user - ldap_entry: - dn: "uid={{ ansible_fqdn }},ou={{ item.service }},ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" - server_uri: "{{ auth_ldap_ansible_url }}" - objectClass: - - top - - inetOrgPerson - bind_dn: "cn=Directory Manager" - bind_pw: "{{ auth_ldap_admin_pwd }}" - state: present - attributes: - uid: "{{ ansible_fqdn }}" - cn: "{{ item.service }} on {{ ansible_fqdn }}" - sn: "Serviceaccount" - register: userchanged +- name: Create LDAP service user + community.general.ldap_entry: + dn: "uid={{ ansible_fqdn }},ou={{ item.service }},ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" + server_uri: "{{ auth_ldap_ansible_url }}" + objectClass: + - top + - inetOrgPerson + bind_dn: "cn=Directory Manager" + bind_pw: "{{ auth_ldap_admin_pwd }}" + state: present + attributes: + uid: "{{ ansible_fqdn }}" + cn: "{{ item.service }} on {{ ansible_fqdn }}" + sn: "Serviceaccount" + register: userchanged - - name: Kerberize LDAP user - when: userchanged.changed - become: True - command: kadmin.local addprinc -randkey -x dn="uid={{ ansible_fqdn }},ou={{ item.service }},ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" +requires_preauth "{{ item.service }}/{{ ansible_fqdn }}@{{ auth_ldap_domain|upper }}" - tags: - - skip_ansible_lint +- name: Kerberize LDAP user + when: userchanged.changed + become: true + ansible.builtin.command: kadmin.local addprinc -randkey -x dn="uid={{ ansible_fqdn }},ou={{ item.service }},ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" +requires_preauth "{{ item.service }}/{{ ansible_fqdn }}@{{ auth_ldap_domain|upper }}" + tags: + - skip_ansible_lint - - name: Check whether keytab exists - become: True - stat: - path: "{{ item.keytab }}" - register: ktstat +- name: Check whether keytab exists + become: true + ansible.builtin.stat: + path: "{{ item.keytab }}" + register: ktstat - - name: Check whether keytab contains service user credentials - become: True - when: ktstat.stat.exists - shell: "klist -k {{ item.keytab|quote }} | grep {{ item.service }}/{{ ansible_fqdn }}@{{ auth_ldap_domain|upper }}" - register: ktlist - failed_when: False - changed_when: False +- name: Check whether keytab contains service user credentials + become: true + when: ktstat.stat.exists + ansible.builtin.shell: "set -o pipefail && klist -k {{ item.keytab | quote }} | grep {{ item.service }}/{{ ansible_fqdn }}@{{ auth_ldap_domain | upper }}" + register: ktlist + failed_when: false + changed_when: false - - name: Export LDAP service user keytab - when: (item.keytab is defined) and ((not ktstat.stat.exists) or (ktlist.rc != 0)) - become: True - command: "kadmin.local ktadd -k {{ item.keytab }} {{ item.service }}/{{ ansible_fqdn }}@{{ auth_ldap_domain|upper }}" +- name: Export LDAP service user keytab + when: (item.keytab is defined) and ((not ktstat.stat.exists) or (ktlist.rc != 0)) + become: true + ansible.builtin.command: "kadmin.local ktadd -k {{ item.keytab }} {{ item.service }}/{{ ansible_fqdn }}@{{ auth_ldap_domain | upper }}" - - name: Set keytab permissions - when: (item.keytab is defined) - become: True - file: - path: "{{ item.keytab }}" - owner: "{{ item.ktowner }}" - group: "{{ item.ktgroup }}" - mode: "{{ item.ktmode }}" +- name: Set keytab permissions + when: (item.keytab is defined) + become: true + ansible.builtin.file: + path: "{{ item.keytab }}" + owner: "{{ item.ktowner }}" + group: "{{ item.ktgroup }}" + mode: "{{ item.ktmode }}" diff --git a/tasks/variable-initialisation.yml b/tasks/variable-initialisation.yml index 482b2aa..14ee370 100644 --- a/tasks/variable-initialisation.yml +++ b/tasks/variable-initialisation.yml @@ -1,5 +1,5 @@ --- - - name: Add inetUser to system users - set_fact: - auth_ldap_user_objectclasses: "{{ auth_ldap_user_objectclasses + ['inetUser'] }}" +- name: Add inetUser to system users + ansible.builtin.set_fact: + auth_ldap_user_objectclasses: "{{ auth_ldap_user_objectclasses + ['inetUser'] }}" diff --git a/templates/kadm5.acl.j2 b/templates/kadm5.acl.j2 deleted file mode 100644 index fdc4a84..0000000 --- a/templates/kadm5.acl.j2 +++ /dev/null @@ -1,3 +0,0 @@ -{% for entry in auth_kerberos_admin_privs %} -{{ entry.principal }} {{ entry.privileges }} {{ entry.target }} -{% endfor %} diff --git a/templates/kdc.conf.j2 b/templates/kdc.conf.j2 deleted file mode 100644 index 7ce2d93..0000000 --- a/templates/kdc.conf.j2 +++ /dev/null @@ -1,32 +0,0 @@ -[kdcdefaults] - kdc_ports = 749,88 - -[dbmodules] - {{ auth_ldap_domain|upper }}-LDAP = { - db_library = kldap - db_module_dir = /usr/lib/x86_64-linux-gnu/krb5/plugins/kdb - ldap_kdc_dn = "cn=krbbind,ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" - ldap_kadmind_dn = "cn=krbbind,ou=TechnicalUsers,{{ auth_ldap_domain_ldap }}" - ldap_service_password_file = /etc/krb5kdc/ldap.cred - ldap_kerberos_container_dn = "cn=Kerberos,{{ auth_ldap_domain_ldap }}" - ldap_servers = ldap://127.0.0.1:389{% for item in groups[auth_ldap_group] %}{% if hostvars[item]['ansible_fqdn'] != ansible_fqdn %} ldap://127.0.0.1:{{ 60389 + hostvars[item]['auth_ldap_server_id'] }}{% endif %}{% endfor %} - - ldap_conns_per_server = 5 - unlockiter = true - } - -[realms] - {{ auth_ldap_domain|upper }} = { - kdc_port = 88 - kdc_tcp_port = 88 - kadmind_port = 749 - max_life = 6h 0m 0s - max_renewable_life = 3d 0h 0m 0s - master_key_type = aes256-cts-hmac-sha384-192 - supported_enctypes = {{ auth_kerberos_enctypes }} - database_module = {{ auth_ldap_domain|upper }}-LDAP - restrict_anonymous_to_tgt = true - des_crc_session_supported = false - default_principal_flags = +preauth - pkinit_identity = FILE:/etc/krb5kdc/server.crt,/etc/krb5kdc/server.key - } diff --git a/templates/krb5.conf.j2 b/templates/krb5.conf.j2 deleted file mode 100644 index 56ce688..0000000 --- a/templates/krb5.conf.j2 +++ /dev/null @@ -1,36 +0,0 @@ -[libdefaults] - default_realm = {{ auth_ldap_domain|upper }} - - kdc_timesync = 1 - ccache_type = 4 - forwardable = true - proxiable = true - # Require principals to be listed in .k5login in order to allow login - # iff that file exists - k5login_authoritative = true - allow_weak_crypto = false - permitted_enctypes = {{ auth_kerberos_enctypes }} - default_tkt_enctypes = {{ auth_kerberos_enctypes }} - default_tgs_enctypes = {{ auth_kerberos_enctypes }} - spake_preauth_groups = {{ auth_kerberos_curves }} - # gokrb5 chokes without the next line - dns_lookup_kdc = true -{% if auth_kerberos_fixed_preauth != -1 %} - # gokrb5 also chokes without the next line - preferred_preauth_types = {{ auth_kerberos_fixed_preauth }} -{% endif %} - -[realms] - {{ auth_ldap_domain|upper }} = { - pkinit_anchors = FILE:/etc/ldap/ca.pem - admin_server = {{ ansible_fqdn }} -{% for host in groups[auth_ldap_group] %} - pkinit_kdc_hostname = {{ hostvars[host]['ansible_fqdn'] }} -{% endfor %} - } - -[domain_realm] - .{{ auth_ldap_domain }} = {{ auth_ldap_domain|upper }} -{% for domain in auth_ldap_domain_subdomains %} - .{{ domain|lower }} = {{ auth_ldap_domain|upper }} -{% endfor %} diff --git a/templates/ldapkrb.j2 b/templates/ldapkrb.j2 deleted file mode 100644 index 4e605ac..0000000 --- a/templates/ldapkrb.j2 +++ /dev/null @@ -1,5 +0,0 @@ -# PAM config for auth passthrough from LDAP to Kerberos -auth required pam_krb5.so ignore_k5login -session required pam_krb5.so ignore_k5login -account required pam_krb5.so ignore_k5login -password required pam_krb5.so ignore_k5login