d360c9a5ba
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg) - Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist - Feature-Status auf In Review gesetzt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
110 lines
4.0 KiB
Markdown
110 lines
4.0 KiB
Markdown
---
|
|
id: PROJ-16
|
|
title: LDAP / Active Directory Anbindung
|
|
status: In Progress
|
|
priority: P1
|
|
created: 2026-03-13
|
|
---
|
|
|
|
# PROJ-16 — LDAP / Active Directory Anbindung
|
|
|
|
## Ziel
|
|
Authentifizierung gegen einen LDAP-Server (OpenLDAP, Microsoft Active Directory, Samba AD).
|
|
Lokale Accounts bleiben weiterhin nutzbar. LDAP-User werden beim ersten Login automatisch
|
|
in der Datenbank angelegt (`source: ldap`) und bei jedem Login synchronisiert.
|
|
|
|
## User Stories
|
|
|
|
- **Als Admin** möchte ich LDAP in `config.yml` konfigurieren, damit Mitarbeiter ihre
|
|
bestehenden Windows/AD-Zugangsdaten nutzen können.
|
|
- **Als Endnutzer** möchte ich mich mit meinem AD-Passwort anmelden, ohne einen separaten
|
|
archivmail-Account zu benötigen.
|
|
- **Als Admin** möchte ich LDAP-User einer Rolle (user/auditor/admin) zuweisen können,
|
|
entweder per fester Zuordnung oder über AD-Gruppen.
|
|
- **Als Admin** möchte ich LDAP deaktivieren können, ohne den restlichen Betrieb zu stören.
|
|
|
|
## Akzeptanzkriterien
|
|
|
|
- [ ] Login mit LDAP-Credentials funktioniert wenn `ldap.enabled: true`
|
|
- [ ] Lokale Accounts funktionieren weiterhin (Fallback wenn LDAP fehlschlägt oder deaktiviert)
|
|
- [ ] LDAP-User werden beim Login automatisch via `UpsertLDAPUser` angelegt/aktualisiert
|
|
- [ ] Rollen-Mapping via AD-Gruppen konfigurierbar (optional, Fallback: default_role)
|
|
- [ ] STARTTLS und LDAPS (Port 636) werden unterstützt
|
|
- [ ] Bind-User (Service Account) für AD-Suche konfigurierbar
|
|
- [ ] Fehlermeldung bei falschem Passwort ist identisch zu lokalem Login (kein Info-Leak)
|
|
- [ ] LDAP-Fehler landen im Audit-Log
|
|
- [ ] Konfigurierbar per `config.yml` Abschnitt `ldap:`
|
|
|
|
## Konfigurationsformat (`config.yml`)
|
|
|
|
```yaml
|
|
ldap:
|
|
enabled: true
|
|
url: "ldap://192.168.1.10:389" # oder ldaps://...
|
|
bind_dn: "CN=archivmail-svc,OU=ServiceAccounts,DC=corp,DC=local"
|
|
bind_password: "geheim"
|
|
base_dn: "OU=Users,DC=corp,DC=local"
|
|
user_filter: "(sAMAccountName=%s)" # %s wird durch eingegebenen Username ersetzt
|
|
tls: false # STARTTLS
|
|
tls_skip_verify: false
|
|
default_role: "user" # Rolle für neue LDAP-User
|
|
group_mappings: # optional: AD-Gruppe → archivmail-Rolle
|
|
- group_dn: "CN=archivmail-admins,OU=Groups,DC=corp,DC=local"
|
|
role: "admin"
|
|
- group_dn: "CN=archivmail-auditors,OU=Groups,DC=corp,DC=local"
|
|
role: "auditor"
|
|
```
|
|
|
|
## Technische Umsetzung
|
|
|
|
### Neues Paket: `internal/ldapauth`
|
|
|
|
```
|
|
internal/ldapauth/
|
|
ldap.go — Client, Bind, Search, Authenticate
|
|
ldap_test.go — Tests mit Mock-LDAP
|
|
```
|
|
|
|
**Abhängigkeit:** `github.com/go-ldap/ldap/v3`
|
|
|
|
### Ablauf Login mit LDAP
|
|
|
|
1. `auth.Manager.Login(username, password)` prüft zuerst lokale DB
|
|
2. Wenn lokaler User nicht gefunden UND LDAP aktiviert → LDAP-Auth versuchen
|
|
3. LDAP-Bind mit Service Account → User-DN per `user_filter` suchen
|
|
4. User-Bind mit gefundener DN + eingegebenem Passwort
|
|
5. Optional: Gruppen-Mitgliedschaft abfragen → Rolle bestimmen
|
|
6. `userstore.UpsertLDAPUser(username, email, role)` aufrufen
|
|
7. JWT-Token wie bei lokalem Login ausstellen
|
|
|
|
### Felder aus LDAP lesen
|
|
|
|
| LDAP-Attribut | archivmail-Feld |
|
|
|--------------|-----------------|
|
|
| `sAMAccountName` / `uid` | username |
|
|
| `mail` | email |
|
|
| `memberOf` | → Gruppen-Mapping → role |
|
|
| `displayName` | (für spätere Anzeige) |
|
|
|
|
### API-Endpunkt: `GET /api/admin/ldap/test` (admin only)
|
|
|
|
Testet die LDAP-Verbindung und gibt Status zurück:
|
|
```json
|
|
{"ok": true, "message": "LDAP-Verbindung erfolgreich", "users_found": 42}
|
|
```
|
|
|
|
## Nicht in diesem Feature
|
|
|
|
- Automatische User-Synchronisation (Bulk-Import aller AD-User) — separates Feature
|
|
- LDAP-Gruppen als Postfach-Zuweisungen
|
|
- Kerberos / SAML / OAuth2 (separate Features)
|
|
|
|
## Dateien
|
|
|
|
- `internal/ldapauth/ldap.go` (neu)
|
|
- `internal/auth/auth.go` (erweitert: LDAP-Fallback)
|
|
- `config/config.go` (erweitert: `LDAPConfig`)
|
|
- `cmd/archivmail/main.go` (erweitert: LDAP-Client initialisieren)
|
|
- `internal/api/server.go` (erweitert: `/api/admin/ldap/test`)
|
|
- `install.sh` (erweitert: LDAP-Kommentar in config.yml)
|