10 KiB
LIAM NTFS / DFS Metadaten-Klassifikation - konkretes Umsetzungskonzept
Ziel
Dieses Dokument beschreibt die konkrete Zielumsetzung fuer die robuste Klassifikation von UNC-Pfaden im LIAM-NTFS-Provider.
Rahmenbedingungen:
- keine Erweiterung der bestehenden Provider-Config
- der Code darf nicht voraussetzen, auf dem DFS- oder SMB-Server selbst zu laufen
- DFS-Strukturen koennen unterschiedlich aufgebaut sein
- es muss sauber unterschieden werden zwischen:
- klassischem SMB-Share
- DFS-Namespace-Root
- DFS-Link
- echtem Folder
Die bestehende Config liefert dafuer nur den Einstiegspunkt und die Zugriffsrechte:
RootPathDomainCredential
Die eigentliche Typbestimmung muss daher zur Laufzeit ueber Metadaten des adressierten UNC-Pfads erfolgen.
Kurzfazit
Die robuste Loesung ist:
- UNC-Pfad normalisieren
- DFS-Metadaten fuer den Pfad und relevante Praefixe abfragen
- wenn kein DFS-Treffer vorliegt, SMB-Share-Metadaten abfragen
- alles unterhalb einer erkannten fachlichen Grenze als Folder behandeln
Die aktuelle Segment-Heuristik wird damit ersetzt, nicht nur verbessert.
Fachregeln
Es gelten folgende semantische Regeln:
\\server\\namespaceist einDfsNamespaceRoot, wenn der Pfad als DFS-Namespace-Root aufgeloest werden kann.\\server\\namespace\\linkist einDfsLink, wenn der Pfad als DFS-Link aufgeloest werden kann.\\server\\shareist einClassicShare, wenn der Share auf dem Server publiziert ist und kein DFS-Treffer vorliegt.- jeder Pfad unterhalb eines
DfsLinkist einFolder - jeder Pfad unterhalb eines
ClassicShareist einFolder - jeder Pfad unterhalb eines
DfsNamespaceRoot, aber oberhalb einesDfsLink, ist nur dannFolder, wenn er kein DFS-Link ist und fachlich wirklich Dateisystemstruktur repraesentiert; fuer den Normalfall sind direkte Kinder eines Namespace-Roots als DFS-Links zu erwarten
Verwendbare Laufzeit-Metadaten
1. DFS-Metadaten
Primaere Quelle fuer DFS:
- Win32 DFS API, bevorzugt
NetDfsGetInfo
Damit kann fuer einen UNC-Pfad geprueft werden:
- ist der Pfad ein DFS-Objekt?
- handelt es sich um Root oder Link?
- welche Targets sind hinterlegt?
Wichtig:
- diese Abfrage funktioniert remote gegen den adressierten Namespace
- sie benoetigt keine lokale Ausfuehrung auf dem DFS-Server
- sie ist fachlich deutlich verlaesslicher als
Directory.Exists(...)
2. SMB-Share-Metadaten
Primaere Quelle fuer klassische Shares:
NetShareEnum- optional ergaenzend
NetShareGetInfo
Das ist fuer LIAM bereits teilweise vorhanden:
cNetworkConnection.EnumNetShares(server)
Damit kann geprueft werden:
- ob
\\server\\shareein echter publizierter SMB-Share ist - welche sichtbaren Disk-Shares auf dem Host existieren
3. Dateisystem-Metadaten
Nur fuer Folder:
Directory.ExistsDirectoryInfo
Diese Daten duerfen nicht fuer die Unterscheidung zwischen DFS und Share benutzt werden, sondern nur nachdem bereits eine fachliche Grenze erkannt wurde.
Nicht ausreichende Datenquellen
Folgende Informationen reichen fuer die Typbestimmung nicht aus:
- Anzahl der UNC-Segmente
RootPathalleineDirectory.Exists- ACLs
- Naming Conventions
- Custom Tags
- Group Strategy
Diese Daten koennen ergaenzend helfen, liefern aber keine robuste Aussage ueber DFS vs. SMB.
Zielmodell
Internes Modell:
ServerRootClassicShareDfsNamespaceRootDfsLinkFolderUnknown
Externe LIAM-Abbildung:
ClassicShare->NtfsShareDfsNamespaceRoot->DfsNamespaceRootDfsLink->NtfsShareFolder->NtfsFolder
Damit bleibt die fachliche Aussenwirkung stabil:
- DFS-Link bleibt nach aussen ein share-aehnliches Objekt
- DFS-Namespace-Root bleibt eigenstaendig sichtbar
Konkreter Klassifikationsalgorithmus
Schritt 1: Normalisierung
Jeder Eingabepfad wird zuerst vereinheitlicht:
- Slash zu Backslash
- doppelte Separatoren bereinigen
- UNC-Praefix sicherstellen
- Trailing Backslash entfernen
Beispiel:
\\SERVER\\share\\//server/share
werden intern zu:
\\server\\share
fuer Vergleiche kann case-insensitive gearbeitet werden.
Schritt 2: DFS zuerst pruefen
Fuer den gesamten Pfad und seine relevanten Praefixe werden DFS-Metadaten geprueft.
Beispiele:
- bei
\\server\\namespace\\link\\folder- pruefe
\\server\\namespace - pruefe
\\server\\namespace\\link
- pruefe
Entscheidungsregel:
- wenn der volle Pfad ein DFS-Namespace-Root ist ->
DfsNamespaceRoot - wenn der volle Pfad ein DFS-Link ist ->
DfsLink - wenn ein Praefix ein DFS-Link ist und der Gesamtpfad darunter liegt ->
Folder - wenn ein Praefix ein DFS-Namespace-Root ist, aber noch kein DFS-Link erkannt wurde, wird weiter geprueft
Wichtig:
- der tiefste erkannte DFS-Link gewinnt als fachliche Grenze
- die Share-Grenze ist dann genau dieser Link-Pfad
Schritt 3: SMB-Share pruefen
Nur wenn kein DFS-Ergebnis vorliegt:
- ermittle sichtbare Shares des Servers per
NetShareEnum - pruefe, ob
\\server\\shareexakt ein publizierter Share ist
Entscheidungsregel:
- wenn der volle Pfad exakt einem Share entspricht ->
ClassicShare - wenn ein Praefix exakt einem Share entspricht und der Gesamtpfad darunter liegt ->
Folder
Schritt 4: Folder nur relativ zu einer erkannten Grenze
Ein Pfad ist nur dann sicher Folder, wenn bereits eine fachliche Grenze erkannt wurde:
- klassischer Share
- DFS-Link
Beispiele:
\\server\\share\\dept->Folder, wenn\\server\\shareein ClassicShare ist\\server\\namespace\\link\\dept->Folder, wenn\\server\\namespace\\linkein DfsLink ist
Schritt 5: Unknown statt falscher Sicherheit
Wenn weder DFS noch SMB sicher bestimmt werden koennen:
- liefere intern
Unknown - logge die Ursache
- triff keine stille Segment-basierten Fallback-Entscheidung
Erforderliche Runtime-Abfragen
DFSResolver
Neue interne Hilfskomponente:
TryGetDfsMetadata(path, out metadata)
Rueckgabedaten:
ExistsIsNamespaceRootIsLinkPathEntryPathTargets
Empfohlene Implementierung:
- P/Invoke gegen
NetDfsGetInfo
Sinnvolle Aufrufmuster:
- pruefe
\\server\\namespace - pruefe
\\server\\namespace\\link - cache Ergebnisse je Pfad
ShareResolver
Bestehende Hilfskomponente weiterverwenden:
EnumNetShares(server)
Ergaenzung:
- optional Hilfsmethode
IsPublishedShare(server, shareName) - Cache je Server
Neue zentrale Datenstruktur
Empfohlene interne Rueckgabe:
PathClassification
- NormalizedPath
- Kind
- BoundaryPath
- ParentBoundaryPath
- BackingType
- ResolvedFrom
- Diagnostics
Dabei bedeutet:
BoundaryPath: fachliche Share-GrenzeParentBoundaryPath: Parent-Objekt fuer LIAM-ParentUIDBackingType:DFSoderSMBResolvedFrom: z. B.DfsLinkPrefix,SharePrefix,FullPathDfsRoot
Verhalten fuer typische Faelle
Fall A
Pfad:
\\SRVWSM001.imagoverum.com\\file_shares
Erwartung:
- wenn DFS-Metadaten Root bestaetigen ->
DfsNamespaceRoot
Fall B
Pfad:
\\SRVWSM001.imagoverum.com\\file_shares\\share2
Erwartung:
- wenn DFS-Metadaten Link bestaetigen -> intern
DfsLink, externNtfsShare
Fall C
Pfad:
\\SRVWSM001.imagoverum.com\\file_shares\\share2\\test33
Erwartung:
- wenn
\\...\\file_shares\\share2als DFS-Link erkannt wurde ->Folder
Anpassung von getDataAreasAsync()
Die Enumeration darf nicht mehr nur mit RequestFoldersListAsync(RootPath, depth) arbeiten.
Stattdessen:
- Root zuerst klassifizieren
- Kinder je nach Root-Typ enumerieren
Regeln:
ClassicShare- Kinder per Dateisystem-Verzeichnisliste
DfsNamespaceRoot- direkte Kinder primaer ueber DFS-Namespace-Inhaltsmetadaten
- nur diese direkten Kinder sind fachlich Share-aehnliche Eintraege
DfsLink- Kinder per Dateisystem-Verzeichnisliste unterhalb des Link-Ziels bzw. unter dem UNC-Linkpfad
Folder- Kinder per Dateisystem-Verzeichnisliste
Der aktuelle Fehler entsteht gerade dadurch, dass direkte Kinder eines DFS-Namespace-Roots wie normale Ordner enumeriert und spaeter wieder als Folder behandelt werden.
Anpassung von LoadDataArea()
LoadDataArea() muss dieselbe zentrale Klassifikation benutzen wie getDataAreasAsync().
Wichtig:
- keine eigene Kurzlogik
- keine Typentscheidung ueber Segmentzahl
- gleiche
PathClassificationfuer denselben Pfad wie im Listenpfad
Logging
Fuer Diagnosefaelle sollten folgende Logeintraege vorhanden sein:
- welcher Pfad wird klassifiziert
- welcher DFS-Check wurde ausgefuehrt
- welcher Share-Check wurde ausgefuehrt
- welcher Praefix als Boundary erkannt wurde
- warum ein Pfad
Unknownwurde
Beispiel:
Path '\\server\\namespace\\link\\team' classified as Folder via DFS link boundary '\\server\\namespace\\link'
Fehlerverhalten
Wenn DFS-Abfragen fehlschlagen:
- Fehler loggen
- weiter mit SMB-Pruefung
Wenn SMB-Abfragen fehlschlagen:
- Fehler loggen
- nicht automatisch Folder annehmen
Wenn beides fehlschlaegt:
Unknown
Damit wird falsche Typvergabe vermieden.
Performance
Noetige Caches:
- DFS-Metadaten-Cache pro Pfad
- Share-Liste pro Server
Empfehlung:
- innerhalb eines Provider-Laufs cachen
- keine globale Langzeitpersistenz
Konkrete Implementierungsschritte
- neue interne Resolver-Komponente fuer DFS-Metadaten einfuehren
- bestehende Share-Abfrage in dedizierte Share-Resolver-Methode kapseln
ClassifyPath()auf Metadaten-basierte Entscheidung umbauengetDataAreasAsync()root-typabhaengig enumerierenLoadDataArea()auf dieselbe Klassifikation umstellen- JSON-Rueckgabe unveraendert lassen:
DfsNamespaceRootals eigenerDataAreaTypeDfsLinknach aussen alsNtfsShareFolderalsNtfsFolder
Entscheidung
Die empfohlene Umsetzung ohne Config-Erweiterung ist:
RootPathaus der vorhandenen Config nur als Einstieg verwenden- DFS-Metadaten zur Laufzeit ueber API abfragen
- SMB-Share-Metadaten zur Laufzeit ueber
NetShareEnumabfragen - Folder ausschliesslich relativ zu einer erkannten fachlichen Grenze ableiten
Nur so koennen klassische Shares, DFS-Namespaces, DFS-Links und echte Folder belastbar unterschieden werden, auch wenn LIAM nicht auf dem Zielserver selbst laeuft.