547 lines
31 KiB
Python
547 lines
31 KiB
Python
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 7–14 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 7–14 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
|