Files
LIAM/LiamNtfs/C4IT_IAM_SET/DataArea_FileSystem_GET.cs
Meik 3d4f60d83e chore: sync LIAM solution snapshot incl. diagnostics tooling
- update multiple LIAM projects and solution/config files

- add LiamWorkflowDiagnostics app sources and generated outputs

- include current workspace state (dependencies and build outputs)
2026-02-27 09:12:34 +01:00

544 lines
25 KiB
C#

using C4IT_IAM_Engine;
using C4IT_IAM;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.IO;
using System.Linq;
using System.Net;
using System.Security;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
using System.Reflection;
namespace C4IT_IAM_GET
{
public enum AccessRights { Owner = 2032127, Write = 1245631, Read = 1179817 }
public enum PermissionGroupStrategy
{
AGP,
AGDLP
}
public class DataArea_FileSystem
{
public const string constApplicationDataPath = "%ProgramData%\\Consulting4IT GmbH\\LIAM";
public string domainName;
public string DomainIPAddress;
public string username;
private SecureString password;
private cNetworkConnection Connection;
public string groupWildCard_Owner;
public string groupWildCard_Read;
public string groupWildCard_Write;
public string groupWildCard_Traverse;
public string groupGOwnerWildcard = string.Empty;
public string groupGWriteWildcard = string.Empty;
public string groupGReadWildcard = string.Empty;
public string groupTraverseWildcard = string.Empty;
public string groupDLOwnerWildcard = string.Empty;
public string groupDLWriteWildcard = string.Empty;
public string groupDLReadWildcard = string.Empty;
public IDictionary<string, string> groupCustomTags;
public string groupDLTag;
public string groupGTag;
public string groupOwnerTag;
public string groupReadTag;
public string groupWriteTag;
public string groupTraverseTag;
public string groupPrefix;
public PermissionGroupStrategy groupPermissionStrategy;
public string groupLDAPFilter;
private string exportFolder;
private PrincipalContext ctx;
public string ConfigID;
public int maxDepth = 1;
public string groupLDAPPath;
public bool console;
private string startDir;
public string SecGroupXML;
public string DataAreasXML;
public SecureString Password { get => password; set => password = value; }
public string StartDir { get => startDir; set => startDir = value; }
public string ExportFolder { get => exportFolder; set => exportFolder = value; }
private ResultToken checkRequiredVariables()
{
ResultToken resultToken = new ResultToken(System.Reflection.MethodBase.GetCurrentMethod().ToString());
resultToken.resultErrorId = 0;
if (String.IsNullOrEmpty(ConfigID))
{
resultToken.resultErrorId = 20001;
resultToken.resultMessage = "Keine Config ID angegeben";
return resultToken;
}
if (String.IsNullOrEmpty(StartDir))
{
resultToken.resultErrorId = 20007;
resultToken.resultMessage = "Kein Startverzeichnis gewählt ";
return resultToken;
}
if (string.IsNullOrEmpty(username) | String.IsNullOrEmpty(new NetworkCredential("", password).Password) | String.IsNullOrEmpty(domainName))
{
resultToken.resultErrorId = 20002;
resultToken.resultMessage = "Fehlende Anmeldeinformationen";
return resultToken;
}
if (String.IsNullOrEmpty(groupWildCard_Owner) | String.IsNullOrEmpty(groupWildCard_Read) | String.IsNullOrEmpty(groupWildCard_Write))
{
resultToken.resultErrorId = 20004;
resultToken.resultMessage = "Keine AD Gruppen Wildcards";
return resultToken;
}
if (String.IsNullOrEmpty(groupLDAPFilter))
{
resultToken.resultErrorId = 20005;
resultToken.resultMessage = "Kein LDAP Gruppenfilter angegeben";
return resultToken;
}
if (String.IsNullOrEmpty(groupLDAPPath))
{
resultToken.resultErrorId = 20006;
resultToken.resultMessage = "Kein LDAP Pfad angegeben";
return resultToken;
}
return resultToken;
}
public DataArea_FileSystem()
{
var logDirectory = Environment.ExpandEnvironmentVariables(constApplicationDataPath);
Helper.CreatePathWithWriteAccess(logDirectory);
var LogPath = Path.Combine(logDirectory, "Logs");
cLogManagerFile.CreateInstance(Path.Combine(LogPath, "LIAM.log"));
DefaultLogger.LogEntry(LogLevels.Info, "=================================================");
DefaultLogger.LogEntry(LogLevels.Info, $"LIAM engine v{Assembly.GetExecutingAssembly().GetName().Version} started");
}
private void FillMatchingGroups()
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
groupWildCard_Owner = (groupPermissionStrategy == PermissionGroupStrategy.AGP ? groupGOwnerWildcard.Replace("{{PREFIX}}", groupPrefix).Replace("{{SCOPETAG}}", groupGTag) : groupDLOwnerWildcard.Replace("{{PREFIX}}", groupPrefix).Replace("{{SCOPETAG}}", groupDLTag)).Replace("{{GROUPTYPEPOSTFIX}}", groupOwnerTag).ReplaceTags(groupCustomTags);
groupWildCard_Write = (groupPermissionStrategy == PermissionGroupStrategy.AGP ? groupGWriteWildcard.Replace("{{PREFIX}}", groupPrefix).Replace("{{SCOPETAG}}", groupGTag) : groupDLWriteWildcard.Replace("{{PREFIX}}", groupPrefix).Replace("{{SCOPETAG}}", groupDLTag)).Replace("{{GROUPTYPEPOSTFIX}}", groupWriteTag).ReplaceTags(groupCustomTags);
groupWildCard_Read = (groupPermissionStrategy == PermissionGroupStrategy.AGP ? groupGReadWildcard.Replace("{{PREFIX}}", groupPrefix).Replace("{{SCOPETAG}}", groupGTag) : groupDLReadWildcard.Replace("{{PREFIX}}", groupPrefix).Replace("{{SCOPETAG}}", groupDLTag)).Replace("{{GROUPTYPEPOSTFIX}}", groupReadTag).ReplaceTags(groupCustomTags);
groupWildCard_Traverse = (groupPermissionStrategy == PermissionGroupStrategy.AGP ? groupTraverseWildcard.Replace("{{PREFIX}}", groupPrefix).Replace("{{SCOPETAG}}", groupGTag) : groupTraverseWildcard.Replace("{{PREFIX}}", groupPrefix).Replace("{{SCOPETAG}}", groupDLTag)).Replace("{{GROUPTYPEPOSTFIX}}", groupTraverseTag).ReplaceTags(groupCustomTags);
DefaultLogger.LogEntry(LogLevels.Debug, $"Owner regex: {groupWildCard_Owner}");
DefaultLogger.LogEntry(LogLevels.Debug, $"Write regex: {groupWildCard_Write}");
DefaultLogger.LogEntry(LogLevels.Debug, $"Read regex: {groupWildCard_Read}");
DefaultLogger.LogEntry(LogLevels.Debug, $"Traverse regex: {groupWildCard_Traverse}");
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
throw;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
public ResultToken BuildRootStructureWrapper()
{
LogMethodBegin(MethodBase.GetCurrentMethod());
FillMatchingGroups();
ResultToken resultToken = new ResultToken(System.Reflection.MethodBase.GetCurrentMethod().ToString());
resultToken.resultErrorId = 0;
try
{
if (checkRequiredVariables().resultErrorId == 0)
{
if (Connection != null)
Connection.Dispose();
DefaultLogger.LogEntry(LogLevels.Debug, $"Establishing connection to {startDir}, User: {username}, Password: {Helper.MaskAllButLastAndFirst(new NetworkCredential("", password).Password)}");
using (Connection = new cNetworkConnection(startDir, username, new NetworkCredential("", password).Password))
{
DefaultLogger.LogEntry(LogLevels.Debug, $"Creating Domain Context: {domainName}");
ctx = new PrincipalContext(ContextType.Domain, domainName, username, new NetworkCredential("", password).Password);
try
{
BuildRootStructure(startDir);
}
catch (Exception e)
{
resultToken.resultErrorId = 20200;
resultToken.resultMessage = "Fehler bei der Analyse der Verzeichnisstruktur \n " + e.Message;
}
}
}
else
{
return checkRequiredVariables();
}
}
catch (Exception E)
{
DefaultLogger.LogException(E);
resultToken.resultErrorId = 20000;
resultToken.resultMessage = $"Fehler beim Ermitteln der Dateistruktur \n{E.Message}";
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
return resultToken;
}
public void BuildRootStructure(string currentDirectory, int currentDepth = 0, DataArea dA = null)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
var firstRun = false;
try
{
string[] folders = Directory.GetDirectories(currentDirectory);
if (dA == null)
{
firstRun = true;
dA = new DataArea();
dA.rootUID = DataArea.GetUniqueDataAreaID(currentDirectory);
DirectoryInfo dADir = new DirectoryInfo(currentDirectory);
IAM_Folder iamFolder = new IAM_Folder()
{
Name = dADir.Name,
technicalName = dADir.FullName,
UID = DataArea.GetUniqueDataAreaID(dADir.FullName),
Parent = string.Empty,
ParentUID = string.Empty,
CreatedDate = dADir.CreationTimeUtc.ToString("s"),
Level = 0,
targetType = Convert.ToInt32(IAM_TargetType.FileSystem),
configurationID = ConfigID
};
dA.IAM_Folders.Add(iamFolder);
}
currentDepth++;
DefaultLogger.LogEntry(LogLevels.Debug, $"Current folder: {currentDirectory}, Level: {currentDepth}, Subdirectories: {folders.Length}");
foreach (string folder in folders)
{
DirectoryInfo dADir = new DirectoryInfo(folder);
IAM_Folder iamFolder = new IAM_Folder()
{
Name = dADir.Name,
technicalName = dADir.FullName,
UID = DataArea.GetUniqueDataAreaID(dADir.FullName),
Parent = dADir.Parent.FullName,
ParentUID = DataArea.GetUniqueDataAreaID(dADir.Parent.FullName),
CreatedDate = dADir.CreationTimeUtc.ToString("s"),
Level = currentDepth,
targetType = Convert.ToInt32(IAM_TargetType.FileSystem),
configurationID = ConfigID
};
var dAACL = dADir.GetAccessControl();
var dAAR = dAACL.GetAccessRules(true, false, typeof(System.Security.Principal.SecurityIdentifier));
var k = "";
DefaultLogger.LogEntry(LogLevels.Debug, $"Current folder: {folder}, Access Control Rules: {dAAR.Count}");
foreach (FileSystemAccessRule rule in dAAR)
{
//skip ACLs for user "everyone"
if (rule.IdentityReference.Value == "S-1-1-0")
continue;
k += rule.FileSystemRights + " - ";
GroupPrincipal grp = GroupPrincipal.FindByIdentity(ctx, IdentityType.Sid, rule.IdentityReference.Value);
if (grp != null)
{
if (Regex.IsMatch(grp.SamAccountName, groupWildCard_Owner, RegexOptions.IgnoreCase))
{
iamFolder.Owner = rule.IdentityReference.Value;
DefaultLogger.LogEntry(LogLevels.Debug, $"ACL on folder: {folder}, matching Owner: {grp.Name}");
}
else if (Regex.IsMatch(grp.SamAccountName, groupWildCard_Write, RegexOptions.IgnoreCase))
{
DefaultLogger.LogEntry(LogLevels.Debug, $"ACL on folder: {folder}, matching Write: {grp.Name}");
iamFolder.Write = rule.IdentityReference.Value;
}
else if (Regex.IsMatch(grp.SamAccountName, groupWildCard_Read, RegexOptions.IgnoreCase))
{
DefaultLogger.LogEntry(LogLevels.Debug, $"ACL on folder: {folder}, matching Read: {grp.Name}");
iamFolder.Read = rule.IdentityReference.Value;
}
else if (Regex.IsMatch(grp.SamAccountName, groupWildCard_Traverse, RegexOptions.IgnoreCase))
{
DefaultLogger.LogEntry(LogLevels.Debug, $"ACL on folder: {folder}, matching Traverse: {grp.Name}");
iamFolder.Traverse = rule.IdentityReference.Value;
}
else
DefaultLogger.LogEntry(LogLevels.Debug, $"No match for: {grp.Name}");
}
}
dA.IAM_Folders.Add(iamFolder);
if (currentDepth < maxDepth)
{
BuildRootStructure(folder, currentDepth, dA);
}
DefaultLogger.LogEntry(LogLevels.Debug, $"Max level ({ maxDepth }) reached");
}
if (firstRun)
SetDataAreaXML(dA);
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
throw E;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
public ResultToken GetRelevantADGroupsWrapper()
{
LogMethodBegin(MethodBase.GetCurrentMethod());
FillMatchingGroups();
ResultToken resultToken = new ResultToken(System.Reflection.MethodBase.GetCurrentMethod().ToString());
resultToken.resultErrorId = 0;
try
{
if (checkRequiredVariables().resultErrorId == 0)
{
GetRelevantADGroups();
}
else
{
return checkRequiredVariables();
}
}
catch (Exception E)
{
resultToken.resultErrorId = 20000;
resultToken.resultMessage = "Fehler Ermitteln der AD-Gruppen \n" + E.Message;
cLogManager.DefaultLogger.LogException(E);
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
return resultToken;
}
public void GetRelevantADGroups()
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
SecurityGroups secGroups = new SecurityGroups();
var ldapPath = $"LDAP://{domainName}/{groupLDAPPath}";
DefaultLogger.LogEntry(LogLevels.Debug, $"Connecting to LDAP using: Domain: {domainName}, LDAPPath: {ldapPath}, User: {username}, Password: {Helper.MaskAllButLastAndFirst(new NetworkCredential("", password).Password)}");
ctx = new PrincipalContext(ContextType.Domain, domainName, username, new NetworkCredential("", password).Password);
DefaultLogger.LogEntry(LogLevels.Debug, $"1 " + ctx.ConnectedServer);
DefaultLogger.LogEntry(LogLevels.Debug, $"2 " + ctx.UserName);
DefaultLogger.LogEntry(LogLevels.Debug, $"3 " + ctx.ValidateCredentials(username, new NetworkCredential("", password).Password));
// DefaultLogger.LogEntry(LogLevels.Debug, $"3.5 " + ctx.ToString());
DirectoryEntry entry = new DirectoryEntry
{
Path = ldapPath,
Username = username,
Password = new NetworkCredential(username, password).Password,
AuthenticationType = AuthenticationTypes.Secure | AuthenticationTypes.Sealing
};
DefaultLogger.LogEntry(LogLevels.Debug, $"4 " + entry.NativeGuid);
DefaultLogger.LogEntry(LogLevels.Debug, $"5 " + entry.Path);
var tmpFilter = "(&(" + groupLDAPFilter + ")(objectClass=group))";
DefaultLogger.LogEntry(LogLevels.Debug, $"6 " + tmpFilter);
//DefaultLogger.LogEntry(LogLevels.Debug, $"6.5 " + entry.ToString());
DirectorySearcher dSearch = new DirectorySearcher(entry)
{
Filter = tmpFilter
};
dSearch.PageSize = 100000;
DefaultLogger.LogEntry(LogLevels.Debug, $"7 " + dSearch.Filter);
SearchResultCollection sr = dSearch.FindAll();
DefaultLogger.LogEntry(LogLevels.Debug, $"8 " + sr.Count);
if (sr.Count > 0)
{
foreach (SearchResult k in sr)
{
IAM_SecurityGroup sec = new IAM_SecurityGroup();
sec.Name = k.Properties["Name"][0].ToString();
setGroupType(sec);
SecurityIdentifier sid = new SecurityIdentifier(k.Properties["objectSid"][0] as byte[], 0);
sec.UID = sid.Value;
sec.technicalName = k.Properties["distinguishedname"][0].ToString();
sec.targetTyp = Convert.ToInt32(IAM_TargetType.FileSystem);
var group = GroupPrincipal.FindByIdentity(ctx, IdentityType.Sid, sid.Value);
sec.Scope = (GroupScope)group.GroupScope;
var filter = "(&(" + groupLDAPFilter + ")(objectClass=group)(memberOf=" + sec.technicalName + "))";
DirectorySearcher iDSearch = new DirectorySearcher(entry)
{
Filter = filter
};
SearchResultCollection iSr = iDSearch.FindAll();
if (iSr.Count > 0 )
{
foreach (SearchResult iK in iSr)
{
IAM_SecurityGroup iSec = new IAM_SecurityGroup();
iSec.Name = iK.Properties["Name"][0].ToString();
setGroupType(iSec);
SecurityIdentifier iSid = new SecurityIdentifier(iK.Properties["objectSid"][0] as byte[], 0);
iSec.UID = iSid.Value;
iSec.technicalName = iK.Properties["distinguishedname"][0].ToString();
iSec.targetTyp = Convert.ToInt32(IAM_TargetType.FileSystem);
iSec.Parent = sec.UID;
var iGroup = GroupPrincipal.FindByIdentity(ctx, IdentityType.Sid, iSid.Value);
iSec.Scope = (GroupScope)iGroup.GroupScope;
if (!secGroups.IAM_SecurityGroups.Any(s => s.technicalName.Equals(iSec.technicalName)))
{
secGroups.IAM_SecurityGroups.Add(iSec);
DefaultLogger.LogEntry(LogLevels.Debug, $"Found security group: {iSec.technicalName}");
}
}
}
else
if (!secGroups.IAM_SecurityGroups.Any(s => s.technicalName.Equals(sec.technicalName)))
{
secGroups.IAM_SecurityGroups.Add(sec);
DefaultLogger.LogEntry(LogLevels.Debug, $"Found security group: {sec.technicalName}");
}
}
}
ctx.Dispose();
entry.Dispose();
dSearch.Dispose();
sr.Dispose();
SetSecGroupXML(secGroups);
DefaultLogger.LogEntry(LogLevels.Debug, $"{secGroups.IAM_SecurityGroups.Count} AD groups retrieved with following lDAPQuery {groupLDAPFilter}");
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
throw E;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
void setGroupType(IAM_SecurityGroup sec)
{
if (sec.Name.EndsWith(groupOwnerTag))
sec.securityGroupType = SecurityGroupType.Owner;
else if (sec.Name.EndsWith(groupReadTag))
sec.securityGroupType = SecurityGroupType.Read;
else if (sec.Name.EndsWith(groupWriteTag))
sec.securityGroupType = SecurityGroupType.Write;
else if (sec.Name.EndsWith(groupTraverseTag))
sec.securityGroupType = SecurityGroupType.Traverse;
}
}
public void SetDataAreaXML(DataArea dA)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
var xmlserializer = new XmlSerializer(typeof(DataArea));
using (var sww = new StringWriter())
{
XmlWriterSettings setting = new XmlWriterSettings();
setting.OmitXmlDeclaration = true;
using (XmlWriter writer = XmlWriter.Create(sww, setting))
{
xmlserializer.Serialize(writer, dA);
XmlDocument xml = new XmlDocument();
xml.LoadXml(sww.ToString());
DataAreasXML = xml.OuterXml;
}
}
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
throw E;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
public void SetSecGroupXML(SecurityGroups secGroups)
{
LogMethodBegin(MethodBase.GetCurrentMethod());
try
{
var xmlserializer = new XmlSerializer(typeof(SecurityGroups));
using (var sww = new StringWriter())
{
XmlWriterSettings setting = new XmlWriterSettings();
setting.OmitXmlDeclaration = true;
using (XmlWriter writer = XmlWriter.Create(sww, setting))
{
xmlserializer.Serialize(writer, secGroups);
XmlDocument xml = new XmlDocument();
xml.LoadXml(sww.ToString());
SecGroupXML = xml.OuterXml;
}
}
}
catch (Exception E)
{
cLogManager.DefaultLogger.LogException(E);
throw E;
}
finally
{
LogMethodEnd(MethodBase.GetCurrentMethod());
}
}
}
}