Ich habe eine Anwendung, die auf mehreren Servern läuft und einige ACLs anwendet.
Problem ist, wenn mehr als ein Server auf die gleiche Ordnerstruktur (d. h. drei Ebenen) anwendet, normalerweise nur die Ebenen eins und drei haben die ACLs angewendet, aber es gibt keine Ausnahme.
Ich habe einen Test mit parallelen Aufgaben erstellt (um die verschiedenen Server zu simulieren):
%Vor%Ich bekomme das gleiche Problem: normalerweise (aber nicht immer) nur die Ebenen eins und drei haben die ACL angewendet.
Warum ist das und wie kann ich das beheben?
Es ist ein lustiges Puzzle.
Ich habe Ihren Test gestartet und das Problem reproduziert fast für jeden Lauf. Und ACL werden oft nicht auch für LEVEL-3 angewendet.
Das Problem wird jedoch nicht reproduziert, wenn Tasks nicht parallel ausgeführt werden. Wenn das Verzeichnis diese 1000 Dateien nicht enthält, reproduziert das Problem viel seltener.
Dieses Verhalten ist der klassischen Race-Bedingung sehr ähnlich.
Ich habe keine expliziten Informationen zu diesem Thema gefunden, aber es scheint, als ob die Anwendung von ACL auf überlappende Verzeichnisbäume keine threadsichere Operation ist.
Um dies zu bestätigen, müssen wir die Implementierung von SetAccessControl()
analysieren (oder den zugrunde liegenden Windows API Aufruf). Aber versuchen wir uns vorzustellen, was es sein könnte.
SetAccessControl()
wird für das angegebene Verzeichnis und DirectorySecurity
record aufgerufen. SetAccessControl()
verwendet, das im übergeordneten Verzeichnis aufgerufen wird. Schließlich wird der in Schritt 4 erstellte Datensatz überschrieben. Natürlich ist der beschriebene Ablauf nur eine Annahme. Wir benötigen NTFS- oder Windows-Interna-Experten, um dies zu bestätigen.
Aber beobachtetes Verhalten weist fast sicher auf den Zustand der Rasse hin. Vermeiden Sie einfach das parallele Anwenden der ACL auf überlappende Verzeichnisbäume und schlafen Sie gut.
Directory.SetAccessControl
ruft intern die Win32-API-Funktion SetSecurityInfo
auf:
Ссылка
Der wichtige Teil der oben genannten Dokumentation:
Wenn Sie die DACL (Discretionary Access Control List) oder Elemente in der Systemzugriffssteuerungsliste (SACL) eines Objekts festlegen, leitet das System automatisch vererbbare Zugriffssteuerungseinträge (ACEs) an vorhandene untergeordnete Objekte weiter , gemäß den ACE-Vererbungsregeln.
Die Aufzählung untergeordneter Objekte (CodeFuller hat dies bereits beschrieben) erfolgt in der Low-Level-Funktion SetSecurityInfo
selbst. Um genauer zu sein, ruft diese Funktion die System-DLL NTMARTA.DLL auf, die all die schmutzige Arbeit erledigt.
Der Hintergrund dafür ist die Vererbung, die aus Leistungsgründen eine "Pseudo-Vererbung" ist. Jedes Objekt enthält nicht nur die "eigenen" ACEs, sondern auch die ererbten ACEs (diejenigen, die im Explorer ausgegraut sind). Die gesamte Vererbung erfolgt während der ACL-Einstellung, nicht während der ACL-Auflösung / Prüfung der Laufzeit.
Diese frühere Entscheidung von Microsoft ist auch der Auslöser für das folgende Problem (Windows-Administratoren sollten dies wissen):
Wenn Sie eine Verzeichnisstruktur an einen anderen Speicherort im Dateisystem verschieben, an dem eine andere ACL festgelegt ist, ändern sich die ACLs der Objekte des verschobenen try nicht.
Die vererbten Berechtigungen sind also falsch, sie stimmen nicht mehr mit der ACL der Eltern überein.
Diese Vererbung ist nicht definiert durch InheritanceFlags
, sondern mit
SetAccessRuleProtection
.
Um CodeFuller's Antwort hinzuzufügen:
& gt; & gt; Nachdem die Aufzählung abgeschlossen ist, wird der interne Verzeichnissicherheitsdatensatz dem Verzeichnis zugewiesen.
Diese Enumeration ist nicht nur ein reines Lesen der Unterobjekte, die ACL jedes Unterobjekts wird SET sein.
Das Problem liegt also in der inneren Funktionsweise der Windows ACL-Behandlung:
SetSecurityInfo
prüft das übergeordnete Verzeichnis nach allen ACEs, die vererbt werden sollen, führt dann eine Rekursion durch und wendet diese vererbbaren ACEs auf alle Unterobjekte an.
Ich weiß darüber Bescheid, weil ich ein Tool geschrieben habe, das die ACLs kompletter Dateisysteme (mit Millionen von Dateien) festlegt, die einen so genannten "verwalteten Ordner" verwenden. Wir können sehr komplexe ALCs mit automatisch berechneten Listenberechtigungen haben.
Für die Einstellung der ACL zu den Dateien und Ordnern verwende ich SetKernelObjectSecurity
. Diese API sollte normalerweise nicht für Dateisysteme verwendet werden, da diese Vererbung nicht behandelt wird. Also musst du das selbst machen. Aber wenn Sie wissen, was Sie tun, und Sie es richtig machen, ist dies die einzige zuverlässige Methode, um die ACL in jeder Situation auf einen Dateibaum zu setzen.
Tatsächlich kann es Situationen geben (ungültige / ungültige ACL-Einträge in untergeordneten Objekten), in denen SetSecurityInfo
diese Objekte nicht richtig setzen kann.
Und jetzt zum Code von Anderson Pimentel:
Aus dem Obigen sollte klar sein, dass die parallele Einstellung nur funktionieren kann, wenn die Vererbung blockiert ist
auf jeder Verzeichnisebene.
Es funktioniert jedoch nicht, nur
in der Aufgabe, da dieser Aufruf möglicherweise zu spät kommt.
Ich habe den Code funktioniert, wenn die obige Anweisung vor dem Start der Aufgabe aufgerufen wird.
Die schlechte Nachricht ist, dass dieser mit C # durchgeführte Aufruf auch eine vollständige Rekursion durchführt.
Es scheint also, dass es in C # keine wirklich überzeugende Lösung gibt, abgesehen von der Tatsache, dass PInvoke die Low-Level-Sicherheitsfunktionen direkt aufruft.
Aber das ist eine andere Geschichte.
Und zu dem anfänglichen Problem, wo verschiedene Server die ACL einstellen:
Wenn wir wissen, was dahinter steckt und was das ALC sein soll, können wir vielleicht einen Weg finden.
Lass es mich wissen.
Führen Sie eine Sperre ein. Sie verfügen über das freigegebene Dateisystem, verwenden Sie also .NET, um zu sperren, wenn ein Prozess Änderungen an einem Ordner vornimmt:
%Vor%In Ihrer Code-Add-On-Initialisierung:
%Vor%und übergeben Sie die bekannte Sperrdatei an Ihre Aufgaben. Warten Sie dann, bis die Datei in jedem Ihrer Prozesse entsperrt wurde:
%Vor%Mit diesen Änderungen wird der Komponententest bestanden.
Sie können weitere Sperren auf den verschiedenen Ebenen hinzufügen, um den Prozess am effizientesten zu machen - so etwas wie eine Hierarchie-Sperrlogik.
Tags und Links c# distributed-computing acl file-permissions