From b5981487d7bcc2502f09a95e48bbee6fb5cc630f Mon Sep 17 00:00:00 2001 From: Meik Date: Fri, 13 Mar 2026 16:37:36 +0100 Subject: [PATCH] Prefer folder ACL groups during NTFS ensure --- LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs | 2 +- LiamNtfs/C4IT_IAM_SET/SecurityGroup.cs | 75 +++++++++++++++++++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs b/LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs index 24b1b56..ccf7a44 100644 --- a/LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs +++ b/LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs @@ -912,7 +912,7 @@ namespace C4IT_IAM_SET else users = null; - newSecurityGroups.EnsureADGroup(groupOUPath, newSecurityGroups.IAM_SecurityGroups[i], users); + newSecurityGroups.EnsureADGroup(groupOUPath, newSecurityGroups.IAM_SecurityGroups[i], users, newDataArea.IAM_Folders[0].technicalName); if (newSecurityGroups.IAM_SecurityGroups[i].CreatedNewEntry) resultToken.createdGroups.Add(newSecurityGroups.IAM_SecurityGroups[i].Name); else diff --git a/LiamNtfs/C4IT_IAM_SET/SecurityGroup.cs b/LiamNtfs/C4IT_IAM_SET/SecurityGroup.cs index a367fcc..0026c86 100644 --- a/LiamNtfs/C4IT_IAM_SET/SecurityGroup.cs +++ b/LiamNtfs/C4IT_IAM_SET/SecurityGroup.cs @@ -480,6 +480,71 @@ namespace C4IT_IAM_Engine return new DirectoryEntry("LDAP://" + domainName + "/" + matchedDistinguishedName, username, new NetworkCredential("", password).Password, AuthenticationTypes.Secure | AuthenticationTypes.Sealing); } + private DirectoryEntry FindGroupEntryFromFolderAcl(string folderPath, string wildcardPattern) + { + if (string.IsNullOrWhiteSpace(folderPath) || string.IsNullOrWhiteSpace(wildcardPattern) || !Directory.Exists(folderPath)) + return null; + + Regex wildcardRegex; + try + { + wildcardRegex = new Regex(wildcardPattern, RegexOptions.IgnoreCase); + } + catch (Exception E) + { + cLogManager.DefaultLogger.LogException(E); + return null; + } + + try + { + var directory = new DirectoryInfo(folderPath); + var rules = directory.GetAccessControl(AccessControlSections.Access) + .GetAccessRules(true, false, typeof(SecurityIdentifier)) + .Cast(); + var matchedNames = new HashSet(StringComparer.OrdinalIgnoreCase); + + using (var domainContext = new PrincipalContext(ContextType.Domain, domainName, username, new NetworkCredential("", password).Password)) + { + foreach (var rule in rules) + { + if (rule.AccessControlType != AccessControlType.Allow) + continue; + + var sid = rule.IdentityReference?.Value; + if (string.IsNullOrWhiteSpace(sid) || sid == "S-1-1-0") + continue; + + using (var group = GroupPrincipal.FindByIdentity(domainContext, IdentityType.Sid, sid)) + { + var samAccountName = group?.SamAccountName; + if (string.IsNullOrWhiteSpace(samAccountName) || !wildcardRegex.IsMatch(samAccountName)) + continue; + + matchedNames.Add(samAccountName); + if (matchedNames.Count > 1) + { + DefaultLogger.LogEntry(LogLevels.Warning, $"Multiple ACL groups on folder '{folderPath}' matched wildcard '{wildcardPattern}'. ACL-based reuse is skipped."); + return null; + } + } + } + } + + if (matchedNames.Count == 0) + return null; + + var matchedName = matchedNames.First(); + DefaultLogger.LogEntry(LogLevels.Debug, $"Reusing ACL-linked AD group '{matchedName}' via wildcard '{wildcardPattern}' on folder '{folderPath}'."); + return FindGroupEntry(matchedName); + } + catch (Exception E) + { + cLogManager.DefaultLogger.LogException(E); + return null; + } + } + private void ApplyExistingGroup(IAM_SecurityGroup secGroup, DirectoryEntry existingGroup) { secGroup.CreatedNewEntry = false; @@ -539,13 +604,19 @@ namespace C4IT_IAM_Engine group.CommitChanges(); } - public DirectoryEntry EnsureADGroup(string ouPath, IAM_SecurityGroup secGroup, List users) + public DirectoryEntry EnsureADGroup(string ouPath, IAM_SecurityGroup secGroup, List users, string folderPath = null) { LogMethodBegin(MethodBase.GetCurrentMethod()); try { secGroup.CreatedNewEntry = false; - var existingGroup = FindGroupEntry(secGroup.Name); + DirectoryEntry existingGroup = null; + if (!ForceStrictAdGroupNames) + existingGroup = FindGroupEntryFromFolderAcl(folderPath, secGroup.WildcardPattern); + + if (existingGroup == null) + existingGroup = FindGroupEntry(secGroup.Name); + if (existingGroup == null && !ForceStrictAdGroupNames) existingGroup = FindGroupEntryByWildcard(ouPath, secGroup.WildcardPattern);