# LIAM NTFS AdditionalConfiguration Blacklist / Whitelist - Technischer Entwurf ## Ziel Dieses Dokument beschreibt einen kleinen technischen Entwurf, um dem NTFS-Provider ueber `AdditionalConfiguration` eine Blacklist und spaeter optional auch eine Whitelist fuer NTFS-Pfade mitzugeben. Die Policy soll klassifizierungsunabhaengig arbeiten und damit fuer Shares, DFS-Links, DFS-Namespaces und Folder dieselbe Matching-Logik verwenden. ## Ausgangslage Der NTFS-Provider verfuegt heute bereits ueber `AdditionalConfiguration`, nutzt diese im NTFS-Code aber im Wesentlichen nur fuer boolesche Feature-Flags. Die Ermittlung der DataAreas erfolgt aktuell rekursiv ueber: - Root-Aufbau in `getDataAreasAsync()` - Kind-Ermittlung in `GetChildDataAreasAsync()` - Dateisystem-Enumeration je Ebene ueber `ntfsBase.RequestFoldersListAsync(parentPath, 1)` Der bestehende Filter `ShouldIncludeDataArea()` wirkt nur auf den `DisplayName` und basiert auf `DataAreaRegEx`. Das ist fuer gezielte Ordnerausschluesse fachlich und technisch zu grob. ## Zielbild Die neue Logik soll eine explizite Pfad-Policy fuer den NTFS-Provider einfuehren. Diese Policy entscheidet fuer jeden gefundenen Pfad: - darf als DataArea materialisiert werden - darf weiter traversiert werden Ein ausgeschlossener Pfad soll weder als DataArea geliefert noch weiter traversiert werden. ## Vorgeschlagene Konfigurationsschluessel ### Aktueller Stand - `NtfsExcludePaths` - `NtfsIncludePaths` Beispiel: ```text NtfsExcludePaths=Archiv;*\Temp;Abteilung\Alt;\\server\share\legacy\* NtfsIncludePaths=Fachbereiche\*;Shares\Produktion\*;\\server\dfs\namespace\link\* ``` ## Aktueller Implementierungsstand Die nachfolgend beschriebene Path-Policy ist im NTFS-Provider inzwischen implementiert. ### 1. Materialisierung und Traversierung sind getrennt In `GetChildDataAreasAsync()` wird pro gefundenem Pfad heute getrennt entschieden: - darf der Pfad als DataArea geliefert werden - darf unterhalb des Pfads weiter traversiert werden Das ist wichtig fuer Include-Regeln. Ein Zwischenpfad darf fuer die Traversierung erlaubt sein, auch wenn erst ein tiefer liegendes Zielobjekt tatsaechlich auf der Whitelist steht. ### 2. Matching ist klassifizierungsunabhaengig Die Path-Policy arbeitet fuer: - `ServerRoot` - `ClassicShare` - `DfsNamespaceRoot` - `DfsLink` - `Folder` mit derselben Matching-Logik. Die Klassifikation bleibt fuer die fachliche Verarbeitung der DataArea relevant, nicht mehr fuer Blacklist-/Whitelist-Matching. ### 3. Relative und absolute Pfade werden parallel ausgewertet Jeder klassifizierte Pfad wird gegen mehrere Kandidaten gematcht: - relativer Pfad unterhalb von `RootPath` - normalisierter absoluter UNC-Pfad Dadurch koennen Regeln sowohl knapp relativ als auch explizit absolut formuliert werden. ### 4. Include-Regeln duerfen Traversierungs-Vorpfade freischalten Wenn `NtfsIncludePaths` gesetzt ist, darf ein Pfad auch dann traversiert werden, wenn er selbst noch nicht final matcht, aber zu einem spaeter passenden Zielpfad fuehren kann. Beispiel: ```text NtfsIncludePaths=Abteilung\IT\* ``` Dann darf `Abteilung` fuer die Traversierung erhalten bleiben, damit `Abteilung\IT\TeamA` ueberhaupt erreicht werden kann. ### 5. `LoadDataArea()` respektiert die Policy Direktes Laden eines Pfads ueber `LoadDataArea()` wird ebenfalls durch die Path-Policy eingeschraenkt. Ausnahme: - der konfigurierte `RootPath` selbst bleibt ladbar Damit kann die Filterung nicht einfach durch direktes Laden einer UID umgangen werden. ### 6. Permission-Management bleibt fachlich auf Folder beschraenkt `IsPermissionManagedFolderPath()` verwendet dieselbe generische Path-Policy, bleibt aber weiterhin nur fuer als `Folder` klassifizierte Pfade zulaessig. Die Path-Policy ist also klassifizierungsunabhaengig, das Berechtigungs-Handling selbst aber bewusst nicht. ### 7. Automatisches Permission-Ensure und Traverse `EnsureNtfsPermissionGroups` wird ebenfalls ueber `AdditionalConfiguration` gesteuert. Die Werte kommen aus `C4IT_GCC_DataArea_Collector_AdditionalAttributes` und werden beim Provider-Aufbau in `AdditionalConfiguration` uebernommen. Wenn `EnsureNtfsPermissionGroups=1` gesetzt ist, wird beim Laden von NTFS-Folder-DataAreas der Soll-Zustand fuer Berechtigungsgruppen sichergestellt: - Owner-/Write-/Read-Gruppen werden angelegt oder wiederverwendet - fehlende NTFS-ACLs werden auf dem Zielordner gesetzt - Traverse-Gruppen werden analog zur Ordner-Neuanlage verarbeitet Damit ist der nachtraegliche Ensure-Pfad fachlich mit der bestehenden Ordner-Neuanlage gleichgezogen. Share-Pfade bleiben gesondert ueber `EnsureNtfsPermissionGroupsForShares` behandelt; Traverse wird dabei nicht implizit fuer Shares erweitert. ### 8. Optionale Traverse-Boundary Die neue Einstellung `NtfsTraverseBoundaryPath` ist optional und wird ebenfalls aus `AdditionalConfiguration` gelesen. Ohne `NtfsTraverseBoundaryPath` bleibt die bestehende Traverse-Reichweite unveraendert. Die Verarbeitung folgt dann der bisherigen `baseFolder`-/`createTraverseGroupLvl`-Logik der Ordner-Neuanlage. Mit `NtfsTraverseBoundaryPath` kann die sichtbare Parent-Kette explizit erweitert werden. Die Traverse-Verarbeitung laeuft dann vom Parent des Zielordners bis inklusive dieser Boundary. Beispiel: ```text RootPath=\\SRVWSM001.imagoverum.com\file_shares\share2 EnsureNtfsPermissionGroups=1 NtfsTraverseBoundaryPath=\\SRVWSM001.imagoverum.com\file_shares ``` Fuer den Zielordner: ```text \\SRVWSM001.imagoverum.com\file_shares\share2\test33 ``` werden Traverse-Gruppen und Parent-ACLs fuer folgende Pfade sichergestellt: - `\\SRVWSM001.imagoverum.com\file_shares\share2` - `\\SRVWSM001.imagoverum.com\file_shares` Nicht verarbeitet wird der Serverroot `\\SRVWSM001.imagoverum.com`. Die Boundary muss ein Parent-Pfad des Zielordners sein und erreichbar sein. Ist das nicht der Fall, bricht der Ensure-/Create-Vorgang mit einer klaren Fehlermeldung ab, bevor Gruppen oder ACLs veraendert werden. ### 9. Traverse-Naming-Platzhalter Fuer Traverse-Naming-Conventions gibt es zusaetzliche optionale Platzhalter: - `{{TRAVERSE_NAME}}`: Name des aktuell verarbeiteten Traverse-Parents, z.B. `share2` - `{{TRAVERSE_VISIBLEPATH}}`: sichtbarer Parent-Pfad ab dem Parent der Boundary, segmentweise mit `_`, z.B. `file_shares_share2` Bestehende Platzhalter wie `{{NAME}}` und `{{RELATIVEPATH}}` bleiben unveraendert und behalten ihre bisherige Bedeutung. Beispiel fuer eine Traverse-Namenskonvention: ```text {{ADGroupPrefix}}_{{SCOPETAG}}_{{TRAVERSE_VISIBLEPATH}}{{_LOOP}}{{GROUPTYPEPOSTFIX}} ``` Bei: ```text ADGroupPrefix=ACL Filesystem_GroupGlobalTag=G Filesystem_GroupTraverseTag=_T ``` entstehen daraus z.B.: ```text ACL_G_FILE_SHARES_T ACL_G_FILE_SHARES_SHARE2_T ``` Wenn das Traverse-`NamingTemplate` leer ist, ist das kein Fehler. Es wird dann keine neue Traverse-Gruppe angelegt. Bestehende Gruppen werden aber weiterhin ueber ACLs und, sofern gepflegt, ueber `Wildcard` gesucht und konfiguriert. Sind `NamingTemplate` und `Wildcard` leer, ist die Traverse-Verarbeitung fuer diesen Parent ein No-op. ### 10. Root-Path-Platzhalter Naming Conventions koennen zusaetzlich Bestandteile des konfigurierten `RootPath` verwenden. Die Platzhalter funktionieren in `NamingTemplate`, `DescriptionTemplate` und `Wildcard`. Fuer: ```text RootPath=\\SRVWSM001.imagoverum.com\file_shares\share2 Zielpfad=\\SRVWSM001.imagoverum.com\file_shares\share2\test33 ``` stehen folgende Root-Platzhalter zur Verfuegung: - `{{ROOT_SERVER}}`: Serveranteil, z.B. `SRVWSM001.imagoverum.com` - `{{ROOT_NAME}}`: letzter Root-Segmentname, z.B. `share2` - `{{ROOT_PATH}}`: alle Root-Segmente nach dem Server, z.B. `file_shares_share2` - `{{ROOT_PATH(1)}}`: die letzten `n` Root-Segmente, z.B. `share2` - `{{ROOT_PATH(2)}}`: z.B. `file_shares_share2` - `{{ROOT_SEGMENT(0)}}`: erstes Root-Segment nach dem Server, z.B. `file_shares` - `{{ROOT_SEGMENT(1)}}`: zweites Root-Segment nach dem Server, z.B. `share2` Root-Segmente werden wie Ordnersegmente sanitisiert. Leerzeichen und Bindestriche werden zu `_`. Nicht vorhandene `ROOT_SEGMENT(n)`-Werte werden zu einem leeren String. Wenn `ROOT_PATH(n)` mehr Segmente anfordert als vorhanden sind, werden alle vorhandenen Root-Segmente verwendet. Beispiel: ```text {{ADGroupPrefix}}_{{ROOT_NAME}}.{{NAME}}{{GROUPTYPEPOSTFIX}} ``` ergibt fuer die Owner-Gruppe des Zielordners: ```text ACL_SHARE2.TEST33_O ``` Alternativ mit Namespace-/Root-Anteil: ```text {{ADGroupPrefix}}_{{ROOT_PATH(2)}}.{{NAME}}{{GROUPTYPEPOSTFIX}} ``` ergibt: ```text ACL_FILE_SHARES_SHARE2.TEST33_O ``` Die bestehenden Platzhalter `{{NAME}}`, `{{RELATIVEPATH}}`, `{{TRAVERSE_NAME}}` und `{{TRAVERSE_VISIBLEPATH}}` bleiben unveraendert. ## Matching-Regeln Empfohlene Semantik: - Trennzeichen fuer Mehrfachwerte: `;` - Auswertung case-insensitive - Leerzeichen an Eintraegen vor dem Match trimmen - Matching gegen relative Pfade unter `RootPath` und gegen normalisierte absolute UNC-Pfade - Interne Normalisierung auf konsistente UNC-/Directory-Notation - Zunaechst nur einfache Wildcards `*` unterstuetzen, keine freien Regex-Ausdruecke - Include-Regeln duerfen fuer die Traversierung auch uebergeordnete Pfade freischalten, wenn diese zu einem spaeter passenden Zielpfad fuehren Empfohlene Prioritaet: 1. Wenn keine Include-Regel gesetzt ist, sind alle Pfade grundsaetzlich erlaubt. 2. Wenn Include-Regeln gesetzt sind, sind nur passende Pfade erlaubt. 3. Exclude-Regeln werden danach angewendet und gewinnen bei Kollision. Das entspricht dem aktuell implementierten Verhalten. ## Beispiele ### 1. Einzelnen Teilbaum ausschliessen Konfiguration: ```text NtfsExcludePaths=Abteilung\Alt\* ``` Wirkung: - `Abteilung\Alt` und alles darunter wird nicht mehr als DataArea geliefert - unterhalb von `Abteilung\Alt` wird auch nicht weiter traversiert - andere Teilbaeume bleiben unveraendert sichtbar ### 2. Bestimmte Ordnernamen ueberall ausschliessen Konfiguration: ```text NtfsExcludePaths=*\Temp;*\Archiv ``` Wirkung: - jeder Pfad, dessen letzter oder einer spaeteren Segmente `Temp` oder `Archiv` entspricht, wird ausgeschlossen - das ist praktisch fuer technische oder historische Unterordner, die in vielen Shares gleich benannt sind ### 3. Nur einen Fachbereich sichtbar lassen Konfiguration: ```text NtfsIncludePaths=Fachbereiche\HR\* ``` Wirkung: - nur Pfade unterhalb von `Fachbereiche\HR` werden als DataAreas geliefert - notwendige Zwischenpfade wie `Fachbereiche` duerfen fuer die Traversierung erhalten bleiben - alle anderen Teilbaeume unterhalb von `RootPath` fallen aus der Ergebnismenge ### 4. Whitelist und Blacklist kombinieren Konfiguration: ```text NtfsIncludePaths=Fachbereiche\IT\* NtfsExcludePaths=Fachbereiche\IT\Test;Fachbereiche\IT\Alt\* ``` Wirkung: - grundsaetzlich ist nur `Fachbereiche\IT` relevant - innerhalb dieses Bereichs werden `Test` und der komplette Teilbaum `Alt` wieder ausgeschlossen - Exclude gewinnt also auch innerhalb eines eingeschraenkten Include-Bereichs ### 5. Absoluten UNC-Pfad fuer DFS-Link verwenden Konfiguration: ```text NtfsIncludePaths=\\server\dfs\namespace\link\Produktion\* ``` Wirkung: - die Regel greift auch dann, wenn der Root ueber DFS klassifiziert wird - benoetigte Vorpfade wie `\\server\dfs`, `\\server\dfs\namespace` und `\\server\dfs\namespace\link` duerfen fuer die Traversierung erhalten bleiben - dadurch kann ein bestimmter DFS-Zweig sehr gezielt freigegeben werden ### 6. Nur bestimmte Shares unter einem Server-Root zulassen Konfiguration: ```text NtfsIncludePaths=ShareA\*;ShareB\* ``` Voraussetzung: - `RootPath` zeigt auf einen Server-Root wie `\\fileserver` Wirkung: - nur Kinder unterhalb von `ShareA` und `ShareB` werden sichtbar - andere Shares des Servers werden nicht materialisiert und nicht weiter traversiert ### 7. Direktes Laden eines ausgeschlossenen Pfads Konfiguration: ```text NtfsExcludePaths=Abteilung\Alt\* ``` Wirkung: - ein direkter `LoadDataArea()` auf einen Pfad unterhalb von `Abteilung\Alt` liefert kein Objekt mehr - der konfigurierte `RootPath` selbst bleibt davon ausgenommen und kann weiterhin geladen werden ## Technische Einhaengepunkte ### 1. Provider-seitige Policy-Methoden Im NTFS-Provider existiert dafuer inzwischen eine kleine Policy-Schicht, insbesondere: - `GetAdditionalConfigurationValues(string key)` - `ShouldIncludeDataArea(...)` - `ShouldTraverseDataArea(...)` - `MatchesPathPolicy(...)` - `TryMatchPathPolicy(...)` - `CanPathLeadToPattern(...)` Die Methode `IsAdditionalConfigurationEnabled()` bleibt fuer boolesche Flags bestehen und wird durch Listen-/String-Helfer ergaenzt. ### 2. Anwendung in der DataArea-Traversierung Der erste und wichtigste Einhaengepunkt ist `GetChildDataAreasAsync()`. Dort wird heute jede gefundene Ebene verarbeitet und vor `BuildDataAreaAsync()` sowie vor dem rekursiven Abstieg durch die Path-Policy geprueft. Vorteil: - geringe Eingriffstiefe - kein Umbau der allgemeinen NTFS-Basis erforderlich - fachliche Wirkung genau dort, wo DataAreas erzeugt werden ### 3. Wiederverwendung fuer Permission-Management `IsPermissionManagedFolderPath()` bleibt fachlich auf Folder beschraenkt, verwendet fuer Black-/Whitelist aber dieselbe generische Path-Policy. Damit wird vermieden, dass ein Ordner zwar nicht mehr als DataArea sichtbar ist, aber weiterhin im Permission-Flow auftaucht. ### 4. Wiederverwendung fuer `LoadDataArea()` Auch `LoadDataArea()` verwendet die Path-Policy inzwischen, damit gefilterte Pfade nicht per Direktzugriff wieder sichtbar werden. ## Offene Abgrenzung Bewusst weiterhin nicht umgesetzt: - Umbau von `cNtfsBase` auf generische Filter-Callbacks - freie Regex-Konfiguration in `AdditionalConfiguration` - unterschiedliche Regeln je Klassifikationstyp Diese Themen koennen spaeter folgen, sind fuer den aktuellen Nutzen aber nicht noetig. ## Logging Fuer ausgeschlossene Pfade sollte auf `Debug` geloggt werden: - welcher Pfad verworfen wurde - welche Regel gegriffen hat - ob der Pfad nur nicht materialisiert oder auch nicht traversiert wurde Beispiel: ```text Skip NTFS path '\\server\share\IT\_disabled' due to AdditionalConfiguration rule 'NtfsExcludePaths=IT\_disabled' ``` Das ist wichtig, damit fehlende DataAreas spaeter im Betrieb nachvollziehbar bleiben. ## Empfohlener Umsetzungsplan 1. Listenparser fuer `AdditionalConfiguration` im NTFS-Provider einfuehren. 2. Pfadnormalisierung und Matching fuer relative sowie absolute Pfade kapseln. 3. `GetChildDataAreasAsync()` um `ShouldTraverseDataArea(...)` erweitern. 4. Debug-Logging fuer Skip-Faelle einfuehren. 5. Dieselbe Policy in `IsPermissionManagedFolderPath()` und `LoadDataArea()` wiederverwenden. Diese Punkte sind im aktuellen Implementierungsstand umgesetzt. ## Kurzfazit Die generische Path-Policy im NTFS-Provider ist klein genug fuer eine risikoarme Implementierung, passt in die vorhandene `AdditionalConfiguration`-Architektur und arbeitet ohne Sonderregeln pro Klassifikationstyp.