fix(PROJ-55): Tenant-Isolation für Rolle "auditor" + Audit-Log korrigieren
Kritischer Sicherheitsbug: Auditoren mit zugewiesenem Tenant sahen Mails und Audit-Log-Einträge anderer Tenants (DSGVO-relevant). auditor wird jetzt analog zu domain_auditor pro Tenant gescoped, sofern tenant_id gesetzt ist (Abwärtskompatibilität: ohne tenant_id bleibt der bisherige globale Zugriff erhalten). Betrifft Mail-Suche, Mail-Detailzugriff, Export, eDiscovery, Threads, OCR sowie das Audit-Log (DB + tamper-evidentes Flat-File), inkl. Befüllung von tenant_id an allen Audit-Log-Schreibstellen.
This commit is contained in:
@@ -36,6 +36,22 @@ func (s *Server) handleGetThread(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// PROJ-55: a global auditor (no tenant_id) may only see mails without a
|
||||
// tenant assignment. A tenant-scoped auditor (tenant_id set) is already
|
||||
// constrained by GetMailsByThread's tenant filter above.
|
||||
var auditorAllowed map[string]struct{}
|
||||
if auditorIsGlobal(sess) {
|
||||
noTenant, idErr := s.store.GetAllIDsWithoutTenant(r.Context())
|
||||
if idErr != nil {
|
||||
writeError(w, http.StatusInternalServerError, "access check failed")
|
||||
return
|
||||
}
|
||||
auditorAllowed = make(map[string]struct{}, len(noTenant))
|
||||
for _, nid := range noTenant {
|
||||
auditorAllowed[nid] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
type mailSummary struct {
|
||||
ID string `json:"id"`
|
||||
From string `json:"from,omitempty"`
|
||||
@@ -63,6 +79,13 @@ func (s *Server) handleGetThread(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// global auditor isolation: skip mails that belong to a tenant.
|
||||
if auditorAllowed != nil {
|
||||
if _, ok := auditorAllowed[id]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var dateStr string
|
||||
if !pm.Date.IsZero() {
|
||||
dateStr = pm.Date.UTC().Format(time.RFC3339)
|
||||
|
||||
Reference in New Issue
Block a user