mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-08-29 15:06:26 +02:00
Shortened service- to svc-
This commit is contained in:
34
roles/svc-openldap/tasks/add_user_objects.yml
Normal file
34
roles/svc-openldap/tasks/add_user_objects.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
- name: Gather all users with their current objectClass list
|
||||
community.general.ldap_search:
|
||||
server_uri: "{{ ldap_server_uri }}"
|
||||
bind_dn: "{{ ldap.dn.administrator.data }}"
|
||||
bind_pw: "{{ ldap.bind_credential }}"
|
||||
dn: "{{ ldap.dn.ou.users }}"
|
||||
scope: subordinate
|
||||
filter: "{{ ldap.filters.users.all }}"
|
||||
attrs:
|
||||
- dn
|
||||
- objectClass
|
||||
- "{{ ldap.user.attributes.id }}"
|
||||
register: ldap_users_with_classes
|
||||
|
||||
- name: Add only missing auxiliary classes
|
||||
community.general.ldap_attrs:
|
||||
server_uri: "{{ ldap_server_uri }}"
|
||||
bind_dn: "{{ ldap.dn.administrator.data }}"
|
||||
bind_pw: "{{ ldap.bind_credential }}"
|
||||
dn: "{{ item.dn }}"
|
||||
attributes:
|
||||
objectClass: "{{ missing_auxiliary }}"
|
||||
state: present
|
||||
async: 60
|
||||
poll: 0
|
||||
loop: "{{ ldap_users_with_classes.results }}"
|
||||
loop_control:
|
||||
label: "{{ item.dn }}"
|
||||
vars:
|
||||
missing_auxiliary: >-
|
||||
{{ (ldap.user.objects.auxiliary.values() | list)
|
||||
| difference(item.objectClass | default([]))
|
||||
}}
|
||||
when: missing_auxiliary | length > 0
|
11
roles/svc-openldap/tasks/create_ldif_files.yml
Normal file
11
roles/svc-openldap/tasks/create_ldif_files.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
- name: "Create LDIF files at {{ ldif_host_path }}{{ folder }}"
|
||||
template:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ ldif_host_path }}{{ folder }}/{{ item | basename | regex_replace('\\.j2$', '') }}"
|
||||
mode: '770'
|
||||
loop: >-
|
||||
{{
|
||||
lookup('fileglob', role_path ~ '/templates/ldif/' ~ folder ~ '/*.j2', wantlist=True)
|
||||
| sort
|
||||
}}
|
||||
notify: "Import {{ folder }} LDIF files"
|
124
roles/svc-openldap/tasks/main.yml
Normal file
124
roles/svc-openldap/tasks/main.yml
Normal file
@@ -0,0 +1,124 @@
|
||||
---
|
||||
- name: "include docker-compose role"
|
||||
include_role:
|
||||
name: docker-compose
|
||||
|
||||
- name: Create {{domains | get_domain(application_id)}}.conf if LDAP is exposed to internet
|
||||
template:
|
||||
src: "nginx.stream.conf.j2"
|
||||
dest: "{{nginx.directories.streams}}{{domains | get_domain(application_id)}}.conf"
|
||||
notify: restart nginx
|
||||
when: applications[application_id].network.public | bool
|
||||
|
||||
- name: Remove {{domains | get_domain(application_id)}}.conf if LDAP is not exposed to internet
|
||||
file:
|
||||
path: "{{ nginx.directories.streams }}{{ domains | get_domain(application_id) }}.conf"
|
||||
state: absent
|
||||
when: not applications[application_id].network.public | bool
|
||||
|
||||
- name: create docker network for LDAP, so that other applications can access it
|
||||
docker_network:
|
||||
name: central_ldap
|
||||
state: present
|
||||
ipam_config:
|
||||
- subnet: "{{ networks.local.central_ldap.subnet }}"
|
||||
|
||||
- name: "Reset LDAP admin passwords"
|
||||
include_tasks: reset_admin_passwords.yml
|
||||
when: applications[application_id].network.local
|
||||
|
||||
- name: "create directory {{ldif_host_path}}{{item}}"
|
||||
file:
|
||||
path: "{{ldif_host_path}}{{item}}"
|
||||
state: directory
|
||||
mode: 0755
|
||||
loop: "{{ldif_types}}"
|
||||
|
||||
- name: "Process all LDIF types"
|
||||
include_tasks: create_ldif_files.yml
|
||||
loop:
|
||||
- configuration
|
||||
loop_control:
|
||||
loop_var: folder
|
||||
|
||||
- name: flush LDIF handlers
|
||||
meta: flush_handlers
|
||||
|
||||
- name: install python-ldap
|
||||
community.general.pacman:
|
||||
name:
|
||||
- python-ldap
|
||||
state: present
|
||||
|
||||
- name: "Include Nextcloud Schema"
|
||||
include_tasks: schemas/nextcloud.yml
|
||||
|
||||
- name: "Include openssh-lpk Schema"
|
||||
include_tasks: schemas/openssh_lpk.yml
|
||||
|
||||
###############################################################################
|
||||
# 1) Create the LDAP entry if it does not yet exist
|
||||
###############################################################################
|
||||
- name: Ensure LDAP users exist
|
||||
community.general.ldap_entry:
|
||||
dn: "{{ ldap.user.attributes.id }}={{ item.key }},{{ ldap.dn.ou.users }}"
|
||||
server_uri: "{{ ldap_server_uri }}"
|
||||
bind_dn: "{{ ldap.dn.administrator.data }}"
|
||||
bind_pw: "{{ ldap.bind_credential }}"
|
||||
objectClass: "{{ ldap.user.objects.structural }}"
|
||||
attributes:
|
||||
uid: "{{ item.value.username }}"
|
||||
sn: "{{ item.value.sn | default(item.key) }}"
|
||||
cn: "{{ item.value.cn | default(item.key) }}"
|
||||
userPassword: "{SSHA}{{ item.value.password }}"
|
||||
loginShell: /bin/bash
|
||||
homeDirectory: "/home/{{ item.key }}"
|
||||
uidNumber: "{{ item.value.uid | int }}"
|
||||
gidNumber: "{{ item.value.gid | int }}"
|
||||
state: present # ↳ creates but never updates
|
||||
async: 60
|
||||
poll: 0
|
||||
loop: "{{ users | dict2items }}"
|
||||
loop_control:
|
||||
label: "{{ item.key }}"
|
||||
|
||||
###############################################################################
|
||||
# 2) Keep the objectClass list AND the mail attribute up-to-date
|
||||
###############################################################################
|
||||
- name: Ensure required objectClass values and mail address are present
|
||||
community.general.ldap_attrs:
|
||||
dn: "{{ ldap.user.attributes.id }}={{ item.key }},{{ ldap.dn.ou.users }}"
|
||||
server_uri: "{{ ldap_server_uri }}"
|
||||
bind_dn: "{{ ldap.dn.administrator.data }}"
|
||||
bind_pw: "{{ ldap.bind_credential }}"
|
||||
attributes:
|
||||
objectClass: "{{ ldap.user.objects.structural }}"
|
||||
mail: "{{ item.value.email }}"
|
||||
state: exact
|
||||
async: 60
|
||||
poll: 0
|
||||
loop: "{{ users | dict2items }}"
|
||||
loop_control:
|
||||
label: "{{ item.key }}"
|
||||
|
||||
- name: "Ensure container for application roles exists"
|
||||
community.general.ldap_entry:
|
||||
dn: "{{ ldap.dn.ou.roles }}"
|
||||
server_uri: "{{ ldap_server_uri }}"
|
||||
bind_dn: "{{ ldap.dn.administrator.data }}"
|
||||
bind_pw: "{{ ldap.bind_credential }}"
|
||||
objectClass: organizationalUnit
|
||||
attributes:
|
||||
ou: roles
|
||||
description: Container for application access profiles
|
||||
state: present
|
||||
|
||||
- name: "Process all LDIF types"
|
||||
include_tasks: create_ldif_files.yml
|
||||
loop:
|
||||
- data
|
||||
loop_control:
|
||||
loop_var: folder
|
||||
|
||||
- name: "Add Objects to all users"
|
||||
include_tasks: add_user_objects.yml
|
57
roles/svc-openldap/tasks/reset_admin_passwords.yml
Normal file
57
roles/svc-openldap/tasks/reset_admin_passwords.yml
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
# Reset both Database and Configuration Admin passwords in LDAP via LDAPI
|
||||
# roles/svc-openldap/tasks/reset_admin_passwords.yml
|
||||
|
||||
- name: "Query available LDAP databases"
|
||||
shell: |
|
||||
docker exec {{ applications[application_id].hostname }} \
|
||||
ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b cn=config "(olcDatabase=*)" dn
|
||||
register: ldap_databases
|
||||
|
||||
- name: "Determine data backend DN (mdb)"
|
||||
set_fact:
|
||||
data_backend_dn: >-
|
||||
{{ ldap_databases.stdout_lines
|
||||
| select('search','^dn: olcDatabase=.*mdb')
|
||||
| map('regex_replace','^dn: ','')
|
||||
| list
|
||||
| first }}
|
||||
|
||||
- name: "Determine config backend DN"
|
||||
set_fact:
|
||||
config_backend_dn: >-
|
||||
{{ ldap_databases.stdout_lines
|
||||
| select('search','^dn: olcDatabase=\{[0-9]+\}config,cn=config$')
|
||||
| map('regex_replace','^dn: ','')
|
||||
| list
|
||||
| first }}
|
||||
|
||||
- name: "Generate hash for Database Admin password"
|
||||
shell: |
|
||||
docker exec {{ applications[application_id].hostname }} \
|
||||
slappasswd -s "{{ ldap.bind_credential }}"
|
||||
register: database_admin_pw_hash
|
||||
|
||||
- name: "Reset Database Admin password in LDAP (olcRootPW)"
|
||||
shell: |
|
||||
docker exec -i {{ applications[application_id].hostname }} ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
|
||||
dn: {{ data_backend_dn }}
|
||||
changetype: modify
|
||||
replace: olcRootPW
|
||||
olcRootPW: {{ database_admin_pw_hash.stdout }}
|
||||
EOF
|
||||
|
||||
- name: "Generate hash for Configuration Admin password"
|
||||
shell: |
|
||||
docker exec {{ applications[application_id].hostname }} \
|
||||
slappasswd -s "{{ applications[application_id].credentials.administrator_password }}"
|
||||
register: config_admin_pw_hash
|
||||
|
||||
- name: "Reset Configuration Admin password in LDAP (olcRootPW)"
|
||||
shell: |
|
||||
docker exec -i {{ applications[application_id].hostname }} ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
|
||||
dn: {{ config_backend_dn }}
|
||||
changetype: modify
|
||||
replace: olcRootPW
|
||||
olcRootPW: {{ config_admin_pw_hash.stdout }}
|
||||
EOF
|
32
roles/svc-openldap/tasks/schemas/nextcloud.yml
Normal file
32
roles/svc-openldap/tasks/schemas/nextcloud.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
- name: "pkgmgr install"
|
||||
include_role:
|
||||
name: pkgmgr-install
|
||||
vars:
|
||||
package_name: ldapsm
|
||||
|
||||
- name: Ensure custom LDAP schema snippet via ldapsm
|
||||
vars:
|
||||
schema_name: "nextcloud"
|
||||
attribute_defs:
|
||||
- "( 1.3.6.1.4.1.99999.1 NAME '{{ ldap.user.attributes.nextcloud_quota }}' DESC 'Quota for Nextcloud' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )"
|
||||
objectclass_defs:
|
||||
- "( 1.3.6.1.4.1.99999.2 NAME 'nextcloudUser' DESC 'Auxiliary class for Nextcloud attributes' AUXILIARY MAY ( {{ ldap.user.attributes.nextcloud_quota }} ) )"
|
||||
command: >
|
||||
ldapsm
|
||||
-s {{ ldap_server_uri }}
|
||||
-D '{{ ldap_bind_dn }}'
|
||||
-W '{{ ldap_bind_pw }}'
|
||||
-n {{ schema_name }}
|
||||
{% for at in attribute_defs %}
|
||||
-a "{{ at }}"
|
||||
{% endfor %}
|
||||
{% for oc in objectclass_defs %}
|
||||
-c "{{ oc }}"
|
||||
{% endfor %}
|
||||
register: ldapsm_result
|
||||
changed_when: "'Created schema entry' in ldapsm_result.stdout"
|
||||
check_mode: no
|
||||
|
||||
- name: Show ldapsm output
|
||||
debug:
|
||||
var: ldapsm_result.stdout_lines
|
40
roles/svc-openldap/tasks/schemas/openssh_lpk.yml
Normal file
40
roles/svc-openldap/tasks/schemas/openssh_lpk.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
- name: Install ldapsm
|
||||
include_role:
|
||||
name: pkgmgr-install
|
||||
vars:
|
||||
package_name: ldapsm
|
||||
|
||||
- name: Ensure OpenSSH-LPK schema via ldapsm
|
||||
vars:
|
||||
schema_name: "openssh-lpk"
|
||||
attribute_defs:
|
||||
- "( 1.3.6.1.4.1.24552.1.1 NAME '{{ ldap.user.attributes.ssh_public_key }}' DESC 'OpenSSH Public Key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )"
|
||||
- "( 1.3.6.1.4.1.24552.1.2 NAME 'sshFingerprint' DESC 'OpenSSH Public Key Fingerprint' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )"
|
||||
objectclass_defs:
|
||||
- >-
|
||||
( 1.3.6.1.4.1.24552.2.1
|
||||
NAME '{{ ldap.user.objects.auxiliary.ssh_public_key }}'
|
||||
DESC 'Auxiliary class for OpenSSH public keys'
|
||||
SUP top
|
||||
AUXILIARY
|
||||
MAY ( {{ ldap.user.attributes.ssh_public_key }} $ sshFingerprint ) )
|
||||
|
||||
command: >
|
||||
ldapsm
|
||||
-s {{ ldap_server_uri }}
|
||||
-D '{{ ldap_bind_dn }}'
|
||||
-W '{{ ldap_bind_pw }}'
|
||||
-n {{ schema_name }}
|
||||
{% for at in attribute_defs %}
|
||||
-a "{{ at }}"
|
||||
{% endfor %}
|
||||
{% for oc in objectclass_defs %}
|
||||
-c "{{ oc }}"
|
||||
{% endfor %}
|
||||
register: opensshlpk_ldapsm
|
||||
changed_when: "'Created schema entry' in opensshlpk_ldapsm.stdout"
|
||||
check_mode: no
|
||||
|
||||
- name: Show ldapsm output for openssh-lpk
|
||||
debug:
|
||||
var: opensshlpk_ldapsm.stdout_lines
|
Reference in New Issue
Block a user