I have an application running in multiple servers applying some ACL's.
Problem is when more than one server is applying on the same folder structure (i.e. three levels), usually only levels one and three have the ACL's applied, but there's no exception.
I've created a test with parallel tasks (to simulate the different servers):
[TestMethod]
public void ApplyACL()
{
var baseDir = Path.Combine(Path.GetTempPath(), "ACL-PROBLEM");
if (Directory.Exists(baseDir))
{
Directory.Delete(baseDir, true);
}
var paths = new[]
{
Path.Combine(baseDir, "LEVEL-1"),
Path.Combine(baseDir, "LEVEL-1", "LEVEL-2"),
Path.Combine(baseDir, "LEVEL-1", "LEVEL-2", "LEVEL-3")
};
//create folders and files, so the ACL takes some time to apply
foreach (var dir in paths)
{
Directory.CreateDirectory(dir);
for (int i = 0; i < 1000; i++)
{
var id = string.Format("{0:000}", i);
File.WriteAllText(Path.Combine(dir, id + ".txt"), id);
}
}
var sids = new[]
{
"S-1-5-21-448539723-725345543-1417001333-1111111",
"S-1-5-21-448539723-725345543-1417001333-2222222",
"S-1-5-21-448539723-725345543-1417001333-3333333"
};
var taskList = new List<Task>();
for (int i = 0; i < paths.Length; i++)
{
taskList.Add(CreateTask(i + 1, paths[i], sids[i]));
}
Parallel.ForEach(taskList, t => t.Start());
Task.WaitAll(taskList.ToArray());
var output = new StringBuilder();
var failed = false;
for (int i = 0; i < paths.Length; i++)
{
var ok = Directory.GetAccessControl(paths[i])
.GetAccessRules(true, false, typeof(SecurityIdentifier))
.OfType<FileSystemAccessRule>()
.Any(f => f.IdentityReference.Value == sids[i]);
if (!ok)
{
failed = true;
}
output.AppendLine(paths[i].Remove(0, baseDir.Length + 1) + " --> " + (ok ? "OK" : "ERROR"));
}
Debug.WriteLine(output);
if (failed)
{
Assert.Fail();
}
}
private static Task CreateTask(int i, string path, string sid)
{
return new Task(() =>
{
var start = DateTime.Now;
Debug.WriteLine("Task {0} start: {1:HH:mm:ss.fffffff}", i, start);
var fileSystemAccessRule = new FileSystemAccessRule(new SecurityIdentifier(sid),
FileSystemRights.Modify | FileSystemRights.Synchronize,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.None,
AccessControlType.Allow);
var directorySecurity = Directory.GetAccessControl(path);
directorySecurity.ResetAccessRule(fileSystemAccessRule);
Directory.SetAccessControl(path, directorySecurity);
Debug.WriteLine("Task {0} finish: {1:HH:mm:ss.fffffff} ({2} ms)", i, DateTime.Now, (DateTime.Now - start).TotalMilliseconds);
});
}
I'm getting the same problem: usually (but not always) only levels one and three have the ACL's applied.
Why is that and how can I fix this?
SetAccessRule
instead ofResetAccessRule
? – CrosspieceSetAccessRule
orResetAccessRule
. – Sideman