wheelybird / ldap-user-manager

A PHP web-based interface for LDAP user account management and self-service password change.
MIT License
477 stars 106 forks source link

Unable to create users and groups if using .ldif file for unattended/unguided initial setup #226

Open FlorianWolters opened 1 month ago

FlorianWolters commented 1 month ago

I am using wheelybird/ldap-user-manager:v1.11 together with bitnami/openldap:2.

I was able to get everything up and running without using a custom LDIF file. Even with a custom LDIF file (see below) I am able to log into the GUI, but as soon as I try to create a LDAP user I got the following error message in the GUI:

     Insufficient access
no write access to parent    

The log of the ui container contains the following:

ldap_parse_result
ldap_msgfree
ldap_err2string
ldap_err2string
[Tue Jul 30 13:20:30.052454 2024] [php:notice] [pid 23] [client 172.19.0.1:39768]  Create account; couldn't create the account for florian.wolters: Insufficient access -- no write access to parent, referer: http://localhost:18080/ldap/account_manager/new_user.php
ldap_msgfree
ldap_err2string
ldap_free_connection 1 1
ldap_send_unbind
ldap_free_connection: actually freed

I assume this is related to permissions / ACLs in the LDAP server itself and not a problem of the GUI. I am posting this here, because I think this project could benefit from some kind of documentation on how to get it initially up and running without having to call the /setup URL.

I created the setup.ldif file, based on the ldapsearch -x -b "dc=example,dc=org" -H ldap://0.0.0.0:1389 command (run in the backend container) after getting it up and running without a custom configuration.

I searched on the WWW, but the LDAP stuff is too advanced for me (I am a total LDAP newbie).

I would be glad if someone can explain what must be added, in order to get this project up and running without having to interact with the /setup URL. I assume, something has to be added to the setup.ldif file.


Here are the relevant files:

docker-compose.yml

services:
  openldap:
    image: bitnami/openldap:2
    container_name: backend
    ports:
      - '1389:1389'
      - '1636:1636'
    environment:
      - LDAP_ROOT=dc=example,dc=org
      - LDAP_ADMIN_USERNAME=max.mustermann
      - LDAP_ADMIN_PASSWORD=admin
      - LDAP_CUSTOM_LDIF_DIR=/ldifs
    networks:
      - openldap
    volumes:
      - 'openldap_data:/bitnami/openldap'
      - './ldifs:/ldifs'

  openldap-ui:
    image: wheelybird/ldap-user-manager:v1.11
    container_name: ui
    environment:
      - ACCEPT_WEAK_PASSWORDS=true
      - DEFAULT_USER_GROUP=everybody
      - DEFAULT_USER_SHELL=/bin/bash
      - EMAIL_DOMAIN=example.org
      - ENFORCE_SAFE_SYSTEM_NAMES=true
      - FORCE_RFC2307BIS=false
      - NO_HTTPS=true
      - ORGANISATION_NAME=Example, Inc.
      - SERVER_HOSTNAME=localhost
      - SERVER_PATH=/ldap
      - SERVER_PORT=80
      - LDAP_URI=ldap://openldap:1389
      - LDAP_BASE_DN=dc=example,dc=org
      - LDAP_DEBUG=true
      - LDAP_VERBOSE_CONNECTION_LOGS=true
      - LDAP_USER_OU=people
      - LDAP_GROUP_OU=groups
      - LDAP_ADMINS_GROUP=admins
      - LDAP_ADMIN_BIND_DN=uid=max.mustermann,ou=people,dc=example,dc=org
      - LDAP_ADMIN_BIND_PWD=admin
      - LDAP_IGNORE_CERT_ERRORS=true
      - LDAP_REQUIRE_STARTTLS=false
      - SITE_NAME=Example, Inc. LDAP Account Manager
      - USERNAME_FORMAT={first_name}.{last_name}
      - USERNAME_REGEX=^[a-z][a-zA-Z0-9._-]{3,32}$
    depends_on:
      - openldap
    ports:
      - '18080:80'
    networks:
      - openldap

