How-to: Package and Register a Restricted LDAP Read-Only ACL in UCS

How to Package and Register a Restricted LDAP Read-Only ACL in UCS

This article describes how to create a Debian package that registers a restricted LDAP read-only ACL in Univention Corporate Server (UCS). The example grants a dedicated LDAP account read access to a specific LDAP subtree while preventing access to other branches and denying write operations.


1. Create the package directory

mkdir -p ~/ldap-acl-test/debian
mkdir -p ~/ldap-acl-test/usr/share/ldap-acl-test
cd ~/ldap-acl-test

The resulting directory structure will look as follows:

ldap-acl-test/
├── 50ldap-acl-test.inst
├── usr/
│   └── share/
│       └── ldap-acl-test/
│           └── 65ldap-readonly.acl
└── debian/
    ├── changelog
    ├── control
    ├── install
    └── rules

2. Create the ACL file

nano usr/share/ldap-acl-test/65ldap-readonly.acl

Example content:

access to dn.subtree="ou=schule1,dc=example,dc=de"
    by dn.base="uid=ldap-readonly,cn=users,dc=example,dc=de" read
    by * +0 break

access to *
    by dn.base="uid=ldap-readonly,cn=users,dc=example,dc=de" none stop
    by * +0 break

Adjust the following values to match your environment:

ou=schule1,dc=example,dc=de
uid=ldap-readonly,cn=users,dc=example,dc=de

The ACL grants the account:

  • Read access to the ou=schule1,... branch
  • Read access to all subordinate objects within this branch
  • No access to other branches
  • No write permissions

The file name 65ldap-readonly.acl is also the file name that will later be used in the UCR template directory:

/etc/univention/templates/files/etc/ldap/slapd.conf.d/65ldap-readonly.acl

3. Create the join script

nano 50ldap-acl-test.inst

Content:

#!/bin/sh

VERSION=1

. /usr/share/univention-join/joinscripthelper.lib
. /usr/share/univention-lib/ldap.sh

joinscript_init

export UNIVENTION_APP_IDENTIFIER="ldap-acl-test-1.0"

ucs_registerLDAPExtension "$@" \
    --ucsversionstart "5.2-0" \
    --ucsversionend "5.99-0" \
    --acl /usr/share/ldap-acl-test/65ldap-readonly.acl || die

joinscript_save_current_version

exit 0

Important:

  • The ACL file is specified with --acl.
  • The path points to the source file installed by the package.
  • --acl and the corresponding file path must be specified together.
  • The script must not later be executed directly with bash 50ldap-acl-test.inst.

Make the script executable:

chmod 755 50ldap-acl-test.inst

4. Create the Debian control file

nano debian/control

Content:

Source: ldap-acl-test
Section: univention
Priority: optional
Maintainer: MiracErde <Miro@example.de>
Build-Depends:
 debhelper-compat (= 13),
 univention-join-dev
Standards-Version: 4.3.0.3

Package: ldap-acl-test
Architecture: all
Depends:
 univention-join,
 shell-univention-lib,
 ${misc:Depends}
Description: Restricted LDAP read-only ACL
 Installs a UCS LDAP ACL for a restricted read-only account.

5. Create the Debian rules file

nano debian/rules

Content:

#!/usr/bin/make -f

%:
	dh $@ --with univention-join

Make the file executable:

chmod 755 debian/rules

The --with univention-join option ensures that the join script is correctly processed as a package join script.


6. Create the installation file

nano debian/install

Content:

usr/share/ldap-acl-test/65ldap-readonly.acl usr/share/ldap-acl-test/

After installing the package, this places the ACL file at:

/usr/share/ldap-acl-test/65ldap-readonly.acl

The final destination directory is managed by the UCS LDAP listener.


7. Create the Debian changelog

Using dch:

dch --create \
    --package ldap-acl-test \
    --newversion 1.0-1 \
    "Register restricted LDAP read-only ACL"

Alternatively, create the file manually:

nano debian/changelog
ldap-acl-test (1.0-1) unstable; urgency=medium

  * Register restricted LDAP read-only ACL.

 -- Administrator <root@example.de>  Fri, 11 Sep 2026 17:00:00 +0200

8. Build the package

From the package directory:

cd ~/ldap-acl-test
dpkg-buildpackage -us -uc -b

The resulting package is located one directory level above:

ls -l ~/ldap-acl-test_*.deb

9. Install the package

dpkg -i ~/ldap-acl-test_*.deb

Verify that the ACL file has been installed:

ls -l /usr/share/ldap-acl-test/65ldap-readonly.acl

The join script should have been installed by dh-univention-join:

ls -l /usr/lib/univention-install/50ldap-acl-test.inst

10. Run the join script correctly

:warning: Do not run the join script as follows:

bash 50ldap-acl-test.inst

Running the script this way prevents UCS from automatically determining the Debian package name.

:white_check_mark: Use:

univention-run-join-scripts

Alternatively, you can run the join script through the UCS management interface.

ucs_registerLDAPExtension can now automatically determine:

  • The Debian package name
  • The installed package version
  • The join script context

Therefore, the following options are normally not required in a production join script:

--packagename
--packageversion

11. Verify that the LDAP extension has been registered

udm settings/ldapacl list

Look for an object associated with ldap-acl-test.

Also verify that the file has been placed in the intended UCR template directory:

ls -l /etc/univention/templates/files/etc/ldap/slapd.conf.d/

The expected file is:

/etc/univention/templates/files/etc/ldap/slapd.conf.d/65ldap-readonly.acl

12. Verify the LDAP configuration and listener

The listener should update the configuration automatically. If you encounter problems, check:

journalctl -u univention-directory-listener

Additionally:

ucr commit /etc/ldap/slapd.conf
systemctl restart slapd

Running ucr commit manually is normally not required, but it can be used for verification or after correcting the configuration.


13. Test access

Test the permitted branch:

ldapsearch -x \
    -D "uid=ldap-readonly,cn=users,dc=example,dc=de" \
    -W \
    -b "ou=schule1,dc=example,dc=de"

Test a branch that is not permitted:

ldapsearch -x \
    -D "uid=ldap-readonly,cn=users,dc=example,dc=de" \
    -W \
    -b "cn=users,dc=example,dc=de"

Access to the second branch must either be denied or return no results.

root@Bremen:~# ldapsearch -x -D "uid=ldap-readonly,cn=users,dc=deadpool,dc=intranet" -W -b "cn=users,dc=deadpool,dc=intranet"
Enter LDAP Password:
# extended LDIF
#
# LDAPv3
# base <cn=users,dc=deadpool,dc=intranet> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 32 No such object

The registration creates a replicated settings/ldapacl object. Based on this object, the UCS LDAP listener distributes the file, including to:

/etc/univention/templates/files/etc/ldap/slapd.conf.d/
root@Bremen:~# ls -lah /etc/univention/templates/files/etc/ldap/slapd.conf.d/65ldap-readonly.acl
-rw-r--r-- 1 root nogroup 257 Sep 11 18:43 /etc/univention/templates/files/etc/ldap/slapd.conf.d/65ldap-readonly.acl

Documentation


See also: