mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-09-05 18:01:40 +02:00
Refactored ldap implementation for ssh keys
This commit is contained in:
@@ -2,6 +2,15 @@
|
||||
|
||||
## Configuration
|
||||
|
||||
## Load env
|
||||
|
||||
To use the following commands firs load the env:
|
||||
```bash
|
||||
export $(grep -v '^[[:space:]]*#' ./.env/env \
|
||||
| sed -E 's/#.*$//; /^[[:space:]]*$/d; s/^[[:space:]]*//; s/[[:space:]]*$//; s/[[:space:]]*=[[:space:]]*/=/' \
|
||||
| xargs)
|
||||
```
|
||||
|
||||
### Show Configuration
|
||||
```bash
|
||||
docker exec -it ldap bash -c "ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'cn=config'"
|
||||
|
@@ -45,7 +45,7 @@
|
||||
|
||||
- name: "Import users, groups, etc. to LDAP"
|
||||
shell: >
|
||||
docker exec -i {{ applications[application_id].hostname }} ldapadd -x -D "{{ldap.dn.administrator}}" -w "{{ldap.bind_credential}}" -c -f "{{ldif_docker_path}}data/{{ item | basename | regex_replace('\.j2$', '') }}"
|
||||
docker exec -i {{ applications[application_id].hostname }} ldapadd -x -D "{{ldap.dn.administrator.data}}" -w "{{ldap.bind_credential}}" -c -f "{{ldif_docker_path}}data/{{ item | basename | regex_replace('\.j2$', '') }}"
|
||||
register: ldapadd_result
|
||||
changed_when: "'adding new entry' in ldapadd_result.stdout"
|
||||
failed_when: ldapadd_result.rc not in [0, 20, 68]
|
||||
|
@@ -20,6 +20,3 @@ galaxy_info:
|
||||
documentation: https://s.veen.world/cymais
|
||||
logo:
|
||||
class: "fa-solid fa-users"
|
||||
#run_after:
|
||||
# - "0"
|
||||
dependencies: []
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
40
roles/docker-ldap/tasks/schemas/openssh_lpk.yml
Normal file
40
roles/docker-ldap/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 '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
|
@@ -17,7 +17,7 @@ services:
|
||||
test: >
|
||||
bash -c '
|
||||
ldapsearch -x -H ldap://localhost:{{ ldap_docker_port }} \
|
||||
-D "{{ ldap.dn.administrator }}" -w "{{ ldap.bind_credential }}" -b "{{ ldap.dn.root }}" > /dev/null \
|
||||
-D "{{ ldap.dn.administrator.data }}" -w "{{ ldap.bind_credential }}" -b "{{ ldap.dn.root }}" > /dev/null \
|
||||
&& ldapsearch -Y EXTERNAL -H ldapi:/// \
|
||||
-b cn=config "(&(objectClass=olcOverlayConfig)(olcOverlay=memberof))" \
|
||||
| grep "olcOverlay:" | grep -q "memberof"
|
||||
|
@@ -12,7 +12,7 @@ LDAP_PASSWORDS= ' ' # Comma separated li
|
||||
LDAP_ROOT= {{ldap.dn.root}} # LDAP baseDN (or suffix) of the LDAP tree. Default: dc=example,dc=org
|
||||
|
||||
## Admin
|
||||
LDAP_ADMIN_DN= {{ldap.dn.administrator}}
|
||||
LDAP_ADMIN_DN= {{ldap.dn.administrator.data}}
|
||||
LDAP_CONFIG_ADMIN_ENABLED= yes
|
||||
LDAP_CONFIG_ADMIN_USERNAME= {{applications[application_id].users.administrator.username}}
|
||||
LDAP_CONFIG_ADMIN_PASSWORD= {{applications[application_id].credentials.administrator_password}}
|
||||
|
@@ -1,10 +1,17 @@
|
||||
application_id: "ldap"
|
||||
ldaps_docker_port: 636
|
||||
ldap_docker_port: 389
|
||||
ldif_host_path: "{{docker_compose.directories.volumes}}ldif/"
|
||||
ldif_docker_path: "/tmp/ldif/"
|
||||
ldap.dn.application_roles: "ou=application_roles,{{ldap.dn.root}}"
|
||||
application_id: "ldap"
|
||||
|
||||
# LDAP Variables
|
||||
ldaps_docker_port: 636
|
||||
ldap_docker_port: 389
|
||||
ldap_server_uri: "ldap://127.0.0.1:{{ ports.localhost.ldap.ldap }}"
|
||||
ldap_hostname: "{{ applications[application_id].hostname }}"
|
||||
ldap_bind_dn: "{{ ldap.dn.administrator.configuration }}"
|
||||
ldap_bind_pw: "{{ applications[application_id].credentials.administrator_password }}"
|
||||
|
||||
# LDIF Variables
|
||||
ldif_host_path: "{{docker_compose.directories.volumes}}ldif/"
|
||||
ldif_docker_path: "/tmp/ldif/"
|
||||
ldif_types:
|
||||
- configuration
|
||||
- data
|
||||
- schema
|
||||
- schema # Don't know if this is still needed, it's now setup via tasks
|
Reference in New Issue
Block a user