Fix NTFS traverse group reuse

This commit is contained in:
Meik
2026-07-09 23:52:19 +02:00
parent b9cd74c5a9
commit b0fd1d0c75
2 changed files with 72 additions and 21 deletions

View File

@@ -688,7 +688,7 @@ namespace C4IT_IAM_SET
var folderName = sanitizedSegments.Length > 0
? sanitizedSegments[sanitizedSegments.Length - 1]
: Helper.SanitizePathSegment(Path.GetFileName(parent.FullName.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)), groupNameSanitizeReplacement);
var traverseTags = GetTraverseReplacementTags(parent.FullName);
var traverseTags = GetTraverseReplacementTags(parent.FullName, traverseGroupTemplate.Scope);
var rootContext = Helper.GetRootPathTemplateContext(baseFolder, groupNameSanitizeReplacement);
var boundedTraverseContext = Helper.GetBoundedAdGroupTemplateContext(
traverseGroupTemplate.NamingTemplate,
@@ -780,18 +780,6 @@ namespace C4IT_IAM_SET
if (parentTraverseGroup != null)
parentTraverseGroupName = parentTraverseGroup.Name;
if (parentTraverseGroup == null && hasTraverseWildcard && !forceStrictAdGroupNames)
{
parentTraverseGroup = FindTraverseGroupByWildcard(domainContext, traverseRegex);
if (parentTraverseGroup != null)
{
parentTraverseGroupName = parentTraverseGroup.Name;
resultToken.reusedGroups.Add(parentTraverseGroup.Name);
resultToken.ensuredTraverseGroups.Add(parentTraverseGroup.Name);
DefaultLogger.LogEntry(LogLevels.Debug, $"Vorhandene Traverse-Gruppe per Wildcard wiederverwendet: {parentTraverseGroup.Name}");
}
}
if (parentTraverseGroup == null && !string.IsNullOrWhiteSpace(traverseNameTemplate))
{
for (var loop = 0; loop < 20; loop++)
@@ -809,6 +797,13 @@ namespace C4IT_IAM_SET
}
}
if (parentTraverseGroup == null && hasTraverseWildcard && !forceStrictAdGroupNames)
{
DefaultLogger.LogEntry(
LogLevels.Debug,
$"Traverse wildcard '{traverseRegex}' is only used for ACL-linked groups on '{parent.FullName}'. Global wildcard reuse is skipped to avoid reusing a traverse group from another path.");
}
if (parentTraverseGroup == null && !string.IsNullOrWhiteSpace(traverseNameTemplate))
{
DefaultLogger.LogEntry(LogLevels.Debug, "Erstelle neue TraverseGroup.");
@@ -952,6 +947,11 @@ namespace C4IT_IAM_SET
}
if (currentSecGroup.Scope != GroupScope.Global)
continue;
if (IsSameGroupName(currentSecGroup.Name, displayTraverseGroupName))
{
DefaultLogger.LogEntry(LogLevels.Debug, $"Skip self membership for Traverse-Gruppe '{displayTraverseGroupName}'.");
continue;
}
if (WhatIf)
{
@@ -972,7 +972,11 @@ namespace C4IT_IAM_SET
{
try
{
if (WhatIf)
if (IsSameGroupName(displayTraverseGroupName, traverseGroupName))
{
DefaultLogger.LogEntry(LogLevels.Debug, $"Skip nested self membership for Traverse-Gruppe '{displayTraverseGroupName}'.");
}
else if (WhatIf)
{
resultToken.warnings.Add($"Traverse-Gruppe '{displayTraverseGroupName}' würde verschachtelte Gruppe '{traverseGroupName}' erhalten.");
}
@@ -1055,14 +1059,45 @@ namespace C4IT_IAM_SET
&& PathsEqual(boundaryPath, path);
}
private Dictionary<string, string> GetTraverseReplacementTags(string currentPath)
private Dictionary<string, string> GetTraverseReplacementTags(string currentPath, GroupScope traverseScope)
{
var visibleSegments = GetVisibleTraversePathSegments(currentPath);
return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
var tags = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
if (groupCustomTags != null)
{
{ "TRAVERSE_NAME", Helper.SanitizePathSegment(GetLastPathSegment(currentPath), groupNameSanitizeReplacement) },
{ "TRAVERSE_VISIBLEPATH", Helper.JoinSanitizedPathSegments(visibleSegments.Select(i => Helper.SanitizePathSegment(i, groupNameSanitizeReplacement)), groupNameSanitizeReplacement) }
};
foreach (var customTag in groupCustomTags)
tags[customTag.Key] = customTag.Value;
}
tags["PREFIX"] = groupPrefix;
tags["GROUPTYPEPOSTFIX"] = groupTraverseTag;
tags["SCOPETAG"] = traverseScope == GroupScope.Local ? groupDLTag : groupGTag;
tags["TRAVERSE_NAME"] = Helper.SanitizePathSegment(GetLastPathSegment(currentPath), groupNameSanitizeReplacement);
tags["TRAVERSE_VISIBLEPATH"] = Helper.JoinSanitizedPathSegments(visibleSegments.Select(i => Helper.SanitizePathSegment(i, groupNameSanitizeReplacement)), groupNameSanitizeReplacement);
return tags;
}
private static bool IsSameGroupName(string left, string right)
{
return !string.IsNullOrWhiteSpace(left)
&& !string.IsNullOrWhiteSpace(right)
&& string.Equals(left, right, StringComparison.OrdinalIgnoreCase);
}
private static bool IsSamePrincipal(GroupPrincipal left, GroupPrincipal right)
{
if (left == null || right == null)
return false;
var leftSid = left.Sid?.Value;
var rightSid = right.Sid?.Value;
if (!string.IsNullOrWhiteSpace(leftSid) && !string.IsNullOrWhiteSpace(rightSid))
return string.Equals(leftSid, rightSid, StringComparison.OrdinalIgnoreCase);
if (!string.IsNullOrWhiteSpace(left.DistinguishedName) && !string.IsNullOrWhiteSpace(right.DistinguishedName))
return string.Equals(left.DistinguishedName, right.DistinguishedName, StringComparison.OrdinalIgnoreCase);
return IsSameGroupName(left.SamAccountName ?? left.Name, right.SamAccountName ?? right.Name);
}
private IEnumerable<string> GetVisibleTraversePathSegments(string currentPath)
@@ -1245,6 +1280,12 @@ namespace C4IT_IAM_SET
if (parentTraverseGroup == null || traverseGroup == null)
return false;
if (IsSamePrincipal(parentTraverseGroup, traverseGroup))
{
DefaultLogger.LogEntry(LogLevels.Debug, $"Skip nested self membership for Traverse-Gruppe '{parentTraverseGroup.Name}'.");
return true;
}
return RetryTraverseMembershipAction(
traverseGroup.Name,
true,
@@ -1554,11 +1595,11 @@ namespace C4IT_IAM_SET
DirectoryInfo dInfo = new DirectoryInfo(technicalName);
//DirectoryInfo dInfoBaseFolder = new DirectoryInfo(baseFolderTechnicalName);
// Get a DirectorySecurity object that represents the
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
// Add the FileSystemAccessRule to the security settings.
var everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
dSecurity.AddAccessRule(new FileSystemAccessRule(everyone,