Added GSSAPI Authentication.
This commit is contained in:
@@ -5,6 +5,7 @@ RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
slapd \
|
||||
ldap-utils \
|
||||
libsasl2-modules-gssapi-mit \
|
||||
python3-jinja2 \
|
||||
python3-ldap3 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -210,3 +210,61 @@ ldapsearch -x -H ldap://localhost \
|
||||
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/<host>@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,<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/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`
|
||||
|
||||
@@ -17,6 +17,9 @@ SLAPD_D = Path("/etc/ldap/slapd.d")
|
||||
base_dn = os.environ.get("LDAP_BASE_DN") or "dc=example,dc=org"
|
||||
password = os.environ.get("LDAP_PASSWORD") or "changeit"
|
||||
tls_enabled = os.environ.get("TLS_ENABLED") == "1"
|
||||
kerberos_enabled = os.environ.get("KERBEROS_ENABLE") == "1"
|
||||
krb5_realm = os.environ.get("KRB5_REALM", "")
|
||||
krb5_sasl_host = os.environ.get("KRB5_SASL_HOST", "")
|
||||
admin_dn = f"cn=admin,{base_dn}"
|
||||
|
||||
|
||||
@@ -116,6 +119,9 @@ def main():
|
||||
apply_ldif(LDIF_DIR / "config-acl.ldif", env, base_dn=base_dn, admin_dn=admin_dn)
|
||||
if tls_enabled:
|
||||
apply_ldif(LDIF_DIR / "config-tls.ldif", env)
|
||||
if kerberos_enabled:
|
||||
apply_ldif(LDIF_DIR / "config-sasl.ldif", env,
|
||||
base_dn=base_dn, krb5_realm=krb5_realm, sasl_host=krb5_sasl_host)
|
||||
|
||||
print("cn=config updated.")
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
dn: cn=config
|
||||
changetype: modify
|
||||
replace: olcSaslHost
|
||||
olcSaslHost: {{ sasl_host }}
|
||||
-
|
||||
replace: olcSaslRealm
|
||||
olcSaslRealm: {{ krb5_realm }}
|
||||
-
|
||||
replace: olcAuthzRegexp
|
||||
olcAuthzRegexp: {0}uid=([^/]+)/admin,cn={{ krb5_realm | lower }},cn=gssapi,cn=auth cn=admin,{{ base_dn }}
|
||||
olcAuthzRegexp: {1}uid=([^,]+),cn={{ krb5_realm | lower }},cn=gssapi,cn=auth uid=$1,ou=users,{{ base_dn }}
|
||||
@@ -31,6 +31,15 @@ else
|
||||
echo "TLS : disabled"
|
||||
fi
|
||||
|
||||
kerberos_enabled="0"
|
||||
if [ "${KERBEROS_ENABLE:-0}" = "1" ]; then
|
||||
kerberos_enabled="1"
|
||||
export KRB5_KTNAME="${KRB5_KTNAME:-/etc/ldap/ldap.keytab}"
|
||||
echo "Kerberos : enabled (keytab: $KRB5_KTNAME)"
|
||||
else
|
||||
echo "Kerberos : disabled"
|
||||
fi
|
||||
|
||||
echo "Ensuring slapd runtime directory..."
|
||||
mkdir -p /var/run/slapd
|
||||
chown openldap:openldap /var/run/slapd
|
||||
@@ -59,6 +68,7 @@ EOF
|
||||
LDAP_BASE_DN="$base_dn" \
|
||||
LDAP_PASSWORD="$password" \
|
||||
TLS_ENABLED="$tls_enabled" \
|
||||
KERBEROS_ENABLE="$kerberos_enabled" \
|
||||
python3 -u /bootstrap/init.py
|
||||
else
|
||||
echo "Already initialised - skipping bootstrap."
|
||||
|
||||
@@ -3,3 +3,9 @@ LDAP_BASE_DN=dc=example,dc=org
|
||||
LDAP_ORG=Example Organization
|
||||
LDAP_PASSWORD=changeit
|
||||
LDAP_ADMIN_PASSWORD=changeit
|
||||
|
||||
# Kerberos SASL/GSSAPI (optional)
|
||||
KERBEROS_ENABLE=0
|
||||
KRB5_REALM=EXAMPLE.ORG
|
||||
KRB5_SASL_HOST=ldap.example.org
|
||||
KRB5_KTNAME=/etc/ldap/ldap.keytab
|
||||
|
||||
Reference in New Issue
Block a user