mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-08-29 15:06:26 +02:00
Renamed the mariadb, openldap and postgres database
This commit is contained in:
38
roles/svc-db-openldap/README.md
Normal file
38
roles/svc-db-openldap/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# LDAP
|
||||
|
||||
## Description
|
||||
|
||||
Unleash the potential of centralized identity management with OpenLDAP. This powerful directory service provides a robust platform for managing users, groups, and organizational units while ensuring secure, scalable, and efficient authentication and authorization.
|
||||
|
||||
## Overview
|
||||
|
||||
Deploy OpenLDAP in a Docker environment with support for TLS-secured communication via an NGINX stream proxy. OpenLDAP offers advanced directory management capabilities, including flexible schema definitions, dynamic configuration overlays, and comprehensive query support with LDAP search utilities.
|
||||
|
||||
For further setup instructions and advanced configuration details, please refer to the following resources available in this directory:
|
||||
- [Administration.md](docs/Administration.md)
|
||||
- [Installation.md](docs/Installation.md)
|
||||
- [Change_DN.md](docs/Change_DN.md)
|
||||
|
||||
## Features
|
||||
|
||||
- **Centralized Identity Management:** Maintain a unified repository for all users and groups with robust organizational structures.
|
||||
- **Flexible Schema Support:** Customize and extend directory schemas to meet diverse organizational requirements.
|
||||
- **Secure Communications:** Enable TLS encryption for data in transit when accessed through an NGINX reverse proxy.
|
||||
- **Dynamic Configuration:** Leverage runtime configuration overlays to adjust directory settings without downtime.
|
||||
- **Comprehensive Query Capabilities:** Utilize LDAP search tools to efficiently query and manage directory data.
|
||||
- **High Performance and Scalability:** Designed to handle large-scale deployments with rapid lookup and authentication response times.
|
||||
|
||||
## Further Resources
|
||||
|
||||
- [Bitnami OpenLDAP](https://hub.docker.com/r/bitnami/openldap)
|
||||
- [phpLDAPadmin Documentation](https://github.com/leenooks/phpLDAPadmin/wiki/Docker-Container)
|
||||
- [LDAP Account Manager](https://github.com/LDAPAccountManager/docker)
|
||||
- [RBAC Wikipedia](https://de.wikipedia.org/wiki/Role_Based_Access_Control)
|
||||
|
||||
## Credits
|
||||
|
||||
Developed and maintained by **Kevin Veen-Birkenbach**.
|
||||
Learn more at [veen.world](https://www.veen.world).
|
||||
|
||||
Part of the [CyMaIS Project](https://github.com/kevinveenbirkenbach/cymais)
|
||||
Licensed under [CyMaIS NonCommercial License (CNCL)](https://s.veen.world/cncl).
|
3
roles/svc-db-openldap/TODO.md
Normal file
3
roles/svc-db-openldap/TODO.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Todos
|
||||
- User Groups and Roles on the proper way
|
||||
- Refactor the use of groups as roles in oauth2 proxy
|
0
roles/svc-db-openldap/__init__.py
Normal file
0
roles/svc-db-openldap/__init__.py
Normal file
11
roles/svc-db-openldap/config/main.yml
Normal file
11
roles/svc-db-openldap/config/main.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
hostname: "svc-db-openldap" # Hostname of the LDAP Server in the ldap network
|
||||
network:
|
||||
name: "svc-db-openldap"
|
||||
local: True # Activates local network. Necessary for LDIF import routines
|
||||
docker: True # Activates docker network to allow other docker containers to connect
|
||||
public: False # Set to true in inventory file if you want to expose the LDAP port to the internet
|
||||
images:
|
||||
openldap: "bitnami/openldap:latest"
|
||||
webinterface: "lam" # The webinterface which should be used. Possible: lam and phpldapadmin
|
||||
features:
|
||||
ldap: true
|
72
roles/svc-db-openldap/docs/Administration.md
Normal file
72
roles/svc-db-openldap/docs/Administration.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Administration
|
||||
|
||||
## 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'"
|
||||
```
|
||||
|
||||
```bash
|
||||
docker exec -it ldap bash -c "ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'cn=config' -s base '(objectClass=*)'"
|
||||
```
|
||||
|
||||
```bash
|
||||
docker exec -it ldap bash -c "ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'cn=config' -s base '(objectClass=olcModuleList)'"
|
||||
```
|
||||
|
||||
### Databases Overview
|
||||
```bash
|
||||
docker exec -it ldap ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(olcDatabase=*)"
|
||||
```
|
||||
|
||||
## Data
|
||||
|
||||
### Set Credentials
|
||||
To execute the following commands set the credentials via:
|
||||
|
||||
```bash
|
||||
eval $(
|
||||
grep -v '^\s*#' .env/env \
|
||||
| sed -E 's/\s*#.*//' \
|
||||
| sed -E 's/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)\s*$/export \1="\2"/'
|
||||
)
|
||||
```
|
||||
|
||||
### Show all Entries
|
||||
```bash
|
||||
docker exec -it ldap bash -c "ldapsearch -LLL -o ldif-wrap=no -x -D \"\$LDAP_ADMIN_DN\" -w \"\$LDAP_ADMIN_PASSWORD\" -b \"\$LDAP_ROOT\"";
|
||||
```
|
||||
|
||||
### Delete Groups and Subgroup
|
||||
To delete the group inclusive all subgroups use:
|
||||
```bash
|
||||
docker exec -it ldap bash -c "ldapsearch -LLL -o ldif-wrap=no -x -D \"\$LDAP_ADMIN_DN\" -w \"\$LDAP_ADMIN_PASSWORD\" -b \"ou=applications,ou=groups,\$LDAP_ROOT\" dn | sed -n 's/^dn: //p' | tac | while read -r dn; do echo \"Deleting \$dn\"; ldapdelete -x -D \"\$LDAP_ADMIN_DN\" -w \"\$LDAP_ADMIN_PASSWORD\" \"\$dn\"; done"
|
||||
|
||||
# Works
|
||||
docker exec -it ldap \
|
||||
ldapdelete -x \
|
||||
-D "$LDAP_ADMIN_DN" \
|
||||
-w "$LDAP_ADMIN_PASSWORD" \
|
||||
-r \
|
||||
"ou=groups,$LDAP_ROOT"
|
||||
```
|
||||
|
||||
## Import RBAC
|
||||
```bash
|
||||
docker exec -i ldap \
|
||||
ldapadd -x \
|
||||
-D "$LDAP_ADMIN_DN" \
|
||||
-w "$LDAP_ADMIN_PASSWORD" \
|
||||
-c \
|
||||
-f "/tmp/ldif/data/01_rbac.ldif"
|
||||
```
|
133
roles/svc-db-openldap/docs/Change_DN.md
Normal file
133
roles/svc-db-openldap/docs/Change_DN.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# Change Distinguished Name (DN) in OpenLDAP Docker
|
||||
|
||||
This document provides a step-by-step guide on how to rename the Distinguished Name (DN) from `cn=administrator,dc=flock,dc=town` to `cn=administrator,dc=cymais,dc=cloud` in an **OpenLDAP Docker** environment.
|
||||
|
||||
**Reference:** [Conversation Link](https://chatgpt.com/share/67d9a2f7-4e04-800f-9a0f-1673194f276c)
|
||||
|
||||
---
|
||||
|
||||
## 1. Export the Current Entry
|
||||
|
||||
Connect to the OpenLDAP container and export the current entry:
|
||||
|
||||
```sh
|
||||
docker exec -it ldap sh -c 'ldapsearch -x -D "$LDAP_ADMIN_DN" -w "$LDAP_ADMIN_PASSWORD" -b "$LDAP_ROOT"' > all_entries.ldif
|
||||
```
|
||||
|
||||
If your ***LDAP_ADMIN_DN*** and ***LDAP_ROOT*** are not accured pass them via ``--env``.
|
||||
|
||||
---
|
||||
|
||||
## 2. Modify the LDIF File
|
||||
|
||||
Open `all_entries.ldif` and update the DN (`dn:` line) and `dc` attributes.
|
||||
|
||||
- Open the file in an editor (`nano`, `vim`, `sed`).
|
||||
- Replace **all occurrences** of `dc=flock,dc=town` with `dc=cymais,dc=cloud`.
|
||||
|
||||
**Using `sed` to modify automatically:**
|
||||
```sh
|
||||
sed -i 's/dc=flock,dc=town/dc=cymais,dc=cloud/g' all_entries.ldif
|
||||
```
|
||||
|
||||
**Before:**
|
||||
```ldif
|
||||
dn: cn=administrator,dc=flock,dc=town
|
||||
cn: administrator
|
||||
objectClass: organizationalRole
|
||||
objectClass: simpleSecurityObject
|
||||
userPassword: {SSHA}...
|
||||
```
|
||||
|
||||
**After:**
|
||||
```ldif
|
||||
dn: cn=administrator,dc=cymais,dc=cloud
|
||||
cn: administrator
|
||||
objectClass: organizationalRole
|
||||
objectClass: simpleSecurityObject
|
||||
userPassword: {SSHA}...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Delete the Old Entry
|
||||
|
||||
### Generate a Recursive Delete LDIF
|
||||
We need an **LDIF file that deletes all objects** under `dc=flock,dc=town`.
|
||||
|
||||
Instead of manually writing an LDIF file, you can use `ldapsearch` and `awk` to generate it dynamically:
|
||||
|
||||
```sh
|
||||
docker exec -it ldap sh -c 'ldapsearch -x -D "cn=administrator,dc=flock,dc=town" -w "$LDAP_ADMIN_PASSWORD" -b "dc=flock,dc=town" dn' | awk "/^dn:/ {print \$2}" | tac > delete_all_dns.txt
|
||||
```
|
||||
|
||||
This creates an **ordered delete list**, starting with child objects before deleting `dc=flock,dc=town`.
|
||||
|
||||
---
|
||||
|
||||
#### Apply the Recursive Delete
|
||||
Now apply the generated `delete_all.ldif` to delete all entries **recursively**:
|
||||
|
||||
```sh
|
||||
docker exec -i ldap sh -c '
|
||||
while read dn; do
|
||||
ldapdelete -x -D "cn=administrator,dc=flock,dc=town" -w "$LDAP_ADMIN_PASSWORD" "$dn"
|
||||
done' < delete_all_dns.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Verify That Everything Is Deleted
|
||||
After running the delete command, verify that `dc=flock,dc=town` is empty:
|
||||
|
||||
```sh
|
||||
docker exec -it ldap sh -c 'ldapsearch -x -D "cn=administrator,dc=flock,dc=town" -w "$LDAP_ADMIN_PASSWORD" -b "dc=flock,dc=town"'
|
||||
```
|
||||
- ✅ If **no results** are returned, the domain has been deleted successfully.
|
||||
- ❌ If results still exist, some entries were not removed.
|
||||
|
||||
|
||||
#### Create new_database.ldif
|
||||
|
||||
docker exec -i ldap ldapadd -Y EXTERNAL -H ldapi:/// -f /dev/stdin < new_database.ldif
|
||||
|
||||
## 4. Add the New Entry
|
||||
|
||||
Now, upload the modified `all_entries.ldif`:
|
||||
|
||||
```sh
|
||||
cat all_entries.ldif | docker exec -i ldap sh -c 'ldapadd -x -D "cn=admin,dc=cymais,dc=cloud" -w "$LDAP_ADMIN_PASSWORD"'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Update Root DN Configuration
|
||||
|
||||
If `cn=administrator` is used as `rootdn`, update the OpenLDAP configuration file (`slapd.conf` or `olcDatabase={1}mdb.ldif` under `cn=config`).
|
||||
|
||||
Find:
|
||||
```ldif
|
||||
olcRootDN: cn=administrator,dc=flock,dc=town
|
||||
```
|
||||
Replace with:
|
||||
```ldif
|
||||
olcRootDN: cn=administrator,dc=cymais,dc=cloud
|
||||
```
|
||||
|
||||
Save the change and apply it:
|
||||
|
||||
```sh
|
||||
docker exec -it ldap ldapmodify -Y EXTERNAL -H ldapi:/// -f config_update.ldif
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Restart OpenLDAP
|
||||
|
||||
Restart the OpenLDAP container if necessary:
|
||||
|
||||
```sh
|
||||
docker restart ldap
|
||||
```
|
||||
|
||||
Now, `cn=administrator,dc=cymais,dc=cloud` should be active as the new administrator account.
|
35
roles/svc-db-openldap/docs/Installation.md
Normal file
35
roles/svc-db-openldap/docs/Installation.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Installation
|
||||
|
||||
## MemberOf
|
||||
```bash
|
||||
# Activate
|
||||
ldapmodify -Y EXTERNAL -H ldapi:/// <<EOF
|
||||
dn: cn=module{0},cn=config
|
||||
changetype: modify
|
||||
add: olcModuleLoad
|
||||
olcModuleLoad: /opt/bitnami/openldap/lib/openldap/memberof.so
|
||||
EOF
|
||||
|
||||
# Verify
|
||||
ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b "cn=module{0},cn=config" olcModuleLoad
|
||||
|
||||
ldapadd -Y EXTERNAL -H ldapi:/// <<EOF
|
||||
dn: olcOverlay=memberof,olcDatabase={2}mdb,cn=config
|
||||
objectClass: olcOverlayConfig
|
||||
objectClass: olcMemberOf
|
||||
olcOverlay: memberof
|
||||
olcMemberOfRefInt: TRUE
|
||||
olcMemberOfDangling: ignore
|
||||
olcMemberOfGroupOC: groupOfNames
|
||||
olcMemberOfMemberAD: member
|
||||
olcMemberOfMemberOfAD: memberOf
|
||||
EOF
|
||||
|
||||
|
||||
```
|
||||
|
||||
### Verifiy that MemberOf is activated and loaded
|
||||
```bash
|
||||
docker exec -it ldap sh -c 'ls -l /opt/bitnami/openldap/lib/openldap/memberof.*'
|
||||
docker exec -it ldap ldapsearch -Y EXTERNAL -H ldapi:/// -b cn=config '(&(objectClass=olcOverlayConfig)(olcOverlay=memberof))'
|
||||
```
|
0
roles/svc-db-openldap/filter_plugins/__init__.py
Normal file
0
roles/svc-db-openldap/filter_plugins/__init__.py
Normal file
@@ -0,0 +1,77 @@
|
||||
def build_ldap_nested_group_entries(applications, users, ldap):
|
||||
"""
|
||||
Builds structured LDAP role entries using the global `ldap` configuration.
|
||||
Supports objectClasses: posixGroup (adds gidNumber, memberUid), groupOfNames (adds member).
|
||||
Now nests roles under an application-level OU: application-id/role.
|
||||
"""
|
||||
|
||||
result = {}
|
||||
|
||||
# Base DN components
|
||||
role_dn_base = ldap["dn"]["ou"]["roles"]
|
||||
user_dn_base = ldap["dn"]["ou"]["users"]
|
||||
ldap_user_attr = ldap["user"]["attributes"]["id"]
|
||||
|
||||
# Supported objectClass flavors
|
||||
flavors = ldap.get("rbac", {}).get("flavors", [])
|
||||
|
||||
for application_id, app_config in applications.items():
|
||||
# Compute the DN for the application-level OU
|
||||
app_ou_dn = f"ou={application_id},{role_dn_base}"
|
||||
|
||||
ou_entry = {
|
||||
"dn": app_ou_dn,
|
||||
"objectClass": ["top", "organizationalUnit"],
|
||||
"ou": application_id,
|
||||
"description": f"Roles for application {application_id}"
|
||||
}
|
||||
result[app_ou_dn] = ou_entry
|
||||
|
||||
# Standard roles with an extra 'administrator'
|
||||
base_roles = app_config.get("rbac", {}).get("roles", {})
|
||||
roles = {
|
||||
**base_roles,
|
||||
"administrator": {
|
||||
"description": "Has full administrative access: manage themes, plugins, settings, and users"
|
||||
}
|
||||
}
|
||||
|
||||
group_id = app_config.get("group_id")
|
||||
|
||||
for role_name, role_conf in roles.items():
|
||||
# Build CN under the application OU
|
||||
cn = role_name
|
||||
dn = f"cn={cn},{app_ou_dn}"
|
||||
|
||||
entry = {
|
||||
"dn": dn,
|
||||
"cn": cn,
|
||||
"description": role_conf.get("description", ""),
|
||||
"objectClass": ["top"] + flavors,
|
||||
}
|
||||
|
||||
member_dns = []
|
||||
member_uids = []
|
||||
for username, user_conf in users.items():
|
||||
if role_name in user_conf.get("roles", []):
|
||||
member_dns.append(f"{ldap_user_attr}={username},{user_dn_base}")
|
||||
member_uids.append(username)
|
||||
|
||||
if "posixGroup" in flavors:
|
||||
entry["gidNumber"] = group_id
|
||||
if member_uids:
|
||||
entry["memberUid"] = member_uids
|
||||
|
||||
if "groupOfNames" in flavors and member_dns:
|
||||
entry["member"] = member_dns
|
||||
|
||||
result[dn] = entry
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
def filters(self):
|
||||
return {
|
||||
"build_ldap_nested_group_entries": build_ldap_nested_group_entries
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
def build_ldap_role_entries(applications, users, ldap):
|
||||
"""
|
||||
Builds structured LDAP role entries using the global `ldap` configuration.
|
||||
Supports objectClasses: posixGroup (adds gidNumber, memberUid), groupOfNames (adds member).
|
||||
"""
|
||||
|
||||
result = {}
|
||||
|
||||
for application_id, application_config in applications.items():
|
||||
base_roles = application_config.get("rbac", {}).get("roles", {})
|
||||
roles = {
|
||||
**base_roles,
|
||||
"administrator": {
|
||||
"description": "Has full administrative access: manage themes, plugins, settings, and users"
|
||||
}
|
||||
}
|
||||
|
||||
group_id = application_config.get("group_id")
|
||||
user_dn_base = ldap["dn"]["ou"]["users"]
|
||||
ldap_user_attr = ldap["user"]["attributes"]["id"]
|
||||
role_dn_base = ldap["dn"]["ou"]["roles"]
|
||||
flavors = ldap.get("rbac", {}).get("flavors", [])
|
||||
|
||||
for role_name, role_conf in roles.items():
|
||||
group_cn = f"{application_id}-{role_name}"
|
||||
dn = f"cn={group_cn},{role_dn_base}"
|
||||
|
||||
entry = {
|
||||
"dn": dn,
|
||||
"cn": group_cn,
|
||||
"description": role_conf.get("description", ""),
|
||||
"objectClass": ["top"] + flavors,
|
||||
}
|
||||
|
||||
# Initialize member lists
|
||||
member_dns = []
|
||||
member_uids = []
|
||||
|
||||
for username, user_config in users.items():
|
||||
if role_name in user_config.get("roles", []):
|
||||
user_dn = f"{ldap_user_attr}={username},{user_dn_base}"
|
||||
member_dns.append(user_dn)
|
||||
member_uids.append(username)
|
||||
|
||||
# Add gidNumber for posixGroup
|
||||
if "posixGroup" in flavors:
|
||||
entry["gidNumber"] = group_id
|
||||
if member_uids:
|
||||
entry["memberUid"] = member_uids
|
||||
|
||||
# Add members for groupOfNames
|
||||
if "groupOfNames" in flavors and member_dns:
|
||||
entry["member"] = member_dns
|
||||
|
||||
result[dn] = entry
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
def filters(self):
|
||||
return {
|
||||
"build_ldap_role_entries": build_ldap_role_entries
|
||||
}
|
55
roles/svc-db-openldap/handlers/main.yml
Normal file
55
roles/svc-db-openldap/handlers/main.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
- name: Load memberof module from file in OpenLDAP container
|
||||
shell: >
|
||||
docker exec -i {{ applications[application_id].hostname }} ldapmodify -Y EXTERNAL -H ldapi:/// -f {{ldif_docker_path}}configuration/01_member_of_configuration.ldif
|
||||
listen:
|
||||
- "Import configuration LDIF files"
|
||||
- "Import all LDIF files"
|
||||
# @todo Remove the following ignore errors when setting up a new server
|
||||
# Just here because debugging would take to much time
|
||||
ignore_errors: true
|
||||
|
||||
- name: Refint Module Activation for OpenLDAP
|
||||
shell: >
|
||||
docker exec -i {{ applications[application_id].hostname }} ldapadd -Y EXTERNAL -H ldapi:/// -f {{ldif_docker_path}}configuration/02_member_of_configuration.ldif
|
||||
listen:
|
||||
- "Import configuration LDIF files"
|
||||
- "Import all LDIF files"
|
||||
register: ldapadd_result
|
||||
failed_when: ldapadd_result.rc not in [0, 68]
|
||||
# @todo Remove the following ignore errors when setting up a new server
|
||||
# Just here because debugging would take to much time
|
||||
ignore_errors: true
|
||||
|
||||
- name: "Import schemas"
|
||||
shell: >
|
||||
docker exec -i {{ applications[application_id].hostname }} ldapadd -Y EXTERNAL -H ldapi:/// -f "{{ldif_docker_path}}schema/{{ 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, 80]
|
||||
listen:
|
||||
- "Import schema LDIF files"
|
||||
- "Import all LDIF files"
|
||||
loop: "{{ lookup('fileglob', role_path ~ '/templates/ldif/schema/*.j2', wantlist=True) }}"
|
||||
|
||||
- name: Refint Overlay Configuration for OpenLDAP
|
||||
shell: >
|
||||
docker exec -i {{ applications[application_id].hostname }} ldapmodify -Y EXTERNAL -H ldapi:/// -f {{ldif_docker_path}}configuration/03_member_of_configuration.ldif
|
||||
listen:
|
||||
- "Import configuration LDIF files"
|
||||
- "Import all LDIF files"
|
||||
register: ldapadd_result
|
||||
failed_when: ldapadd_result.rc not in [0, 68]
|
||||
# @todo Remove the following ignore errors when setting up a new server
|
||||
# Just here because debugging would take to much time
|
||||
ignore_errors: true
|
||||
|
||||
- name: "Import users, groups, etc. to LDAP"
|
||||
shell: >
|
||||
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]
|
||||
listen:
|
||||
- "Import data LDIF files"
|
||||
- "Import all LDIF files"
|
||||
loop: "{{ query('fileglob', role_path ~ '/templates/ldif/data/*.j2') | sort }}"
|
22
roles/svc-db-openldap/meta/main.yml
Normal file
22
roles/svc-db-openldap/meta/main.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: "Kevin Veen-Birkenbach"
|
||||
description: "Unleash the potential of centralized identity management with our robust LDAP Directory solution, powered by OpenLDAP. Manage users, groups, and schemas securely with extensive customization options and integrated TLS support."
|
||||
license: "CyMaIS NonCommercial License (CNCL)"
|
||||
license_url: "https://s.veen.world/cncl"
|
||||
company: |
|
||||
Kevin Veen-Birkenbach
|
||||
Consulting & Coaching Solutions
|
||||
https://www.veen.world
|
||||
galaxy_tags:
|
||||
- ldap
|
||||
- openldap
|
||||
- docker
|
||||
- directory
|
||||
- tls
|
||||
- identity management
|
||||
repository: https://s.veen.world/cymais
|
||||
issue_tracker_url: https://s.veen.world/cymaisissues
|
||||
documentation: https://s.veen.world/cymais
|
||||
logo:
|
||||
class: "fa-solid fa-users"
|
10
roles/svc-db-openldap/schema/main.yml
Normal file
10
roles/svc-db-openldap/schema/main.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
credentials:
|
||||
administrator_password:
|
||||
description: "Initial password for the LDAP administrator (e.g. cn=admin,dc=example,dc=com)"
|
||||
algorithm: "sha256"
|
||||
validation: "^[a-f0-9]{64}$"
|
||||
|
||||
administrator_database_password:
|
||||
description: "Password used internally for the database-backed directory admin"
|
||||
algorithm: "bcrypt"
|
||||
validation: "^\\$2[aby]\\$.{56}$"
|
34
roles/svc-db-openldap/tasks/add_user_objects.yml
Normal file
34
roles/svc-db-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-db-openldap/tasks/create_ldif_files.yml
Normal file
11
roles/svc-db-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"
|
135
roles/svc-db-openldap/tasks/main.yml
Normal file
135
roles/svc-db-openldap/tasks/main.yml
Normal file
@@ -0,0 +1,135 @@
|
||||
---
|
||||
|
||||
- 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: "{{ applications[application_id].network.name }}"
|
||||
state: present
|
||||
ipam_config:
|
||||
- subnet: "{{ networks.local['svc-db-openldap'].subnet }}"
|
||||
|
||||
- meta: flush_handlers
|
||||
|
||||
- name: "Wait for LDAP to be available"
|
||||
wait_for:
|
||||
host: "127.0.0.1"
|
||||
port: "{{ ports.localhost.ldap['svc-db-openldap'] }}"
|
||||
delay: 5
|
||||
timeout: 120
|
||||
state: started
|
||||
|
||||
- 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
|
56
roles/svc-db-openldap/tasks/reset_admin_passwords.yml
Normal file
56
roles/svc-db-openldap/tasks/reset_admin_passwords.yml
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
# Reset both Database and Configuration Admin passwords in LDAP via LDAPI
|
||||
|
||||
- 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-db-openldap/tasks/schemas/nextcloud.yml
Normal file
32
roles/svc-db-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-db-openldap/tasks/schemas/openssh_lpk.yml
Normal file
40
roles/svc-db-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
|
28
roles/svc-db-openldap/templates/docker-compose.yml.j2
Normal file
28
roles/svc-db-openldap/templates/docker-compose.yml.j2
Normal file
@@ -0,0 +1,28 @@
|
||||
{% include 'roles/docker-compose/templates/base.yml.j2' %}
|
||||
|
||||
application:
|
||||
image: "{{ applications[application_id].images.openldap }}"
|
||||
container_name: {{ applications[application_id].hostname }}
|
||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||
{% if applications[application_id].network.public | bool or applications[application_id].network.local | bool %}
|
||||
ports:
|
||||
- 127.0.0.1:{{ports.localhost.ldap['svc-db-openldap']}}:{{ldap_docker_port}}
|
||||
{% endif %}
|
||||
volumes:
|
||||
- 'data:/bitnami/openldap'
|
||||
- '{{ldif_host_path}}:{{ldif_docker_path}}:ro'
|
||||
healthcheck:
|
||||
test: >
|
||||
bash -c '
|
||||
ldapsearch -x -H ldap://localhost:{{ ldap_docker_port }} \
|
||||
-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"
|
||||
'
|
||||
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||
|
||||
{% include 'roles/docker-compose/templates/volumes.yml.j2' %}
|
||||
data:
|
||||
|
||||
{% include 'roles/docker-compose/templates/networks.yml.j2' %}
|
26
roles/svc-db-openldap/templates/env.j2
Normal file
26
roles/svc-db-openldap/templates/env.j2
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
# @See https://hub.docker.com/r/bitnami/openldap
|
||||
|
||||
# GENERAL
|
||||
## Admin (Data)
|
||||
LDAP_ADMIN_USERNAME= {{applications[application_id].users.administrator.username}} # LDAP database admin user.
|
||||
LDAP_ADMIN_PASSWORD= {{ldap.bind_credential}} # LDAP database admin password.
|
||||
|
||||
## Users
|
||||
LDAP_USERS= ' ' # Comma separated list of LDAP users to create in the default LDAP tree. Default: user01,user02
|
||||
LDAP_PASSWORDS= ' ' # Comma separated list of passwords to use for LDAP users. Default: bitnami1,bitnami2
|
||||
LDAP_ROOT= {{ldap.dn.root}} # LDAP baseDN (or suffix) of the LDAP tree. Default: dc=example,dc=org
|
||||
|
||||
## Admin (Config)
|
||||
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}}
|
||||
|
||||
# Network
|
||||
LDAP_PORT_NUMBER= {{ldap_docker_port}} # Route to default port
|
||||
LDAP_ENABLE_TLS= no # Using nginx proxy for tls
|
||||
LDAP_LDAPS_PORT_NUMBER= {{ldaps_docker_port}} # Port used for TLS secure traffic. Priviledged port is supported (e.g. 636). Default: 1636 (non privileged port).
|
||||
|
||||
# Security
|
||||
LDAP_ALLOW_ANON_BINDING= no # Allow anonymous bindings to the LDAP server. Default: yes.
|
@@ -0,0 +1,50 @@
|
||||
# MemberOf Overlay Configuration for OpenLDAP
|
||||
#
|
||||
# This file activates the memberOf module and configures the memberOf overlay,
|
||||
# which is required by Nextcloud for proper group management.
|
||||
# @see https://docs.nextcloud.com/server/latest/admin_manual/configuration_user/user_auth_ldap.html
|
||||
# @see https://www.adimian.com/blog/how-to-enable-memberof-using-openldap/
|
||||
#
|
||||
# The first section loads the memberof module from the specified path.
|
||||
# - olcModuleLoad: Specifies that the "memberof" module should be loaded.
|
||||
# - olcModulePath: Provides the full path to the memberof shared object.
|
||||
#
|
||||
# The second section configures the memberOf overlay for the designated database.
|
||||
# - The DN "olcOverlay={0}memberof,olcDatabase={1}hdb,cn=config" sets up the overlay
|
||||
# on the database backend (here assumed to be "hdb").
|
||||
# - olcMemberOfDangling: ignore
|
||||
# Instructs the overlay to ignore references to non-existent objects.
|
||||
# - olcMemberOfRefInt: TRUE
|
||||
# Enables referential integrity so that changes in group membership automatically
|
||||
# update the user's "memberOf" attribute.
|
||||
# - olcMemberOfGroupOC: groupOfNames
|
||||
# Specifies that the overlay applies to groups with the object class "groupOfNames".
|
||||
# - olcMemberOfMemberAD: member
|
||||
# Indicates that the group's membership is stored in the "member" attribute.
|
||||
# - olcMemberOfMemberOfAD: memberOf
|
||||
# Defines that the overlay will maintain the "memberOf" attribute in user entries.
|
||||
#
|
||||
# IMPORTANT: All groups created before enabling this module must be deleted and recreated,
|
||||
# as the overlay only assigns the "member" attribute when a new group is created.
|
||||
|
||||
# @todo Solve the following error:
|
||||
#fatal: [echoserver]: FAILED! => {"changed": true, "cmd": "docker exec -i ldap ldapmodify -Y EXTERNAL -H ldapi:/// -f /tmp/ldif/01_member_of_configuration.ldif\n", "delta": "0:00:00.059605", "end": "2025-02-25 12:01:18.218851", "msg": "non-zero return code", "rc": 247, "start": "2025-02-25 12:01:18.159246", "stderr": "SASL/EXTERNAL authentication started\nSASL username: gidNumber=0+uidNumber=1001,cn=peercred,cn=external,cn=auth\nSASL SSF: 0\nldapmodify: modify operation type is missing at line 2, entry \"cn=module,cn=config\"", "stderr_lines": ["SASL/EXTERNAL authentication started", "SASL username: gidNumber=0+uidNumber=1001,cn=peercred,cn=external,cn=auth", "SASL SSF: 0", "ldapmodify: modify operation type is missing at line 2, entry \"cn=module,cn=config\""], "stdout": "", "stdout_lines": []}
|
||||
|
||||
|
||||
dn: cn=module,cn=config
|
||||
cn: module
|
||||
objectClass: olcModuleList
|
||||
olcModuleLoad: memberof
|
||||
olcModulePath: /opt/bitnami/openldap/lib/openldap/memberof.so
|
||||
|
||||
dn: olcOverlay={0}memberof,olcDatabase={1}hdb,cn=config
|
||||
objectClass: olcConfig
|
||||
objectClass: olcMemberOf
|
||||
objectClass: olcOverlayConfig
|
||||
objectClass: top
|
||||
olcOverlay: memberof
|
||||
olcMemberOfDangling: ignore
|
||||
olcMemberOfRefInt: TRUE
|
||||
olcMemberOfGroupOC: groupOfNames
|
||||
olcMemberOfMemberAD: member
|
||||
olcMemberOfMemberOfAD: memberOf
|
@@ -0,0 +1,10 @@
|
||||
# Refint Module Activation for OpenLDAP
|
||||
#
|
||||
# This section adds the refint module to the LDAP configuration.
|
||||
# The refint module ensures referential integrity by automatically updating
|
||||
# or removing references when objects are renamed or deleted.
|
||||
#
|
||||
# In this file, the "olcmoduleload" attribute is used to load the "refint" module.
|
||||
dn: cn=module{1},cn=config
|
||||
add: olcmoduleload
|
||||
olcmoduleload: refint
|
@@ -0,0 +1,23 @@
|
||||
# Refint Overlay Configuration for OpenLDAP
|
||||
#
|
||||
# This file configures the refint overlay for the specified LDAP database.
|
||||
#
|
||||
# The overlay is applied to the database (here using the "hdb" backend) and is
|
||||
# responsible for maintaining referential integrity.
|
||||
#
|
||||
# The attribute "olcRefintAttribute" lists the attributes that will be monitored
|
||||
# for changes. In this case, changes to the following attributes will be tracked:
|
||||
# - memberof
|
||||
# - member
|
||||
# - manager
|
||||
# - owner
|
||||
#
|
||||
# This ensures that any changes in the LDAP directory (such as deletion or modification
|
||||
# of an object) automatically update all references to that object, preventing dangling references.
|
||||
dn: olcOverlay={1}refint,olcDatabase={1}hdb,cn=config
|
||||
objectClass: olcConfig
|
||||
objectClass: olcOverlayConfig
|
||||
objectClass: olcRefintConfig
|
||||
objectClass: top
|
||||
olcOverlay: {1}refint
|
||||
olcRefintAttribute: memberof member manager owner
|
@@ -0,0 +1,6 @@
|
||||
# Activates Password hashing in ldap
|
||||
|
||||
dn: cn=config
|
||||
changetype: modify
|
||||
replace: olcPasswordHash
|
||||
olcPasswordHash: {SSHA}
|
@@ -0,0 +1 @@
|
||||
This folder contains configuration files where a specific logic needs to be applied.
|
@@ -0,0 +1,30 @@
|
||||
{#
|
||||
@todo: activate
|
||||
{% for dn, entry in (applications | build_ldap_role_entries(users, ldap)).items() %}
|
||||
|
||||
dn: {{ dn }}
|
||||
{% for oc in entry.objectClass %}
|
||||
objectClass: {{ oc }}
|
||||
{% endfor %}
|
||||
{% if entry.ou is defined %}
|
||||
ou: {{ entry.ou }}
|
||||
{% else %}
|
||||
cn: {{ entry.cn }}
|
||||
{% endif %}
|
||||
{% if entry.gidNumber is defined %}
|
||||
gidNumber: {{ entry.gidNumber }}
|
||||
{% endif %}
|
||||
description: {{ entry.description }}
|
||||
{% if entry.memberUid is defined %}
|
||||
{% for uid in entry.memberUid %}
|
||||
memberUid: {{ uid }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if entry.member is defined %}
|
||||
{% for m in entry.member %}
|
||||
member: {{ m }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
#}
|
@@ -0,0 +1,23 @@
|
||||
{% for dn, entry in (applications | build_ldap_role_entries(users, ldap)).items() %}
|
||||
|
||||
dn: {{ dn }}
|
||||
{% for oc in entry.objectClass %}
|
||||
objectClass: {{ oc }}
|
||||
{% endfor %}
|
||||
{% if entry.gidNumber is defined %}
|
||||
gidNumber: {{ entry.gidNumber }}
|
||||
{% endif %}
|
||||
cn: {{ entry.cn }}
|
||||
description: {{ entry.description }}
|
||||
{% if entry.memberUid is defined %}
|
||||
{% for uid in entry.memberUid %}
|
||||
memberUid: {{ uid }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if entry.member is defined %}
|
||||
{% for m in entry.member %}
|
||||
member: {{ m }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
1
roles/svc-db-openldap/templates/ldif/data/README.md
Normal file
1
roles/svc-db-openldap/templates/ldif/data/README.md
Normal file
@@ -0,0 +1 @@
|
||||
This folder contains files which are importet via ldapadd without any specific logic
|
6
roles/svc-db-openldap/templates/nginx.stream.conf.j2
Normal file
6
roles/svc-db-openldap/templates/nginx.stream.conf.j2
Normal file
@@ -0,0 +1,6 @@
|
||||
server {
|
||||
listen {{ ports.public.ldaps['svc-db-openldap'] }}ssl;
|
||||
proxy_pass 127.0.0.1:{{ ports.localhost.ldap['svc-db-openldap'] }};
|
||||
|
||||
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_credentials.j2' %}
|
||||
}
|
3
roles/svc-db-openldap/users/main.yml
Normal file
3
roles/svc-db-openldap/users/main.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
users:
|
||||
administrator:
|
||||
username: "administrator"
|
17
roles/svc-db-openldap/vars/main.yml
Normal file
17
roles/svc-db-openldap/vars/main.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
application_id: "svc-db-openldap"
|
||||
|
||||
# LDAP Variables
|
||||
ldaps_docker_port: 636
|
||||
ldap_docker_port: 389
|
||||
ldap_server_uri: "ldap://127.0.0.1:{{ ports.localhost.ldap['svc-db-openldap'] }}"
|
||||
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 # Don't know if this is still needed, it's now setup via tasks
|
Reference in New Issue
Block a user