Refactored ldap implementation for ssh keys

This commit is contained in:
2025-06-27 16:41:10 +02:00
parent bb73e948d3
commit 40edaa52ad
22 changed files with 167 additions and 67 deletions

View File

@@ -1,22 +1,32 @@
- name: "1) Gather all existing user DNs"
- name: Gather all users with their current objectClass list
community.general.ldap_search:
server_uri: "{{ ldap.server.uri }}"
bind_dn: "{{ ldap.dn.administrator }}"
server_uri: "{{ ldap_server_uri }}"
bind_dn: "{{ ldap.dn.administrator.data }}"
bind_pw: "{{ ldap.bind_credential }}"
base: "{{ ldap.dn.users }}"
dn: "{{ ldap.dn.users }}"
scope: subordinate
filter: "{{ ldap.filters.users.all }}"
attributes: ["dn"]
register: ldap_existing_users
attrs:
- dn
- objectClass
- "{{ ldap.attributes.user_id }}"
register: ldap_users_with_classes
- name: "2) Update each existing user with all user_objects"
- name: Add only missing auxiliary classes
community.general.ldap_attrs:
server_uri: "{{ ldap.server.uri }}"
bind_dn: "{{ ldap.dn.administrator }}"
server_uri: "{{ ldap_server_uri }}"
bind_dn: "{{ ldap.dn.administrator.data }}"
bind_pw: "{{ ldap.bind_credential }}"
dn: "{{ item.dn }}"
attributes:
objectClass: "{{ ldap.user_objects }}"
state: exact
loop: "{{ ldap_existing_users.entries }}"
objectClass: "{{ missing_auxiliary }}"
state: present
loop: "{{ ldap_users_with_classes.results }}"
loop_control:
label: "{{ item.dn }}"
vars:
missing_auxiliary: >-
{{ ldap.user_objects.auxiliary
| difference(item.objectClass | default([]))
}}
when: missing_auxiliary | length > 0

View File

@@ -49,11 +49,10 @@
state: present
- name: "Include Nextcloud Schema"
include_tasks: create_nextcloud_schema.yml
vars:
ldap_server_uri: "ldap://127.0.0.1:{{ ports.localhost.ldap.ldap }}"
ldap_bind_dn: "cn={{ applications[application_id].users.administrator.username }},cn=config"
ldap_bind_pw: "{{ applications[application_id].credentials.administrator_password }}"
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
@@ -61,10 +60,10 @@
- name: Ensure LDAP users exist
community.general.ldap_entry:
dn: "{{ ldap.attributes.user_id }}={{ item.key }},{{ ldap.dn.users }}"
server_uri: "ldap://127.0.0.1:{{ ports.localhost.ldap.ldap }}"
bind_dn: "{{ ldap.dn.administrator }}"
server_uri: "{{ ldap_server_uri }}"
bind_dn: "{{ ldap.dn.administrator.data }}"
bind_pw: "{{ ldap.bind_credential }}"
objectClass: "{{ ldap.user_objects }}"
objectClass: "{{ ldap.user_objects.structural }}"
attributes:
uid: "{{ item.key }}" # {{ ldap.attributes.user_id }} can't be used as key here, dynamic key generation isn't possible
sn: "{{ item.value.sn | default(item.key) }}"
@@ -85,13 +84,13 @@
- name: Ensure required objectClass values and mail address are present
community.general.ldap_attrs:
dn: "{{ ldap.attributes.user_id }}={{ item.key }},{{ ldap.dn.users }}"
server_uri: "ldap://127.0.0.1:{{ ports.localhost.ldap.ldap }}"
bind_dn: "{{ ldap.dn.administrator }}"
server_uri: "{{ ldap_server_uri }}"
bind_dn: "{{ ldap.dn.administrator.data }}"
bind_pw: "{{ ldap.bind_credential }}"
attributes:
objectClass: "{{ ldap.user_objects }}"
objectClass: "{{ ldap.user_objects.structural }}"
mail: "{{ item.value.email }}"
state: exact # exact is safest for single-valued attributes
state: exact
loop: "{{ users | dict2items }}"
loop_control:
label: "{{ item.key }}"
@@ -99,8 +98,8 @@
- name: "Ensure container for application roles exists"
community.general.ldap_entry:
dn: "{{ ldap.dn.application_roles }}"
server_uri: "ldap://127.0.0.1:{{ ports.localhost.ldap.ldap }}"
bind_dn: "{{ ldap.dn.administrator }}"
server_uri: "{{ ldap_server_uri }}"
bind_dn: "{{ ldap.dn.administrator.data }}"
bind_pw: "{{ ldap.bind_credential }}"
objectClass: organizationalUnit
attributes:

View 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 'sshPublicKey' 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 'ldapPublicKey'
DESC 'Auxiliary class for OpenSSH public keys'
SUP top
AUXILIARY
MAY ( sshPublicKey $ 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