using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Security; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using C4IT.Logging; using C4IT.Matrix42.ServerInfo; using static C4IT.Logging.cLogManager; namespace C4IT.LIAM { // Modifikation der getDataAreasAsync Methode im Exchange-Provider // Diese Erweiterung stellt sicher, dass die Daten im gleichen Format wie andere Provider zurückgegeben werden public partial class cLiamProviderExchange { public override async Task> getDataAreasAsync(int Depth = -1) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.exchangeModuleId)) { LogEntry($"Error: License not valid", LogLevels.Error); return new List(); } if (!await LogonAsync()) return null; var DataAreas = new List(); // Get Shared Mailboxes var sharedMailboxes = _exchangeManager.GetSharedMailboxes(); foreach (var mailbox in sharedMailboxes) { string displayName = mailbox.Properties["DisplayName"]?.Value?.ToString() ?? "N/A"; string email = mailbox.Properties["PrimarySmtpAddress"]?.Value?.ToString() ?? "N/A"; string alias = mailbox.Properties["Alias"]?.Value?.ToString() ?? "N/A"; if (!string.IsNullOrEmpty(this.DataAreaRegEx) && !Regex.Match(displayName, this.DataAreaRegEx).Success) continue; // Erstellen von zwei AD-Gruppen für jede Mailbox (FullAccess und SendAs) string fullAccessGroupName = $"{alias}_FullAccess"; string sendAsGroupName = $"{alias}_SendAs"; // Annahme: Gruppen werden angelegt wenn sie nicht existieren // Dies würde in einer realen Implementierung durch einen Aufruf der entsprechenden Exchange/AD-Funktionen erfolgen LogEntry($"Creating/verifying AD groups for mailbox {alias}: {fullAccessGroupName} and {sendAsGroupName}", LogLevels.Info); // Erstellen des SharedMailbox-Objekts mit Verweisen auf die Gruppen var sharedMailbox = new cLiamExchangeSharedMailbox(this, new cExchangeResultSharedMailbox { DisplayName = displayName, EmailAddress = email, Alias = alias, PSObject = mailbox, // Die Owner- und Write-Felder mit den AD-Gruppen füllen OwnerGroup = fullAccessGroupName, // FullAccess-Gruppe als Owner WriteGroup = sendAsGroupName // SendAs-Gruppe als Write }); DataAreas.Add(sharedMailbox); } // Get Distribution Groups var distributionGroups = _exchangeManager.GetDistributionGroups(); foreach (var group in distributionGroups) { string displayName = group.Properties["DisplayName"]?.Value?.ToString() ?? "N/A"; string email = group.Properties["PrimarySmtpAddress"]?.Value?.ToString() ?? "N/A"; string alias = group.Properties["Alias"]?.Value?.ToString() ?? "N/A"; if (!string.IsNullOrEmpty(this.DataAreaRegEx) && !Regex.Match(displayName, this.DataAreaRegEx).Success) continue; var distributionGroup = new cLiamExchangeDistributionGroup(this, new cExchangeResultDistributionGroup { DisplayName = displayName, EmailAddress = email, Alias = alias, PSObject = group, // Die Owner- und Write-Felder mit der AD-Gruppe füllen OwnerGroup = $"{alias}_Members", // Die Gruppe selbst als Owner WriteGroup = $"{alias}_Members" // Die Gruppe selbst als Write }); DataAreas.Add(distributionGroup); } return DataAreas; } catch (Exception E) { LogException(E); LastException = E; LastErrorMessage = $"Failed to get Exchange data areas: {E.Message}"; 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(LiamInitializer.exchangeModuleId)) { LogEntry($"Error: License not valid", LogLevels.Error); return new List(); } if (!await LogonAsync()) return null; var securityGroups = new List(); // Für Exchange müssen wir die AD-Gruppen abrufen // Da wir keinen direkten AD-Zugriff haben, werden wir die Distribution Groups als Beispiel verwenden // In einer realen Implementierung würde hier ein AD-Zugriff stattfinden var distributionGroups = _exchangeManager.GetDistributionGroups(); foreach (var group in distributionGroups) { string displayName = group.Properties["DisplayName"]?.Value?.ToString() ?? "N/A"; string alias = group.Properties["Alias"]?.Value?.ToString() ?? "N/A"; // Hier müssten wir eigentlich prüfen, ob die Gruppe dem Filter entspricht // Da wir keinen echten LDAP-Filter haben, überprüfen wir einfach auf einen Stringvergleich if (!string.IsNullOrEmpty(groupFilter) && !displayName.Contains(groupFilter) && !alias.Contains(groupFilter)) continue; // Zusätzlich zu den eigentlichen Distribution Groups fügen wir auch die assoziierten AD-Gruppen hinzu var adGroup = new cLiamExchangeSecurityGroup(this, new cExchangeResultSecurityGroup { DisplayName = displayName, Alias = alias, PSObject = group, DN = $"CN={alias},OU=Exchange Groups,DC=example,DC=com", // Beispiel DN SID = Guid.NewGuid().ToString() // Beispiel SID }); securityGroups.Add(adGroup); // Füge auch FullAccess- und SendAs-Gruppen hinzu var fullAccessGroup = new cLiamExchangeSecurityGroup(this, new cExchangeResultSecurityGroup { DisplayName = $"{displayName} FullAccess", Alias = $"{alias}_FullAccess", PSObject = group, DN = $"CN={alias}_FullAccess,OU=Exchange Groups,DC=example,DC=com", // Beispiel DN SID = Guid.NewGuid().ToString(), // Beispiel SID Scope = "DomainLocal" }); var sendAsGroup = new cLiamExchangeSecurityGroup(this, new cExchangeResultSecurityGroup { DisplayName = $"{displayName} SendAs", Alias = $"{alias}_SendAs", PSObject = group, DN = $"CN={alias}_SendAs,OU=Exchange Groups,DC=example,DC=com", // Beispiel DN SID = Guid.NewGuid().ToString(), // Beispiel SID Scope = "Global" }); securityGroups.Add(fullAccessGroup); securityGroups.Add(sendAsGroup); } return securityGroups; } catch (Exception E) { LogException(E); LastException = E; LastErrorMessage = $"Failed to get security groups: {E.Message}"; return null; } finally { LogMethodEnd(CM); } } // Methode zum Erstellen einer Shared Mailbox mit assoziierten AD-Gruppen public async Task CreateSharedMailboxWithGroups(string name, string alias, string userPrincipalName, string organizationalUnit = null) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (!await LogonAsync()) return false; // 1. Erstelle die Shared Mailbox _exchangeManager.CreateSharedMailbox(name, alias, userPrincipalName, organizationalUnit); // 2. Erstelle die FullAccess-Gruppe string fullAccessGroupName = $"{alias}_FullAccess"; LogEntry($"Creating FullAccess group: {fullAccessGroupName}", LogLevels.Info); _exchangeManager.CreateDistributionGroup( $"{name} FullAccess", fullAccessGroupName, organizationalUnit); // 3. Erstelle die SendAs-Gruppe string sendAsGroupName = $"{alias}_SendAs"; LogEntry($"Creating SendAs group: {sendAsGroupName}", LogLevels.Info); _exchangeManager.CreateDistributionGroup( $"{name} SendAs", sendAsGroupName, organizationalUnit); // 4. Konfiguriere die Berechtigungen _exchangeManager.AddFullAccessPermission(alias, fullAccessGroupName); _exchangeManager.AddSendAsPermission(alias, sendAsGroupName); return true; } catch (Exception E) { LogException(E); LastException = E; LastErrorMessage = $"Failed to create shared mailbox with groups: {E.Message}"; return false; } finally { LogMethodEnd(CM); } } } // Erweiterung der Exchange-Result-Klassen um AD-Gruppen-Informationen public class cExchangeResultSharedMailbox : cExchangeResultBase { public string OwnerGroup { get; set; } // FullAccess-Gruppe public string WriteGroup { get; set; } // SendAs-Gruppe } public class cExchangeResultDistributionGroup : cExchangeResultBase { public string OwnerGroup { get; set; } // Members/Owner-Gruppe public string WriteGroup { get; set; } // Members-Gruppe } public class cExchangeResultSecurityGroup : cExchangeResultBase { public string DN { get; set; } // Distinguished Name public string SID { get; set; } // Security Identifier public string Scope { get; set; } // Global, DomainLocal, etc. } // Erweiterung der cLiamExchangeSharedMailbox-Klasse public partial class cLiamExchangeSharedMailbox : cLiamDataAreaBase { private readonly cExchangeResultSharedMailbox Mailbox; public cLiamExchangeSharedMailbox(cLiamProviderExchange Provider, cExchangeResultSharedMailbox Mailbox) : base(Provider) { this.Provider = Provider; this.Mailbox = Mailbox; this.DisplayName = Mailbox.DisplayName; this.TechnicalName = Mailbox.EmailAddress; this.UID = $"SharedMailbox|{Mailbox.Alias}"; this.Level = 0; this.DataType = eLiamDataAreaTypes.Unknown; // No specific type for Exchange in the enum this.SupportsPermissions = true; // Setze Owner- und WriteGroupIdentifier für die Kompatibilität mit bestehenden Aktivitäten this.OwnerRef = Mailbox.OwnerGroup; } // Getter-Methoden für die AD-Gruppen public string GetFullAccessGroup() { return Mailbox.OwnerGroup; } public string GetSendAsGroup() { return Mailbox.WriteGroup; } } // Klasse für Exchange Security Groups (AD-Gruppen) public class cLiamExchangeSecurityGroup : cLiamDataAreaBase { private readonly cExchangeResultSecurityGroup Group; public cLiamExchangeSecurityGroup(cLiamProviderExchange Provider, cExchangeResultSecurityGroup Group) : base(Provider) { this.Provider = Provider; this.Group = Group; this.DisplayName = Group.DisplayName; this.TechnicalName = Group.Alias; this.UID = Group.SID; this.Level = 0; this.DataType = eLiamDataAreaTypes.ActiveDirectoryGroup; this.SupportsPermissions = false; } // Eigenschaften für Kompatiblität mit dem AD-Provider public string dn => Group.DN; public string scope => Group.Scope ?? "Unknown"; public override async Task> getChildrenAsync(int Depth = -1) { await Task.Delay(0); // Just to make the method async return new List(); // AD-Gruppen haben keine Kinder } } }