Files
Assetmanager/app/privacy.py
T

547 lines
31 KiB
Python
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.
from __future__ import annotations
from copy import deepcopy
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
import json
import os
PRIVACY_AUDIT_LOG = Path(os.getenv("PRIVACY_AUDIT_LOG", "/app/data/logs/privacy-policy-audit.log"))
DEFAULT_PURPOSES = [
"Inventory of company computers and servers",
"Technical support and troubleshooting",
"Remote access to desktop, terminal and file system",
"Installation and maintenance of software",
"Execution of administrative commands and scripts",
"Security and patch management",
"Traceability of administrative interventions",
"Device management through an asset management system",
]
DEFAULT_TOMS = [
"Self-hosted deployment as Docker containers",
"Application is restricted to the internal network",
"Encrypted connections between clients and servers",
"Access restricted to a small group of administrators and IT support staff",
"Role-based access control and LDAP/local authentication",
"Protected local emergency administrator for LDAP outages",
"Database and host access restricted to authorized administrators",
"Regular backups with controlled retention",
"Logging of administrative actions and deletion-policy changes",
"Regular patching and update procedures",
]
DEFAULT_CATEGORIES: list[dict[str, Any]] = [
{
"key": "am_user_accounts",
"name": "AssetManager user accounts",
"system": "AssetManager / LDAP-AD",
"data_subjects": "Administrators and IT support staff",
"personal_data": "Name, username, email address, optional AD image, permissions, timestamps, authentication source and local password hash",
"purpose": "Authentication, authorization and traceability of administrative activity",
"retention_type": "manual_parent_delete",
"retention_days": None,
"retention_trigger": "Account deletion after authorization and operational retention checks",
"automatic_possible": False,
"automatic_enabled": False,
"manual_procedure": "Disable the account first; delete it manually when it is no longer needed. Protected emergency administrators cannot be deleted.",
"backup_handling": "Removed through the regular backup rotation; repeat deletion after a restore.",
"responsible": "IT",
"notes": "LDAP passwords are not stored. Local passwords are stored only as password hashes.",
},
{
"key": "am_asset_identity",
"name": "Asset and device master data",
"system": "AssetManager",
"data_subjects": "Employees whose devices are managed",
"personal_data": "Computer name, IP address, MAC address, assigned user, department, location, currently logged-on user and device identifiers",
"purpose": "Inventory, support, security and device management",
"retention_type": "overwrite_parent_delete",
"retention_days": None,
"retention_trigger": "Values are overwritten by later inventories; final deletion with the asset",
"automatic_possible": False,
"automatic_enabled": False,
"manual_procedure": "Delete or anonymize the asset after it is decommissioned and no longer needed for operational or evidentiary purposes.",
"backup_handling": "Removed through backup rotation; repeat deletion after a restore.",
"responsible": "IT",
"notes": "Current values may be updated or overwritten during synchronization.",
},
{
"key": "am_software_inventory",
"name": "Software inventory",
"system": "AssetManager",
"data_subjects": "Employees whose devices are managed",
"personal_data": "Software names, versions, publishers, installation information and linked asset/device identity",
"purpose": "Software inventory, maintenance, security and future licence management",
"retention_type": "overwrite_parent_delete",
"retention_days": None,
"retention_trigger": "Replaced by the next successful inventory; final deletion with the asset",
"automatic_possible": True,
"automatic_enabled": False,
"manual_procedure": "Delete the asset or run a new inventory. Excluded software is not stored.",
"backup_handling": "Removed through backup rotation.",
"responsible": "IT",
"notes": "The current implementation replaces the inventory of an asset during a successful import.",
},
{
"key": "am_job_metadata",
"name": "Job metadata and administrative activity",
"system": "AssetManager",
"data_subjects": "Administrators, IT support staff and employees whose devices are managed",
"personal_data": "Job ID, asset, job type, status, timestamps, initiating user and execution history",
"purpose": "Execution control, troubleshooting and traceability of administrative interventions",
"retention_type": "days",
"retention_days": 365,
"retention_trigger": "Job completion",
"automatic_possible": True,
"automatic_enabled": False,
"manual_procedure": "Delete old job history through an approved deletion run after checking audit requirements.",
"backup_handling": "Removed through backup rotation.",
"responsible": "IT",
"notes": "Suggested value; must be approved by the data protection officer.",
},
{
"key": "am_job_payloads",
"name": "Job scripts, output, callback payloads and diagnostics",
"system": "AssetManager",
"data_subjects": "Administrators, IT support staff and employees whose devices are managed",
"personal_data": "Scripts, commands, standard output, error output, callback data and technical diagnostics which may contain usernames or device information",
"purpose": "Troubleshooting and verification of job execution",
"retention_type": "days",
"retention_days": 90,
"retention_trigger": "Job completion or final failure",
"automatic_possible": True,
"automatic_enabled": False,
"manual_procedure": "Remove contents after the troubleshooting period while retaining only necessary job metadata.",
"backup_handling": "Removed through backup rotation.",
"responsible": "IT",
"notes": "Callback debug logging should remain disabled unless required for troubleshooting.",
},
{
"key": "am_diagnostic_logs",
"name": "Application, LDAP and diagnostic logs",
"system": "AssetManager",
"data_subjects": "Administrators, IT support staff and employees whose devices are managed",
"personal_data": "Usernames, timestamps, device names, IP addresses, authentication results and error details",
"purpose": "Security monitoring and troubleshooting",
"retention_type": "days",
"retention_days": 30,
"retention_trigger": "Log entry creation",
"automatic_possible": True,
"automatic_enabled": False,
"manual_procedure": "Delete or rotate logs after the retention period; use detailed LDAP debug only temporarily.",
"backup_handling": "Logs in backups expire through backup rotation.",
"responsible": "IT",
"notes": "Detailed LDAP debug logs should have a shorter operational lifetime, for example 714 days.",
},
{
"key": "am_deletion_logs",
"name": "Deletion run and policy audit log",
"system": "AssetManager",
"data_subjects": "Administrators and IT support staff",
"personal_data": "Executing administrator, timestamps, rule identifier, counts and result; no deleted content",
"purpose": "Proof and traceability of deletion processes",
"retention_type": "days",
"retention_days": 730,
"retention_trigger": "Policy change or deletion run",
"automatic_possible": True,
"automatic_enabled": False,
"manual_procedure": "Remove old audit entries only after the evidence period and DPO approval.",
"backup_handling": "Removed through backup rotation.",
"responsible": "IT / Data protection",
"notes": "The log must not reproduce the deleted personal data.",
},
{
"key": "mc_accounts",
"name": "LDAP/AD user accounts and profile information",
"system": "MeshCentral",
"data_subjects": "Administrators and IT support staff",
"personal_data": "Username, display name and optional email address",
"purpose": "Authentication and administration of remote support",
"retention_type": "external_manual",
"retention_days": None,
"retention_trigger": "Manual deletion of the MeshCentral account",
"automatic_possible": False,
"automatic_enabled": False,
"manual_procedure": "Delete the account manually in MeshCentral. Profile information is deleted with the account.",
"backup_handling": "Subject to MeshCentral and backup retention.",
"responsible": "IT",
"notes": "No automatic deletion in the standard configuration.",
},
{
"key": "mc_device_current",
"name": "Current MeshCentral device, network and logged-on-user data",
"system": "MeshCentral",
"data_subjects": "Employees whose devices are managed",
"personal_data": "Computer name, current IP and MAC address, current logged-on user and device identity",
"purpose": "Remote support, inventory and device management",
"retention_type": "external_overwrite_parent_delete",
"retention_days": None,
"retention_trigger": "Values are updated/overwritten; final deletion with the device",
"automatic_possible": False,
"automatic_enabled": False,
"manual_procedure": "Delete the device manually in MeshCentral when it is no longer managed.",
"backup_handling": "Subject to MeshCentral and backup retention.",
"responsible": "IT",
"notes": "No fixed retention period for the current value.",
},
{
"key": "mc_events_10_20",
"name": "Historical IP, online and device events",
"system": "MeshCentral",
"data_subjects": "Employees whose devices are managed and support staff",
"personal_data": "Historical online status, IP addresses, device events and timestamps",
"purpose": "Remote support, troubleshooting and traceability",
"retention_type": "external_days",
"retention_days": 20,
"retention_trigger": "Event creation",
"automatic_possible": False,
"automatic_enabled": False,
"manual_procedure": "Configure the relevant MeshCentral event retention. Individual event types may use 10 or 20 days.",
"backup_handling": "Subject to MeshCentral database backup rotation.",
"responsible": "IT",
"notes": "The exact period depends on the MeshCentral event type.",
},
{
"key": "mc_support_sessions",
"name": "Support connection timestamps and duration",
"system": "MeshCentral",
"data_subjects": "Employees whose devices are supported and support staff",
"personal_data": "Connection start, end, duration, user/device reference and support activity",
"purpose": "Remote support and traceability",
"retention_type": "external_days",
"retention_days": 20,
"retention_trigger": "Connection event creation",
"automatic_possible": False,
"automatic_enabled": False,
"manual_procedure": "Configure MeshCentral event retention and verify it regularly.",
"backup_handling": "Subject to MeshCentral database backup rotation.",
"responsible": "IT",
"notes": "Treated as general events in the current concept.",
},
{
"key": "mc_live_content",
"name": "Screen, clipboard and transferred session content",
"system": "MeshCentral / endpoints",
"data_subjects": "Employees whose devices are supported",
"personal_data": "Screen content, clipboard content and transferred files",
"purpose": "Live remote support and file transfer",
"retention_type": "not_stored",
"retention_days": None,
"retention_trigger": "Not applicable",
"automatic_possible": False,
"automatic_enabled": False,
"manual_procedure": "No server-side deletion is required when content is only transmitted live. Files remain on source or target devices and must be handled there.",
"backup_handling": "Not applicable to MeshCentral if no copy is stored.",
"responsible": "IT / endpoint owner",
"notes": "Standard configuration does not permanently store these contents on the server.",
},
{
"key": "mc_recordings",
"name": "Screenshots and session recordings",
"system": "MeshCentral / support workstation",
"data_subjects": "Employees whose devices are supported and support staff",
"personal_data": "Screenshots, screen recordings, usernames, device identity and session timestamps",
"purpose": "Support documentation, if separately authorized",
"retention_type": "external_manual",
"retention_days": None,
"retention_trigger": "Manual creation or configured recording retention",
"automatic_possible": False,
"automatic_enabled": False,
"manual_procedure": "Local screenshots and recordings must be deleted by the support employee. Server-side recordings are disabled by default; if enabled, configure maxRecordingDays.",
"backup_handling": "Depends on local workstation and MeshCentral backup configuration.",
"responsible": "IT / support employee",
"notes": "Without maxRecordingDays, server-side recordings have no automatic retention limit.",
},
]
PROTECTED_PRIVACY_CATEGORY_KEYS = frozenset(str(item.get("key")) for item in DEFAULT_CATEGORIES)
DEFAULT_PRIVACY_SETTINGS: dict[str, Any] = {
"processing_activity": {
"title": "Remote support, software inventory and asset management",
"responsible_department": "IT",
"responsible_people": "",
"controller": "",
"data_protection_contact": "",
"legal_basis": "To be reviewed and approved by the data protection officer",
"data_subject_groups": "Employees whose computers are managed; administrators and IT support staff",
"internal_recipients": "Authorized IT administrators and IT support staff",
"external_recipients": "None",
"third_country_transfer": False,
"third_country_details": "No transfer intended",
"systems": "AssetManager, MeshCentral, Active Directory/LDAP, managed endpoints and backup system",
"backup_system": "",
"backup_retention_days": None,
"restore_deletion_procedure": "After a restore, deletion runs must be repeated for data deleted since the backup was created.",
"review_interval_months": 12,
"last_reviewed_at": "",
"approved_by": "",
"document_version": "1.0",
"purposes": deepcopy(DEFAULT_PURPOSES),
"toms": deepcopy(DEFAULT_TOMS),
},
"categories": deepcopy(DEFAULT_CATEGORIES),
"phase": 2,
"automatic_deletion_available": False,
}
def merge_privacy_settings(raw: Any) -> dict[str, Any]:
result = deepcopy(DEFAULT_PRIVACY_SETTINGS)
if not isinstance(raw, dict):
return result
activity = raw.get("processing_activity")
if isinstance(activity, dict):
result["processing_activity"].update(activity)
categories = raw.get("categories")
if isinstance(categories, list) and categories:
result["categories"] = [normalize_category(item, index) for index, item in enumerate(categories) if isinstance(item, dict)]
present_keys = {str(item.get("key") or "") for item in result["categories"]}
for default_category in DEFAULT_CATEGORIES:
if str(default_category.get("key") or "") not in present_keys:
result["categories"].append(normalize_category(default_category, len(result["categories"])))
result["phase"] = 2
result["automatic_deletion_available"] = False
return result
def normalize_category(item: dict[str, Any], index: int = 0) -> dict[str, Any]:
days = item.get("retention_days")
try:
days = int(days) if days not in (None, "") else None
except (TypeError, ValueError):
days = None
return {
"key": str(item.get("key") or f"custom_{index + 1}")[:100],
"name": str(item.get("name") or "")[:250],
"system": str(item.get("system") or "")[:200],
"data_subjects": str(item.get("data_subjects") or "")[:1000],
"personal_data": str(item.get("personal_data") or "")[:4000],
"purpose": str(item.get("purpose") or "")[:4000],
"retention_type": str(item.get("retention_type") or "manual")[:80],
"retention_days": max(0, days) if days is not None else None,
"retention_trigger": str(item.get("retention_trigger") or "")[:1000],
"automatic_possible": bool(item.get("automatic_possible")),
"automatic_enabled": False,
"manual_procedure": str(item.get("manual_procedure") or "")[:4000],
"backup_handling": str(item.get("backup_handling") or "")[:2000],
"responsible": str(item.get("responsible") or "")[:500],
"notes": str(item.get("notes") or "")[:4000],
}
def append_privacy_audit(action: str, changed_by: str, details: dict[str, Any]) -> None:
PRIVACY_AUDIT_LOG.parent.mkdir(parents=True, exist_ok=True)
record = {
"timestamp_utc": datetime.now(timezone.utc).isoformat(),
"action": action,
"changed_by": changed_by or "unknown",
"details": details,
}
with PRIVACY_AUDIT_LOG.open("a", encoding="utf-8") as handle:
handle.write(json.dumps(record, ensure_ascii=False, sort_keys=True) + "\n")
def privacy_audit_tail(limit: int = 100) -> list[dict[str, Any]]:
if not PRIVACY_AUDIT_LOG.exists():
return []
try:
lines = PRIVACY_AUDIT_LOG.read_text(encoding="utf-8", errors="replace").splitlines()[-max(1, limit):]
except OSError:
return []
result: list[dict[str, Any]] = []
for line in reversed(lines):
try:
result.append(json.loads(line))
except json.JSONDecodeError:
continue
return result
_GERMAN_ACTIVITY = {
"title": "Fernwartung, Softwareinventarisierung und Assetmanagement",
"responsible_department": "IT",
"legal_basis": "Vom Datenschutzbeauftragten zu prüfen und freizugeben",
"data_subject_groups": "Beschäftigte, deren Computer verwaltet werden; Administratoren und IT-Support-Mitarbeitende",
"internal_recipients": "Berechtigte IT-Administratoren und IT-Support-Mitarbeitende",
"external_recipients": "Keine",
"third_country_details": "Keine Übermittlung vorgesehen",
"systems": "AssetManager, MeshCentral, Active Directory/LDAP, verwaltete Endgeräte und Backup-System",
"restore_deletion_procedure": "Nach einer Wiederherstellung werden Löschläufe für Daten wiederholt, die seit Erstellung der Sicherung gelöscht wurden.",
"purposes": [
"Inventarisierung betrieblicher Computer und Server",
"Technischer Support und Fehlerbehebung",
"Fernzugriff auf Desktop, Terminal und Dateisystem",
"Installation und Wartung von Software",
"Ausführung administrativer Befehle und Skripte",
"Sicherheits- und Patchmanagement",
"Nachvollziehbarkeit administrativer Eingriffe",
"Geräteverwaltung über ein Assetmanagement-System",
],
"toms": [
"Selbst gehosteter Betrieb als Docker-Container",
"Anwendung ist auf das interne Netzwerk beschränkt",
"Verschlüsselte Verbindungen zwischen Clients und Servern",
"Zugriff nur für einen kleinen Kreis von Administratoren und IT-Support-Mitarbeitenden",
"Rollenbasierte Zugriffskontrolle und LDAP-/lokale Authentifizierung",
"Geschützter lokaler Notfall-Administrator bei LDAP-Ausfällen",
"Datenbank- und Hostzugriff nur für berechtigte Administratoren",
"Regelmäßige Sicherungen mit kontrollierter Aufbewahrung",
"Protokollierung administrativer Aktionen und Änderungen des Löschkonzepts",
"Regelmäßige Patch- und Updateverfahren",
],
}
_GERMAN_CATEGORIES = {
"am_user_accounts": {
"name": "AssetManager-Benutzerkonten",
"data_subjects": "Administratoren und IT-Support-Mitarbeitende",
"personal_data": "Name, Benutzername, E-Mail-Adresse, optionales AD-Bild, Berechtigungen, Zeitstempel, Authentifizierungsquelle und lokaler Passwort-Hash",
"purpose": "Authentifizierung, Autorisierung und Nachvollziehbarkeit administrativer Tätigkeiten",
"retention_trigger": "Kontolöschung nach Freigabe und Prüfung betrieblicher Nachweispflichten",
"manual_procedure": "Konto zunächst deaktivieren und manuell löschen, sobald es nicht mehr benötigt wird. Geschützte Notfall-Administratoren können nicht gelöscht werden.",
"backup_handling": "Entfernung durch reguläre Backuprotation; nach Wiederherstellung Löschung erneut ausführen.",
"notes": "LDAP-Passwörter werden nicht gespeichert. Lokale Passwörter werden nur als Passwort-Hash gespeichert.",
},
"am_asset_identity": {
"name": "Asset- und Geräte-Stammdaten",
"data_subjects": "Beschäftigte, deren Geräte verwaltet werden",
"personal_data": "Computername, IP-Adresse, MAC-Adresse, zugeordneter Benutzer, Abteilung, Standort, aktuell angemeldeter Benutzer und Gerätekennungen",
"purpose": "Inventarisierung, Support, Sicherheit und Geräteverwaltung",
"retention_trigger": "Werte werden durch spätere Inventuren überschrieben; endgültige Löschung mit dem Asset",
"manual_procedure": "Asset nach Außerbetriebnahme und Ablauf betrieblicher oder nachweisbezogener Erfordernisse löschen oder anonymisieren.",
"backup_handling": "Entfernung durch Backuprotation; nach Wiederherstellung Löschung erneut ausführen.",
"notes": "Aktuelle Werte können bei Synchronisierungen aktualisiert oder überschrieben werden.",
},
"am_software_inventory": {
"name": "Softwareinventur",
"data_subjects": "Beschäftigte, deren Geräte verwaltet werden",
"personal_data": "Softwarename, Version, Hersteller, Installationsinformationen und Verknüpfung zur Asset-/Geräteidentität",
"purpose": "Softwareinventarisierung, Wartung, Sicherheit und spätere Lizenzverwaltung",
"retention_trigger": "Ersetzung durch die nächste erfolgreiche Inventur; endgültige Löschung mit dem Asset",
"manual_procedure": "Asset löschen oder neue Inventur durchführen. Ausgeschlossene Software wird nicht gespeichert.",
"backup_handling": "Entfernung durch Backuprotation.",
"notes": "Die aktuelle Implementierung ersetzt die Inventur eines Assets beim erfolgreichen Import.",
},
"am_job_metadata": {
"name": "Job-Metadaten und administrative Aktivitäten",
"data_subjects": "Administratoren, IT-Support-Mitarbeitende und Beschäftigte, deren Geräte verwaltet werden",
"personal_data": "Job-ID, Asset, Jobart, Status, Zeitstempel, auslösender Benutzer und Ausführungshistorie",
"purpose": "Ausführungssteuerung, Fehleranalyse und Nachvollziehbarkeit administrativer Eingriffe",
"retention_trigger": "Abschluss des Jobs",
"manual_procedure": "Alte Jobhistorie nach Prüfung der Nachweisanforderungen über einen freigegebenen Löschlauf löschen.",
"backup_handling": "Entfernung durch Backuprotation.",
"notes": "Vorschlagswert; durch den Datenschutzbeauftragten freizugeben.",
},
"am_job_payloads": {
"name": "Jobskripte, Ausgaben, Callback-Daten und Diagnosen",
"data_subjects": "Administratoren, IT-Support-Mitarbeitende und Beschäftigte, deren Geräte verwaltet werden",
"personal_data": "Skripte, Befehle, Standardausgabe, Fehlerausgabe, Callback-Daten und technische Diagnosen mit möglichen Benutzernamen oder Geräteinformationen",
"purpose": "Fehleranalyse und Nachweis der Jobausführung",
"retention_trigger": "Abschluss oder endgültiger Fehler des Jobs",
"manual_procedure": "Inhalte nach Ablauf der Fehleranalysefrist entfernen und nur erforderliche Job-Metadaten behalten.",
"backup_handling": "Entfernung durch Backuprotation.",
"notes": "Callback-Debugging soll nur bei konkretem Analysebedarf aktiviert werden.",
},
"am_diagnostic_logs": {
"name": "Anwendungs-, LDAP- und Diagnoseprotokolle",
"data_subjects": "Administratoren, IT-Support-Mitarbeitende und Beschäftigte, deren Geräte verwaltet werden",
"personal_data": "Benutzernamen, Zeitstempel, Gerätenamen, IP-Adressen, Anmeldeergebnisse und Fehlerdetails",
"purpose": "Sicherheitsüberwachung und Fehleranalyse",
"retention_trigger": "Erstellung des Protokolleintrags",
"manual_procedure": "Protokolle nach Ablauf der Frist löschen oder rotieren; ausführliches LDAP-Debugging nur vorübergehend verwenden.",
"backup_handling": "Protokolle in Sicherungen verfallen durch Backuprotation.",
"notes": "Ausführliche LDAP-Debugprotokolle sollten nur 714 Tage aufbewahrt werden.",
},
"am_deletion_logs": {
"name": "Löschlauf- und Richtlinienprotokoll",
"data_subjects": "Administratoren und IT-Support-Mitarbeitende",
"personal_data": "Ausführender Administrator, Zeitstempel, Regelkennung, Anzahlen und Ergebnis; keine gelöschten Inhalte",
"purpose": "Nachweis und Nachvollziehbarkeit von Löschprozessen",
"retention_trigger": "Änderung einer Regel oder Durchführung eines Löschlaufs",
"manual_procedure": "Alte Nachweise erst nach Ablauf der Nachweisfrist und Freigabe durch den Datenschutzbeauftragten entfernen.",
"backup_handling": "Entfernung durch Backuprotation.",
"notes": "Das Protokoll darf die gelöschten personenbezogenen Inhalte nicht erneut speichern.",
},
"mc_accounts": {
"name": "LDAP-/AD-Benutzerkonten und Profilinformationen",
"data_subjects": "Administratoren und IT-Support-Mitarbeitende",
"personal_data": "Benutzername, Anzeigename und optionale E-Mail-Adresse",
"purpose": "Authentifizierung und Verwaltung der Fernunterstützung",
"retention_trigger": "Manuelle Löschung des MeshCentral-Kontos",
"manual_procedure": "Konto manuell in MeshCentral löschen. Profilinformationen werden mit dem Konto gelöscht.",
"backup_handling": "Unterliegt der MeshCentral- und Backup-Aufbewahrung.",
"notes": "Keine automatische Löschung in der Standardkonfiguration.",
},
"mc_device_current": {
"name": "Aktuelle MeshCentral-Geräte-, Netzwerk- und Benutzerinformationen",
"data_subjects": "Beschäftigte, deren Geräte verwaltet werden",
"personal_data": "Computername, aktuelle IP- und MAC-Adresse, aktuell angemeldeter Benutzer und Geräteidentität",
"purpose": "Fernsupport, Inventarisierung und Geräteverwaltung",
"retention_trigger": "Werte werden aktualisiert/überschrieben; endgültige Löschung mit dem Gerät",
"manual_procedure": "Gerät manuell in MeshCentral löschen, wenn es nicht mehr verwaltet wird.",
"backup_handling": "Unterliegt der MeshCentral- und Backup-Aufbewahrung.",
"notes": "Keine feste Löschfrist für den aktuellen Wert.",
},
"mc_events_10_20": {
"name": "Historische IP-, Online- und Geräteereignisse",
"data_subjects": "Beschäftigte, deren Geräte verwaltet werden, und Support-Mitarbeitende",
"personal_data": "Historischer Onlinestatus, IP-Adressen, Geräteereignisse und Zeitstempel",
"purpose": "Fernsupport, Fehleranalyse und Nachvollziehbarkeit",
"retention_trigger": "Erstellung des Ereignisses",
"manual_procedure": "Passende MeshCentral-Ereignisaufbewahrung konfigurieren. Einzelne Ereignistypen verwenden 10 oder 20 Tage.",
"backup_handling": "Unterliegt der Rotation der MeshCentral-Datenbanksicherungen.",
"notes": "Die genaue Frist hängt vom MeshCentral-Ereignistyp ab.",
},
"mc_support_sessions": {
"name": "Zeitpunkt und Dauer von Supportverbindungen",
"data_subjects": "Beschäftigte, deren Geräte unterstützt werden, und Support-Mitarbeitende",
"personal_data": "Verbindungsbeginn, Ende, Dauer, Benutzer-/Gerätebezug und Supportaktivität",
"purpose": "Fernsupport und Nachvollziehbarkeit",
"retention_trigger": "Erstellung des Verbindungsereignisses",
"manual_procedure": "MeshCentral-Ereignisaufbewahrung konfigurieren und regelmäßig prüfen.",
"backup_handling": "Unterliegt der Rotation der MeshCentral-Datenbanksicherungen.",
"notes": "Im aktuellen Konzept als allgemeine Ereignisse behandelt.",
},
"mc_live_content": {
"name": "Bildschirm-, Zwischenablage- und Dateiübertragungsinhalte",
"data_subjects": "Beschäftigte, deren Geräte unterstützt werden",
"personal_data": "Bildschirminhalte, Zwischenablageinhalte und übertragene Dateien",
"purpose": "Live-Fernsupport und Dateiübertragung",
"retention_trigger": "Nicht anwendbar",
"manual_procedure": "Bei reiner Live-Übertragung ist keine serverseitige Löschung erforderlich. Dateien verbleiben auf Quell- oder Zielgeräten und müssen dort behandelt werden.",
"backup_handling": "Nicht auf MeshCentral anwendbar, wenn keine Kopie gespeichert wird.",
"responsible": "IT / Eigentümer des Endgeräts",
"notes": "Die Standardkonfiguration speichert diese Inhalte nicht dauerhaft auf dem Server.",
},
"mc_recordings": {
"name": "Screenshots und Sitzungsaufzeichnungen",
"data_subjects": "Beschäftigte, deren Geräte unterstützt werden, und Support-Mitarbeitende",
"personal_data": "Screenshots, Bildschirmaufzeichnungen, Benutzernamen, Geräteidentität und Sitzungszeitstempel",
"purpose": "Supportdokumentation, sofern gesondert autorisiert",
"retention_trigger": "Manuelle Erstellung oder konfigurierte Aufbewahrung für Aufzeichnungen",
"manual_procedure": "Lokale Screenshots und Aufzeichnungen durch Support-Mitarbeitende löschen. Serverseitige Aufzeichnungen sind standardmäßig deaktiviert; bei Aktivierung maxRecordingDays konfigurieren.",
"backup_handling": "Abhängig von lokaler Arbeitsstation und MeshCentral-Backupkonfiguration.",
"responsible": "IT / Support-Mitarbeitende",
"notes": "Ohne maxRecordingDays besteht für serverseitige Aufzeichnungen keine automatische Löschfrist.",
},
}
def localized_privacy_settings(raw: Any, language_code: str = "en") -> dict[str, Any]:
settings = merge_privacy_settings(raw)
for category in settings["categories"]:
category["is_system"] = category.get("key") in PROTECTED_PRIVACY_CATEGORY_KEYS
if not str(language_code or "").lower().startswith("de") or (isinstance(raw, dict) and raw):
return settings
settings["processing_activity"].update(deepcopy(_GERMAN_ACTIVITY))
for category in settings["categories"]:
override = _GERMAN_CATEGORIES.get(category.get("key"))
if override:
category.update(deepcopy(override))
category["is_system"] = category.get("key") in PROTECTED_PRIVACY_CATEGORY_KEYS
return settings