Files
openldap/README.md
T

272 lines
6.4 KiB
Markdown

# 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: <distinguished name>
<attrdesc>: <attrvalue>
<attrdesc>: <attrvalue>
...
```
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_KDC_HOST` | — | Hostname of the Kerberos KDC |
| `LDAP_HOSTNAME` | — | Hostname matching the `ldap/<host>@REALM` service principal |
| `KRB5_KTNAME` | `/etc/krb5.keytab` | Path to the keytab inside the container |
### Principal-to-DN mapping
| Kerberos principal | LDAP DN |
|---|---|
| `*/admin@REALM` | `cn=admin,<base_dn>` |
| `username@REALM` | `uid=username,ou=users,<base_dn>` |
### 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/krb5.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`