# OpenLDAP OpenLDAP 2.6 container running on Ubuntu 26.04 with cn=config (slapd-config) database. ## Optional Bootstrap Accounts CSV Files Bootstrap reads account files from `/bootstrap/accounts` inside the container. With the current compose setup, this maps to: `~/app-data/openldap/accounts` Optional files: - `users.csv`: `uid,gn,sn,mail` - `admins.csv`: `uid,gn,sn,mail` - `posix-users.csv`: `uid,gn,sn,mail,uidNumber,gidNumber` You can provide any subset of these files; missing files are skipped. Rows starting with `#` are ignored. ## Changing the password Use `ldappasswd` to change the password: ```bash BASE_DN="dc=koszewscy,dc=waw,dc=pl" USER_DN="cn=admin,$BASE_DN" ldappasswd -x -D "$USER_DN" -W -S "$USER_DN" ``` or use a oneliner: ```shell DN="cn=admin,dc=koszewscy,dc=waw,dc=pl" ldappasswd -x -D "$DN" -W -S "$DN" ``` Change the password for the Admin: `change_password.ldif`: ```ldif dn: olcDatabase={1}mdb,cn=config changetype: modify replace: olcRootPW olcRootPW: {SSHA}newhashedpassword ``` ```bash ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f change_password.ldif ``` ## LDIF file format The basic form of an entry is: ``` # comment dn: : : ... ``` Lines may be continued by starting the next line with a single space or tab. ``` dn: cn=Barbara J Jensen,dc=example,dc= com cn: Barbara J Jensen ``` is equivalent to: ``` dn: cn=Barbara J Jensen,dc=example,dc=com cn: Barbara J Jensen ``` Multiple values for the same attribute are represented by repeating the attribute description: ``` dn: cn=Barbara J Jensen,dc=example,dc=com cn: Barbara J Jensen cn: Babs Jensen ``` If an attribute value contains a non-printable character, it must be base64-encoded and prefixed with a single colon: ``` dn: cn=Barbara J Jensen,dc=example,dc=com cn:: QmFyYmFyYSBKIEplbnNlbgo= ``` Binary files (e.g. images) can be included in the LDIF file by using the "file:" prefix: ``` dn: cn=Barbara J Jensen,dc=example,dc=com jpegPhoto:< file:///home/bjensen/photo.jpg ``` Multiple entries are separated by a blank line. Binary files like the one above may also be included in as Base64-encoded values. The full specification is available at https://datatracker.ietf.org/doc/html/rfc2849. ## Accessing cn=config SASL EXTERNAL authenticates via the Unix socket — uid=0 maps to the cn=config superuser. The commands must run inside the container where the socket is accessible. ### Browse the entire cn=config tree ```bash ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=config ``` ### Browse a specific database entry ```bash ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b "olcDatabase={1}mdb,cn=config" ``` ### Modify cn=config ```bash ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<'EOF' dn: cn=config changetype: modify replace: olcLogLevel olcLogLevel: stats EOF ``` ### Verify EXTERNAL identity ```bash ldapwhoami -Q -Y EXTERNAL -H ldapi:/// ``` Expected: `dn:gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth` ## Editing Access Control Rules 1. Inserting a New Rule at the Top ```ldif # filename: insert_rule.ldif dn: olcDatabase={1}mdb,cn=config changetype: modify add: olcAccess olcAccess: {0}to * by dn.exact="cn=security-scanner,dc=example,dc=com" read break ``` 2. Deleting a Specific Rule ```ldif # filename: delete_rule.ldif dn: olcDatabase={1}mdb,cn=config changetype: modify delete: olcAccess olcAccess: {2} ``` 3. Updating an Existing Rule (In-Place) ```ldif # filename: update_rule.ldif dn: olcDatabase={1}mdb,cn=config changetype: modify replace: olcAccess olcAccess: {1}to attrs=userPassword by self write by anonymous auth by group.exact="cn=it-admins,dc=example,dc=com" write ``` 4. Reordering the Entire Stack ```ldif # filename: reorder_rules.ldif dn: olcDatabase={1}mdb,cn=config changetype: modify replace: olcAccess olcAccess: {0}to * by dn.exact="cn=security-scanner,dc=example,dc=com" read break olcAccess: {1}to attrs=userPassword by self write by anonymous auth by group.exact="cn=it-admins,dc=example,dc=com" write olcAccess: {2}to * by self read ``` ## Accessing the DIT ```bash ldapsearch -x -H ldap://localhost \ -D "cn=admin,dc=koszewscy,dc=waw,dc=pl" -W \ -b "dc=koszewscy,dc=waw,dc=pl" ``` ### Verify readonly service account bind ```bash ldapwhoami -x -H ldap://localhost \ -D "cn=readonly,ou=service-accounts,dc=koszewscy,dc=waw,dc=pl" -W ``` ## Kerberos SASL/GSSAPI Gate with `KERBEROS_ENABLE=1`. When enabled, slapd is configured at first-run bootstrap with SASL GSSAPI and two authz-regexp rules that map Kerberos principals to LDAP DNs. ### Environment variables | Variable | Default | Description | |---|---|---| | `KERBEROS_ENABLE` | `0` | Set to `1` to enable | | `KRB5_REALM` | — | Kerberos realm (uppercase, e.g. `EXAMPLE.ORG`) | | `KRB5_SASL_HOST` | — | Hostname matching the `ldap/@REALM` service principal | | `KRB5_KTNAME` | `/etc/ldap/ldap.keytab` | Path to the keytab inside the container | ### Principal-to-DN mapping | Kerberos principal | LDAP DN | |---|---| | `*/admin@REALM` | `cn=admin,` | | `username@REALM` | `uid=username,ou=users,` | ### Setup steps 1. In the Kerberos container, create the service principal and extract a keytab: ```bash kadmin.local -q "addprinc -randkey ldap/ldap.example.org@REALM" kadmin.local -q "ktadd -k /tmp/ldap.keytab ldap/ldap.example.org@REALM" ``` 2. Copy the keytab to the OpenLDAP host: ```bash container cp kerberos:/tmp/ldap.keytab ~/app-data/openldap/ldap.keytab ``` 3. Mount it into the OpenLDAP container at `KRB5_KTNAME` (default `/etc/ldap/ldap.keytab`) and set the Kerberos env vars in `openldap.env`. 4. On first start, bootstrap applies the SASL configuration automatically. For an already-initialised instance apply it manually: ```bash ldapmodify -Q -Y EXTERNAL -H ldapi:/// <<'EOF' dn: cn=config changetype: modify replace: olcSaslHost olcSaslHost: ldap.example.org - replace: olcSaslRealm olcSaslRealm: EXAMPLE.ORG - replace: olcAuthzRegexp olcAuthzRegexp: {0}uid=([^/]+)/admin,cn=example.org,cn=gssapi,cn=auth cn=admin,dc=example,dc=org olcAuthzRegexp: {1}uid=([^,]+),cn=example.org,cn=gssapi,cn=auth uid=$1,ou=users,dc=example,dc=org EOF ``` ### Test authentication ```bash kinit username@REALM ldapwhoami -Y GSSAPI -H ldap://ldap.example.org ``` Expected: `dn:uid=username,ou=users,dc=example,dc=org`