Files
archivmail/cmd/archivmail/encryption_status.go
T
sysopsandClaude Sonnet 4.6 46096db802 feat(PROJ-49): Verschlüsselungspflicht at-rest sichtbar machen (Healthcheck & Warnung)
storage.loadKey() startet bei fehlendem/unlesbarem/ungültigem Keyfile
weiterhin unverschlüsselt (kein Hard-Fail), aber:
- einmalige WARN-Logzeile beim Start mit konkretem Grund
- neuer Healthcheck-Prüfpunkt "Encryption" in archivmail status
- Dashboard-API liefert encryption.enabled
- README: GoBD-Hinweis zu storage.keyfile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 20:01:38 +02:00

46 lines
1.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"encoding/base64"
"log/slog"
"os"
"strings"
)
// warnEncryptionStatus emits a single, clearly visible WARN log line at startup
// when the at-rest mail storage is not AES-256-encrypted (PROJ-49).
//
// It does not change the (backwards-compatible) behaviour of storage.loadKey():
// the service starts regardless. It only increases visibility so operators do
// not silently archive unencrypted mails on a GoBD installation.
//
// enabled is the result of (*storage.Store).EncryptionEnabled(); keyfile is the
// configured path (may be empty). When encryption is disabled the keyfile is
// inspected to log a concrete reason (missing path, unreadable file, wrong size).
func warnEncryptionStatus(logger *slog.Logger, keyfile string, enabled bool) {
if enabled {
logger.Info("Speicherverschlüsselung aktiv (AES-256-GCM at-rest)", "keyfile", keyfile)
return
}
switch {
case strings.TrimSpace(keyfile) == "":
logger.Warn("WARNUNG: Keine Verschlüsselung konfiguriert E-Mail-Speicher ist NICHT AES-256-verschlüsselt. " +
"Für GoBD-konforme produktive Installationen storage.keyfile setzen.")
default:
data, err := os.ReadFile(keyfile)
if err != nil {
logger.Warn("WARNUNG: Keyfile nicht lesbar E-Mail-Speicher ist NICHT AES-256-verschlüsselt",
"keyfile", keyfile, "err", err)
return
}
raw := strings.TrimSpace(string(data))
decoded, derr := base64.StdEncoding.DecodeString(raw)
if derr != nil {
decoded = []byte(raw)
}
logger.Warn("WARNUNG: Ungültiges Keyfile (≠ 32 Byte) E-Mail-Speicher ist NICHT AES-256-verschlüsselt",
"keyfile", keyfile, "bytes", len(decoded), "expected", 32)
}
}