From 61dd57cf0caf23d2c98688e6f28151e284d35dc7 Mon Sep 17 00:00:00 2001 From: Meik Date: Wed, 18 Mar 2026 14:35:14 +0100 Subject: [PATCH] Add workflow NTFS WhatIf toggle --- LiamNtfs/C4IT.LIAM.Ntfs.cs | 4 +- LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs | 224 ++++++++++++------ LiamWorkflowActivities/LiamWorkflowRuntime.cs | 14 +- 3 files changed, 169 insertions(+), 73 deletions(-) diff --git a/LiamNtfs/C4IT.LIAM.Ntfs.cs b/LiamNtfs/C4IT.LIAM.Ntfs.cs index 512b5c9..937c97a 100644 --- a/LiamNtfs/C4IT.LIAM.Ntfs.cs +++ b/LiamNtfs/C4IT.LIAM.Ntfs.cs @@ -623,7 +623,8 @@ namespace C4IT.LIAM IDictionary customTags, IEnumerable ownerSids, IEnumerable readerSids, - IEnumerable writerSids + IEnumerable writerSids, + bool whatIf = false ) { var engine = CreateFilesystemEngine( @@ -633,6 +634,7 @@ namespace C4IT.LIAM ownerSids, readerSids, writerSids); + engine.WhatIf = whatIf; var result = engine.createDataArea(); return Task.FromResult(result); } diff --git a/LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs b/LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs index ccf3ea3..c0ebb3a 100644 --- a/LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs +++ b/LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem.cs @@ -134,19 +134,7 @@ namespace C4IT_IAM_SET resultToken.resultErrorId = 0; if (checkRequiredVariables().resultErrorId == 0) { - newDataArea = new DataArea(); - IAM_Folder folder = new IAM_Folder(); - folder.configurationID = ConfigID; - folder.technicalName = newFolderPath; - folder.targetType = (int)IAM_TargetType.FileSystem; - folder.Parent = newFolderParent; - folder.ParentUID = DataArea.GetUniqueDataAreaID(newFolderParent); - newDataArea.IAM_Folders.Add(folder); - newSecurityGroups = new SecurityGroups(); - newSecurityGroups.username = username; - newSecurityGroups.domainName = domainName; - newSecurityGroups.password = password; - newSecurityGroups.ForceStrictAdGroupNames = forceStrictAdGroupNames; + InitializeFolderContext(); try { // ImpersonationHelper.Impersonate(domainName, username, new NetworkCredential("", password).Password, delegate @@ -157,22 +145,26 @@ namespace C4IT_IAM_SET DefaultLogger.LogEntry(LogLevels.Info, $"Establishing connection to {baseFolder}, User: {username}, Password: {Helper.MaskAllButLastAndFirst(new NetworkCredential("", password).Password)}"); using (Connection = new cNetworkConnection(baseFolder, username, new NetworkCredential("", password).Password)) { - if (checkFolder().resultErrorId == 0) + var folderCheckResult = checkFolder(); + if (folderCheckResult.resultErrorId == 0) { try { - createADGroups(); + createADGroups(resultToken); try { - resultToken = createFolder(); - try + resultToken = MergeResultTokens(resultToken, createFolder()); + if (resultToken.resultErrorId == 0) { - resultToken = SetTraversePermissions(); - } - catch (Exception e) - { - resultToken.resultErrorId = 30200; - resultToken.resultMessage = "Fehler beim setzen der Traverserechte \n" + e.Message; + try + { + resultToken = MergeResultTokens(resultToken, SetTraversePermissions()); + } + catch (Exception e) + { + resultToken.resultErrorId = 30200; + resultToken.resultMessage = "Fehler beim setzen der Traverserechte \n" + e.Message; + } } } catch (Exception e) @@ -191,7 +183,7 @@ namespace C4IT_IAM_SET } else { - resultToken = checkFolder(); + resultToken = folderCheckResult; } /* }, logonType, @@ -222,6 +214,29 @@ namespace C4IT_IAM_SET } } + private ResultToken MergeResultTokens(ResultToken target, ResultToken source) + { + if (target == null) + return source; + + if (source == null) + return target; + + if (source.resultErrorId != 0 || target.resultErrorId == 0) + target.resultErrorId = source.resultErrorId; + if (!string.IsNullOrWhiteSpace(source.resultMessage)) + target.resultMessage = source.resultMessage; + if (!string.IsNullOrWhiteSpace(source.resultFunction)) + target.resultFunction = source.resultFunction; + target.createdGroups.AddRange(source.createdGroups); + target.reusedGroups.AddRange(source.reusedGroups); + target.addedAclEntries.AddRange(source.addedAclEntries); + target.skippedAclEntries.AddRange(source.skippedAclEntries); + target.ensuredTraverseGroups.AddRange(source.ensuredTraverseGroups); + target.warnings.AddRange(source.warnings); + return target; + } + private ResultToken checkRequiredVariablesForEnsure() { ResultToken resultToken = new ResultToken(System.Reflection.MethodBase.GetCurrentMethod().ToString()); @@ -601,41 +616,52 @@ namespace C4IT_IAM_SET if (parent.Parent != null) { DefaultLogger.LogEntry(LogLevels.Debug, "Parent.Parent ist nicht null. Erstelle AD-Gruppe."); - try + if (WhatIf) { - newSecurityGroups.CreateADGroup(groupOUPath, newTraverseGroup, null); - DefaultLogger.LogEntry(LogLevels.Debug, $"AD-Gruppe erstellt: {newTraverseGroup.Name}"); resultToken.createdGroups.Add(newTraverseGroup.Name); resultToken.ensuredTraverseGroups.Add(newTraverseGroup.Name); - } - catch (Exception ex) - { - DefaultLogger.LogEntry(LogLevels.Error, $"Fehler beim Erstellen der AD-Gruppe: {ex.Message}"); - continue; - } - - parentTraverseGroup = GroupPrincipal.FindByIdentity(domainContext, newTraverseGroup.Name); - if (parentTraverseGroup == null) - { - DefaultLogger.LogEntry(LogLevels.Error, $"parentTraverseGroup konnte nach Erstellung der Gruppe nicht gefunden werden: {newTraverseGroup.Name}"); - continue; - } - - try - { - var accesscontrol = parent.GetAccessControl(); - accesscontrol.AddAccessRule(new FileSystemAccessRule(parentTraverseGroup.Sid, - FileSystemRights.Read, InheritanceFlags.None, PropagationFlags.None, - AccessControlType.Allow)); - DefaultLogger.LogEntry(LogLevels.Debug, $"Setze Traverse-ACL auf: {parent.FullName} für {parentTraverseGroup.DistinguishedName}"); - parent.SetAccessControl(accesscontrol); - resultToken.addedAclEntries.Add(parentTraverseGroup.Name); + resultToken.warnings.Add($"Traverse-Gruppe würde angelegt werden: {newTraverseGroup.Name}"); + resultToken.addedAclEntries.Add(newTraverseGroup.Name); parentTraverseAclExists = true; } - catch (Exception ex) + else { - DefaultLogger.LogEntry(LogLevels.Error, $"Fehler beim Setzen der ACL: {ex.Message}"); - continue; + try + { + newSecurityGroups.CreateADGroup(groupOUPath, newTraverseGroup, null); + DefaultLogger.LogEntry(LogLevels.Debug, $"AD-Gruppe erstellt: {newTraverseGroup.Name}"); + resultToken.createdGroups.Add(newTraverseGroup.Name); + resultToken.ensuredTraverseGroups.Add(newTraverseGroup.Name); + } + catch (Exception ex) + { + DefaultLogger.LogEntry(LogLevels.Error, $"Fehler beim Erstellen der AD-Gruppe: {ex.Message}"); + continue; + } + + parentTraverseGroup = GroupPrincipal.FindByIdentity(domainContext, newTraverseGroup.Name); + if (parentTraverseGroup == null) + { + DefaultLogger.LogEntry(LogLevels.Error, $"parentTraverseGroup konnte nach Erstellung der Gruppe nicht gefunden werden: {newTraverseGroup.Name}"); + continue; + } + + try + { + var accesscontrol = parent.GetAccessControl(); + accesscontrol.AddAccessRule(new FileSystemAccessRule(parentTraverseGroup.Sid, + FileSystemRights.Read, InheritanceFlags.None, PropagationFlags.None, + AccessControlType.Allow)); + DefaultLogger.LogEntry(LogLevels.Debug, $"Setze Traverse-ACL auf: {parent.FullName} für {parentTraverseGroup.DistinguishedName}"); + parent.SetAccessControl(accesscontrol); + resultToken.addedAclEntries.Add(parentTraverseGroup.Name); + parentTraverseAclExists = true; + } + catch (Exception ex) + { + DefaultLogger.LogEntry(LogLevels.Error, $"Fehler beim Setzen der ACL: {ex.Message}"); + continue; + } } } else @@ -662,10 +688,13 @@ namespace C4IT_IAM_SET } else { - accessControl.AddAccessRule(new FileSystemAccessRule(parentTraverseGroup.Sid, - FileSystemRights.Read, InheritanceFlags.None, PropagationFlags.None, - AccessControlType.Allow)); - parent.SetAccessControl(accessControl); + if (!WhatIf) + { + accessControl.AddAccessRule(new FileSystemAccessRule(parentTraverseGroup.Sid, + FileSystemRights.Read, InheritanceFlags.None, PropagationFlags.None, + AccessControlType.Allow)); + parent.SetAccessControl(accessControl); + } resultToken.addedAclEntries.Add(parentTraverseGroup.Name); } } @@ -681,8 +710,11 @@ namespace C4IT_IAM_SET if (i == lvl) { DefaultLogger.LogEntry(LogLevels.Debug, "Verarbeite SecurityGroups bei oberster Ebene."); - DefaultLogger.LogEntry(LogLevels.Debug, "Warte 3min."); - System.Threading.Thread.Sleep(180000); // 60 Sekunden warten + if (!WhatIf) + { + DefaultLogger.LogEntry(LogLevels.Debug, "Warte 3min."); + System.Threading.Thread.Sleep(180000); // 60 Sekunden warten + } foreach (var currentSecGroup in newSecurityGroups.IAM_SecurityGroups) { if (currentSecGroup == null) @@ -704,9 +736,16 @@ namespace C4IT_IAM_SET { if (!parentTraverseGroup.Members.Contains(groupPrincipal)) { - DefaultLogger.LogEntry(LogLevels.Debug, $"Füge {groupPrincipal.DistinguishedName} zur Traverse-Gruppe {parentTraverseGroup.DistinguishedName} hinzu"); - parentTraverseGroup.Members.Add(groupPrincipal); - parentTraverseGroup.Save(); + if (WhatIf) + { + resultToken.warnings.Add($"Traverse-Gruppe '{parentTraverseGroup.Name}' würde Mitglied '{groupPrincipal.Name}' erhalten."); + } + else + { + DefaultLogger.LogEntry(LogLevels.Debug, $"Füge {groupPrincipal.DistinguishedName} zur Traverse-Gruppe {parentTraverseGroup.DistinguishedName} hinzu"); + parentTraverseGroup.Members.Add(groupPrincipal); + parentTraverseGroup.Save(); + } } } catch (Exception ex) @@ -727,9 +766,16 @@ namespace C4IT_IAM_SET { if (!parentTraverseGroup.Members.Contains(traverseGroup)) { - DefaultLogger.LogEntry(LogLevels.Debug, $"Füge {traverseGroup.DistinguishedName} zur Traverse-Gruppe {parentTraverseGroup.DistinguishedName} hinzu"); - parentTraverseGroup.Members.Add(traverseGroup); - parentTraverseGroup.Save(); + if (WhatIf) + { + resultToken.warnings.Add($"Traverse-Gruppe '{parentTraverseGroup.Name}' würde verschachtelte Gruppe '{traverseGroup.Name}' erhalten."); + } + else + { + DefaultLogger.LogEntry(LogLevels.Debug, $"Füge {traverseGroup.DistinguishedName} zur Traverse-Gruppe {parentTraverseGroup.DistinguishedName} hinzu"); + parentTraverseGroup.Members.Add(traverseGroup); + parentTraverseGroup.Save(); + } } } catch (Exception ex) @@ -741,8 +787,11 @@ namespace C4IT_IAM_SET } try { - parentTraverseGroup.Save(); - DefaultLogger.LogEntry(LogLevels.Debug, $"parentTraverseGroup gespeichert: {parentTraverseGroup.Name}"); + if (!WhatIf) + { + parentTraverseGroup.Save(); + DefaultLogger.LogEntry(LogLevels.Debug, $"parentTraverseGroup gespeichert: {parentTraverseGroup.Name}"); + } } catch (Exception ex) { @@ -974,6 +1023,26 @@ namespace C4IT_IAM_SET } else { + if (WhatIf) + { + newDataArea.IAM_Folders[0].UID = DataArea.GetUniqueDataAreaID(newDataArea.IAM_Folders[0].technicalName); + resultToken.warnings.Add($"Verzeichnis würde erstellt werden: {newDataArea.IAM_Folders[0].technicalName}"); + + for (int i = 0; newSecurityGroups.IAM_SecurityGroups.Count > i; i++) + { + var currentSecGroup = newSecurityGroups.IAM_SecurityGroups[i]; + if (groupPermissionStrategy == PermissionGroupStrategy.AGDLP && currentSecGroup.Scope == GroupScope.Local + || groupPermissionStrategy == PermissionGroupStrategy.AGP && currentSecGroup.Scope == GroupScope.Global) + { + resultToken.addedAclEntries.Add(currentSecGroup.Name); + } + } + + resultToken.resultErrorId = 0; + resultToken.resultMessage = "Verzeichnis-, Gruppen- und ACL-Vorschau erfolgreich erstellt"; + return resultToken; + } + DefaultLogger.LogEntry(LogLevels.Debug, $"Creating folder: {newDataArea.IAM_Folders[0].technicalName}"); DirectoryInfo newDir = Directory.CreateDirectory(newDataArea.IAM_Folders[0].technicalName); newDataArea.IAM_Folders[0].UID = DataArea.GetUniqueDataAreaID(newDir.FullName); @@ -1026,7 +1095,7 @@ namespace C4IT_IAM_SET LogMethodEnd(MethodBase.GetCurrentMethod()); } - private void createADGroups() + private void createADGroups(ResultToken resultToken) { LogMethodBegin(MethodBase.GetCurrentMethod()); @@ -1085,7 +1154,24 @@ namespace C4IT_IAM_SET users = readers; else users = null; - newSecurityGroups.CreateADGroup(groupOUPath, newSecurityGroups.IAM_SecurityGroups[i], users); + + if (WhatIf) + { + var existingGroup = newSecurityGroups.PreviewADGroup(groupOUPath, newSecurityGroups.IAM_SecurityGroups[i], newDataArea.IAM_Folders[0].technicalName); + newSecurityGroups.IAM_SecurityGroups[i].CreatedNewEntry = existingGroup == null; + } + else + { + newSecurityGroups.CreateADGroup(groupOUPath, newSecurityGroups.IAM_SecurityGroups[i], users); + } + + if (resultToken != null) + { + if (newSecurityGroups.IAM_SecurityGroups[i].CreatedNewEntry) + resultToken.createdGroups.Add(newSecurityGroups.IAM_SecurityGroups[i].Name); + else + resultToken.reusedGroups.Add(newSecurityGroups.IAM_SecurityGroups[i].Name); + } } } catch (Exception E) diff --git a/LiamWorkflowActivities/LiamWorkflowRuntime.cs b/LiamWorkflowActivities/LiamWorkflowRuntime.cs index ead2d9e..6a13b5b 100644 --- a/LiamWorkflowActivities/LiamWorkflowRuntime.cs +++ b/LiamWorkflowActivities/LiamWorkflowRuntime.cs @@ -96,7 +96,8 @@ namespace LiamWorkflowActivities return result; } - if (!await EnsureNtfsPermissionGroupsIfConfiguredAsync(provider, dataAreas, result, simulateConfiguredNtfsPermissionEnsure)) + var workflowWhatIf = IsWorkflowWhatIfEnabled(provider); + if (!await EnsureNtfsPermissionGroupsIfConfiguredAsync(provider, dataAreas, result, simulateConfiguredNtfsPermissionEnsure || workflowWhatIf)) return result; result.DataAreas = dataAreas @@ -170,7 +171,8 @@ namespace LiamWorkflowActivities customTags, NormalizeIdentifierList(ownerSids), NormalizeIdentifierList(readerSids), - NormalizeIdentifierList(writerSids)); + NormalizeIdentifierList(writerSids), + IsWorkflowWhatIfEnabled(provider)); if (token == null) token = CreateInvalidNtfsResultToken(ntfsProvider.GetLastErrorMessage() ?? "Provider returned no result while creating the data area."); result.ResultToken = token; @@ -202,7 +204,8 @@ namespace LiamWorkflowActivities NormalizeIdentifierList(ownerSids), NormalizeIdentifierList(readerSids), NormalizeIdentifierList(writerSids), - ensureTraverseGroups); + ensureTraverseGroups, + IsWorkflowWhatIfEnabled(provider)); if (token == null) token = CreateInvalidNtfsResultToken(ntfsProvider.GetLastErrorMessage() ?? "Provider returned no result while ensuring NTFS permission groups."); result.ResultToken = token; @@ -570,6 +573,11 @@ namespace LiamWorkflowActivities || rawValue.Equals("yes", StringComparison.OrdinalIgnoreCase); } + private static bool IsWorkflowWhatIfEnabled(cLiamProviderBase provider) + { + return IsAdditionalConfigurationEnabled(provider, "WhatIf"); + } + private static void SetErrorFromProvider(GetDataAreasOperationResult result, cLiamProviderBase provider, string fallbackCode, string fallbackMessage) { var error = ExtractProviderError(provider, fallbackCode, fallbackMessage);