networks:
  openldap:
    name: openldap

volumes:
  openldap_data:
    name: openldap_data
    driver: local

setup.ldif

# extended LDIF
#
# LDAPv3
# base <dc=example,dc=org> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# example.org
dn: dc=example,dc=org
objectClass: dcObject
objectClass: organization
dc: example
o: Example, Inc.

# groups, example.org
dn: ou=groups,dc=example,dc=org
objectClass: organizationalUnit
ou: groups

# people, example.org
dn: ou=people,dc=example,dc=org
objectClass: organizationalUnit
ou: people

# jane.doe, people, example.org
dn: uid=jane.doe,ou=people,dc=example,dc=org
givenName: Jane
sn: Doe
uid: jane.doe
mail: jane.doe@example.org
cn: Jane Doe
objectClass: person
objectClass: inetOrgPerson
objectClass: organizationalPerson
userPassword: user

# john.doe, people, example.org
dn: uid=john.doe,ou=people,dc=example,dc=org
givenName: John
sn: Doe
uid: john.doe
mail: john.doe@example.org
cn: John Doe
objectClass: person
objectClass: inetOrgPerson
objectClass: organizationalPerson
userPassword: user

# lastGID, example.org
dn: cn=lastGID,dc=example,dc=org
objectClass: device
objectClass: top
description: Records the last GID used to create a Posix group. This prevents the re-use of a GID from a deleted group.
cn: lastGID
serialNumber: 2002

# lastUID, example.org
dn: cn=lastUID,dc=example,dc=org
objectClass: device
objectClass: top
description: Records the last UID used to create a Posix account. This prevents the re-use of a UID from a deleted account.
cn: lastUID
serialNumber: 2001

# everybody, groups, example.org
dn: cn=everybody,ou=groups,dc=example,dc=org
objectClass: top
objectClass: posixGroup
cn: everybody
memberUid: max.mustermann
gidNumber: 2001
description: The group for normal users.

# admins, groups, example.org
dn: cn=admins,ou=groups,dc=example,dc=org
objectClass: top
objectClass: posixGroup
cn: admins
memberUid: max.mustermann
gidNumber: 2002
description: The group for administrators.

# max.mustermann, people, example.org
dn: uid=max.mustermann,ou=people,dc=example,dc=org
givenName: Max
sn: Mustermann
uid: max.mustermann
mail: max.mustermann@example.org
cn: Max Mustermann
objectClass: person
objectClass: inetOrgPerson
objectClass: posixAccount
userPassword: admin
uidNumber: 2001
gidNumber: 2001
loginShell: /bin/bash
homeDirectory: /home/max.mustermann
wheelybird commented 1 month ago

Hi. The account you're creating in the LDIF (uid=max.mustermann,ou=people,dc=example,dc=org) is a different account from the admin account you created for the OpenLDAP container. You should change LDAP_ADMIN_BIND_DN=uid=max.mustermann,ou=people,dc=example,dc=org to e.g. LDAP_ADMIN_BIND_DN=uid=max.mustermann,dc=example,dc=org.

FlorianWolters commented 3 weeks ago

Sorry for the late response.

Updating from LDAP_ADMIN_BIND_DN=uid=max.mustermann,ou=people,dc=example,dc=org to LDAP_ADMIN_BIND_DN=uid=max.mustermann,dc=example,dc=org in the docker-compose.yml file does not work.

Message in the web UI after login:

Problem: Failed to bind as uid=max.mustermann,dc=example,dc=org

Also, I don't see why both accounts in my OP should be different. Imo, they are different after this change.

wheelybird commented 3 weeks ago

Actually it probably should be cn=max.mustermann,dc=example,dc=org. It's the value of LDAP_ADMIN_DN in the bitnami/openldap container. The documentation on their Docker hub page doesn't say what that defaults to, so if cn=max.mustermann,dc=example,dc=org doesn't work then you might need to exec into the ldap container and run env | grep LDAP_ADMIN_DN to find the actual DN for the admin user. If that doesn't work, you can try slapcat -b cn=config in that container instead.