using System; using System.Collections.Generic; using System.DirectoryServices.AccountManagement; using System.IO; using System.Linq; using System.Reflection; using System.Security.AccessControl; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using C4IT.Logging; using C4IT.Matrix42.ServerInfo; using LiamAD; using static C4IT.Logging.cLogManager; using static LiamAD.ADServiceGroupCreator; using static LiamAD.cActiveDirectoryBase; namespace C4IT.LIAM { public static class LiamInitializer { static public cLiamProviderBase CreateInstance(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) { return new cLiamProviderAD(LiamConfiguration, ProviderData); } } public class cLiamProviderAD : cLiamProviderBase { public static Guid adModuleId = new Guid("e820a625-0653-ee11-b886-00155d300101"); public readonly cActiveDirectoryBase activeDirectoryBase = new cActiveDirectoryBase(); private readonly ADServiceGroupCreator _serviceGroupCreator; public cLiamProviderAD(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) : base(LiamConfiguration, ProviderData) { _serviceGroupCreator = new ADServiceGroupCreator(this); } public List> CreateServiceGroups( string serviceName, string description = null, eLiamAccessRoleScopes gruppenbereich = eLiamAccessRoleScopes.Universal, ADGroupType gruppentyp = ADGroupType.Distribution, IEnumerable ownerSidList = null, IEnumerable memberSidList = null) { return _serviceGroupCreator.EnsureServiceGroups( serviceName, description, gruppenbereich, gruppentyp, ownerSidList, memberSidList); } public override async Task LogonAsync() { if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId)) { LogEntry($"Error: License not valid", LogLevels.Error); return false; } return await LogonAsync(true); } public async Task LogonAsync(bool force = false) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { var LI = new cADLogonInfo() { Domain = Domain, User = Credential?.Identification, UserSecret = Credential?.Secret, TargetGroupPath = this.GroupPath }; var RetVal = await activeDirectoryBase.LogonAsync(LI); return RetVal; } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return false; } public override async Task> getDataAreasAsync(int Depth = -1) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId)) { LogEntry($"Error: License not valid", LogLevels.Error); return new List(); } if (!await LogonAsync()) return null; if (string.IsNullOrEmpty(this.GroupPath)) return null; // 1. Alle Roh-Resultate einlesen var rawList = await activeDirectoryBase.RequestSecurityGroupsListAsync(this.GroupFilter); if (rawList == null) return null; // 2. Nur die, die dem RegEx entsprechen und deren Wert extrahieren var allResults = rawList .Where(entry => string.IsNullOrEmpty(this.GroupRegEx) || Regex.Match(entry.Value.DisplayName, this.GroupRegEx).Success) .Select(entry => (cSecurityGroupResult)entry.Value) .ToList(); // 3. ManagedBySID-Werte sammeln (ohne Null-/Leereinträge) var managedBySids = new HashSet( allResults .Select(r => r.ManagedBySID) .Where(m => !string.IsNullOrEmpty(m)) ); // 4. Nur die Gruppen, deren ID nicht in managedBySids enthalten ist var filteredResults = allResults .Where(r => !managedBySids.Contains(r.ID)) .ToList(); // 5. In DataArea-Objekte umwandeln var SecurityGroups = new List(); foreach (var secGroup in filteredResults) { SecurityGroups.Add(new cLiamAdGroupAsDataArea(this, secGroup)); } return SecurityGroups; } catch (Exception E) { LogException(E); return null; } finally { LogMethodEnd(CM); } } public override async Task> getSecurityGroupsAsync(string groupFilter) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId)) { LogEntry($"Error: License not valid", LogLevels.Error); return new List(); } if (!await LogonAsync()) return null; if (string.IsNullOrEmpty(this.GroupPath)) return null; var SecurityGroups = new List(); var SGL = await activeDirectoryBase.RequestSecurityGroupsListAsync(groupFilter); if (SGL == null) return null; foreach (var Entry in SGL) { if (!string.IsNullOrEmpty(this.GroupRegEx) && !Regex.Match(Entry.Value.DisplayName, this.GroupRegEx).Success) continue; var SecurityGroup = new cLiamAdGroup2(this, (cSecurityGroupResult)Entry.Value); SecurityGroups.Add(SecurityGroup); } return SecurityGroups; } catch (Exception E) { LogException(E); } finally { LogMethodEnd(CM); } return null; } public int getDepth(string path) { return getDepth(this.RootPath, path); } public static int getDepth(DirectoryInfo root, DirectoryInfo folder) { var rootDepth = root.FullName.TrimEnd(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar).Length; var folderDepth = folder.FullName.TrimEnd(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar).Length; return folderDepth - rootDepth; } public static int getDepth(string root, string folder) { return getDepth(new DirectoryInfo(root), new DirectoryInfo(folder)); } public override string GetLastErrorMessage() { throw new NotImplementedException(); } public override async Task LoadDataArea(string UID) { //TODO implement LoadDataArea var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { await Task.Delay(0); if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId)) { LogEntry($"Error: License not valid", LogLevels.Error); return null; } var res = new cLiamAdGroupAsDataArea(this, new cSecurityGroupResult() { Path = UID }); return res; } catch (Exception E) { LogException(E); return null; } finally { LogMethodEnd(CM); } } } public class cLiamAdGroupAsDataArea : cLiamDataAreaBase { public new readonly cLiamProviderAD Provider = null; public readonly string dn = null; public readonly string scope = null; public readonly string ManagedBySID; public override Task> getChildrenAsync(int Depth = -1) { throw new NotImplementedException(); } public cLiamAdGroupAsDataArea(cLiamProviderAD Provider, cSecurityGroupResult secGroup) : base(Provider) { this.UID = secGroup.ID; this.TechnicalName = secGroup.Path; this.DisplayName = secGroup.DisplayName; this.Description = secGroup.Description; this.Provider = Provider; this.dn = secGroup.Path; this.scope = secGroup.Scope.ToString(); this.ManagedBySID = secGroup.ManagedBySID; } public override async Task> GetOwnersAsync() { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { return await GetMembersAsync(true); } catch (Exception E) { LogException(E); return null; } finally { LogMethodEnd(CM); } } private async Task> GetMembersAsync(bool owners) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { var AD = this.Provider?.activeDirectoryBase; if (AD == null) { LogEntry($"Could not get ad class from Provider for folder '{this.TechnicalName}'", LogLevels.Warning); return null; } cADCollectionBase lstMembers; if (owners && !string.IsNullOrEmpty(OwnerRef)) lstMembers = await AD.GetMembersAsync(OwnerRef); else if (owners && !string.IsNullOrEmpty(dn)) lstMembers = await AD.GetManagedByMembersAsync(this.dn); else lstMembers = null; if (lstMembers == null) { LogEntry($"Could not get owner list for folder '{this.TechnicalName}'", LogLevels.Warning); return null; } var RetVal = new List(lstMembers.Count); LogEntry($"Owners for folder found: {lstMembers.Count}", LogLevels.Debug); foreach (var MemberEntry in lstMembers.Values) { var User = new cLiamUserInfo() { DisplayName = MemberEntry.DisplayName, UserPrincipalName = (MemberEntry as cADUserResult).UserPrincipalName, SID = MemberEntry.ID }; RetVal.Add(User); } return RetVal; } catch (Exception E) { LogException(E); return null; } finally { LogMethodEnd(CM); } } } public class cLiamAdGroup2 : cLiamDataAreaBase { public new readonly cLiamProviderAD Provider = null; public readonly string dn = null; public readonly string scope = null; public override Task> getChildrenAsync(int Depth = -1) { throw new NotImplementedException(); } public cLiamAdGroup2(cLiamProviderAD Provider, cSecurityGroupResult secGroup) : base(Provider) { this.DisplayName = secGroup.DisplayName; this.UID = secGroup.ID; this.TechnicalName = secGroup.DisplayName; this.Provider = Provider; this.dn = secGroup.Path; this.scope = secGroup.Scope.ToString(); } } }