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:
@@ -13,6 +13,15 @@ import (
|
||||
"archivmail/pkg/mailparser"
|
||||
)
|
||||
|
||||
// apiKeyTenantPtr converts an API-key session tenant id (0 = no tenant) into a
|
||||
// *int64 for audit logging (PROJ-55). Returns nil for the tenant-less case.
|
||||
func apiKeyTenantPtr(id int64) *int64 {
|
||||
if id == 0 {
|
||||
return nil
|
||||
}
|
||||
return &id
|
||||
}
|
||||
|
||||
// handleV1MethodNotAllowed returns 405 for non-GET methods on v1 endpoints.
|
||||
func (s *Server) handleV1MethodNotAllowed(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Allow", "GET")
|
||||
@@ -121,6 +130,7 @@ func (s *Server) handleV1SearchMails(w http.ResponseWriter, r *http.Request) {
|
||||
s.audlog.Log(audit.Entry{
|
||||
EventType: audit.EventSearch,
|
||||
Username: fmt.Sprintf("apikey:%s", akSess.KeyName),
|
||||
TenantID: apiKeyTenantPtr(akSess.TenantID),
|
||||
Query: q,
|
||||
Detail: fmt.Sprintf("v1_api contact=%s from=%s to=%s", contactFilter, fromFilter, toFilter),
|
||||
Success: true,
|
||||
@@ -217,6 +227,7 @@ func (s *Server) handleV1GetMail(w http.ResponseWriter, r *http.Request) {
|
||||
s.audlog.Log(audit.Entry{
|
||||
EventType: audit.EventMailView,
|
||||
Username: fmt.Sprintf("apikey:%s", akSess.KeyName),
|
||||
TenantID: apiKeyTenantPtr(akSess.TenantID),
|
||||
MailID: id,
|
||||
Detail: "v1_api",
|
||||
Success: true,
|
||||
@@ -303,6 +314,7 @@ func (s *Server) handleV1GetMailRaw(w http.ResponseWriter, r *http.Request) {
|
||||
s.audlog.Log(audit.Entry{
|
||||
EventType: audit.EventExport,
|
||||
Username: fmt.Sprintf("apikey:%s", akSess.KeyName),
|
||||
TenantID: apiKeyTenantPtr(akSess.TenantID),
|
||||
MailID: id,
|
||||
Detail: "v1_api raw download",
|
||||
Success: true,
|
||||
|
||||
Reference in New Issue
Block a user