Files
LIAM/LiamExchange/C4IT.LIAM.Exchange.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

942 lines
37 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
using C4IT.Matrix42.ServerInfo;
using System.Text.RegularExpressions;
using LiamNtfs;
using System.DirectoryServices;
using System.Security.Principal;
namespace C4IT.LIAM
{
public class cLiamProviderExchange : cLiamProviderBase
{
public static Guid exchangeModuleId = new Guid("A1E213C3-6517-EA11-4881-000C2980FD95");
public readonly ExchangeManager exchangeManager;
internal readonly cActiveDirectoryBase activeDirectoryBase = new cActiveDirectoryBase();
private string exchangeUri;
private PSCredential credential;
private string organizationalUnit;
private string lastErrorCode = string.Empty;
private string lastErrorMessage;
private bool isLoggedOn = false;
public cLiamProviderExchange(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) :
base(LiamConfiguration, ProviderData)
{
exchangeUri = ProviderData.RootPath;
if (!string.IsNullOrEmpty(ProviderData.GroupPath))
organizationalUnit = ProviderData.GroupPath;
else
organizationalUnit = ProviderData.Domain;
// Credential erstellen
var securePassword = new SecureString();
foreach (char c in ProviderData.Credential.Secret)
{
securePassword.AppendChar(c);
}
credential = new PSCredential(ProviderData.Credential.Identification, securePassword);
// ExchangeManager initialisieren
exchangeManager = new ExchangeManager(this, exchangeUri, credential, ProviderData.Domain, organizationalUnit);
// AD-Zugriff initialisieren
var LI = new cNtfsLogonInfo()
{
Domain = Domain,
User = Credential?.Identification,
UserSecret = Credential?.Secret,
TargetGroupPath = this.GroupPath
};
// Asynchrone Initialisierung starten
_ = activeDirectoryBase.LogonAsync(LI).ConfigureAwait(false);
}
/// <summary>
/// Extrahiert den GUID-Wert aus den Properties.
/// Zunächst wird versucht, "objectGUID" zu lesen ist dieser leer, wird "GUID" verwendet.
/// </summary>
internal static string ExtractObjectGuid(dynamic properties)
{
// Erstversuch: objectGUID (wie in AD)
var value = properties["objectGUID"]?.Value;
if (value == null || string.IsNullOrEmpty(value.ToString()))
{
// Alternative: GUID (wie von den Exchange-Cmdlets zurückgegeben)
value = properties["GUID"]?.Value;
}
if (value is byte[] guidBytes)
return new Guid(guidBytes).ToString();
if (value is Guid guid)
return guid.ToString();
return value?.ToString() ?? string.Empty;
}
public string GetLastErrorCode()
{
return lastErrorCode;
}
private void ClearLastError()
{
lastErrorCode = string.Empty;
lastErrorMessage = string.Empty;
}
private void SetLastError(string code, string message)
{
lastErrorCode = string.IsNullOrWhiteSpace(code) ? "EXCH_UNKNOWN_ERROR" : code;
lastErrorMessage = message ?? string.Empty;
LogEntry($"[{lastErrorCode}] {lastErrorMessage}", LogLevels.Error);
}
public override async Task<bool> LogonAsync()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
ClearLastError();
if (!cC4ITLicenseM42ESM.Instance.IsValid)
{
SetLastError("EXCH_LOGON_LICENSE_INVALID", "License not valid or Exchange module not licensed");
return false;
}
try
{
var testMailboxes = exchangeManager.GetSharedMailboxes(
"Name -like '*'",
out string errorCode,
out string errorMessage);
if (testMailboxes == null)
{
SetLastError(errorCode, $"Failed to connect to Exchange: {errorMessage}");
isLoggedOn = false;
return false;
}
if (testMailboxes != null)
{
LogEntry("Successfully connected to Exchange", LogLevels.Info);
isLoggedOn = true;
ClearLastError();
return true;
}
}
catch (Exception ex)
{
LogException(ex);
SetLastError("EXCH_LOGON_EXCEPTION", $"Failed to connect to Exchange: {ex.Message}");
isLoggedOn = false;
return false;
}
SetLastError("EXCH_LOGON_FAILED", "Unknown error connecting to Exchange");
return false;
}
catch (Exception E)
{
LogException(E);
SetLastError("EXCH_LOGON_EXCEPTION", $"Exception during Exchange logon: {E.Message}");
return false;
}
finally
{
LogMethodEnd(CM);
}
}
public override string GetLastErrorMessage()
{
return lastErrorMessage;
}
public override async Task<List<cLiamDataAreaBase>> getDataAreasAsync(int MaxDepth = -1)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
ClearLastError();
if (!cC4ITLicenseM42ESM.Instance.IsValid)
{
SetLastError("EXCH_GET_DATAAREAS_LICENSE_INVALID", "License not valid or Exchange module not licensed");
return new List<cLiamDataAreaBase>();
}
if (!isLoggedOn && !await LogonAsync())
return null;
var DataAreas = new List<cLiamDataAreaBase>();
// Shared Mailboxes
var sharedMailboxes = exchangeManager.GetSharedMailboxes(
null,
out string sharedErrorCode,
out string sharedErrorMessage);
if (sharedMailboxes == null)
{
SetLastError(sharedErrorCode, $"Failed to read shared mailboxes: {sharedErrorMessage}");
return null;
}
foreach (var mailbox in sharedMailboxes)
{
var displayName = mailbox.Properties["DisplayName"]?.Value?.ToString();
var alias = mailbox.Properties["Alias"]?.Value?.ToString();
var primarySmtpAddress = mailbox.Properties["PrimarySmtpAddress"]?.Value?.ToString();
var objectGuid = ExtractObjectGuid(mailbox.Properties);
// Filterung via Regex
if (!string.IsNullOrEmpty(this.DataAreaRegEx) &&
!Regex.Match(displayName, this.DataAreaRegEx).Success)
continue;
var exchangeMailbox = new cLiamExchangeSharedMailbox(this, displayName, primarySmtpAddress, alias, objectGuid);
DataAreas.Add(exchangeMailbox);
}
// Distribution Groups
var distributionGroups = exchangeManager.GetDistributionGroups(
null,
out string distErrorCode,
out string distErrorMessage);
if (distributionGroups == null)
{
SetLastError(distErrorCode, $"Failed to read distribution groups: {distErrorMessage}");
return null;
}
foreach (var group in distributionGroups)
{
var displayName = group.Properties["DisplayName"]?.Value?.ToString();
var alias = group.Properties["Alias"]?.Value?.ToString();
var primarySmtpAddress = group.Properties["PrimarySmtpAddress"]?.Value?.ToString();
var objectGuid = ExtractObjectGuid(group.Properties);
if (!string.IsNullOrEmpty(this.DataAreaRegEx) &&
!Regex.Match(displayName, this.DataAreaRegEx).Success)
continue;
var exchangeGroup = new cLiamExchangeDistributionGroup(this, displayName, primarySmtpAddress, alias, objectGuid);
DataAreas.Add(exchangeGroup);
}
ClearLastError();
return DataAreas;
}
catch (Exception E)
{
LogException(E);
SetLastError("EXCH_GET_DATAAREAS_EXCEPTION", E.Message);
}
finally
{
LogMethodEnd(CM);
}
return null;
}
public override async Task<cLiamDataAreaBase> LoadDataArea(string UID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var dataType = cLIAMHelper.getUidItem(ref UID);
if (string.IsNullOrEmpty(dataType))
return null;
if (!int.TryParse(dataType, out int dataTypeInt))
return null;
var primarySmtpAddress = cLIAMHelper.getUidItem(ref UID);
if (string.IsNullOrEmpty(primarySmtpAddress))
return null;
if (!isLoggedOn && !await LogonAsync())
return null;
switch ((eLiamDataAreaTypes)dataTypeInt)
{
case eLiamDataAreaTypes.ExchangeSharedMailbox:
return await cLiamExchangeSharedMailbox.Load(this, primarySmtpAddress);
case eLiamDataAreaTypes.ExchangeDistributionGroup:
return await cLiamExchangeDistributionGroup.Load(this, primarySmtpAddress);
default:
return null;
}
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<List<cLiamDataAreaBase>> getSecurityGroupsAsync(string groupFilter)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
ClearLastError();
if (!cC4ITLicenseM42ESM.Instance.IsValid)
{
SetLastError("EXCH_GET_SECURITYGROUPS_LICENSE_INVALID", "License not valid or Exchange module not licensed");
return new List<cLiamDataAreaBase>();
}
if (!isLoggedOn && !await LogonAsync())
return null;
var securityGroups = new List<cLiamDataAreaBase>();
var groups = exchangeManager.GetSecurityGroups(
groupFilter,
out string errorCode,
out string errorMessage);
if (groups == null)
{
SetLastError(errorCode, $"Failed to read security groups: {errorMessage}");
return null;
}
foreach (var group in groups)
{
var displayName = group.Properties["DisplayName"]?.Value?.ToString();
var sid = group.Properties["Sid"]?.Value?.ToString();
var dn = group.Properties["DistinguishedName"]?.Value?.ToString();
var objectGuid = ExtractObjectGuid(group.Properties);
if (!string.IsNullOrEmpty(this.GroupRegEx) &&
!Regex.Match(displayName, this.GroupRegEx).Success)
continue;
var securityGroup = new cLiamExchangeSecurityGroup(this, displayName, sid, dn, objectGuid);
securityGroups.Add(securityGroup);
}
ClearLastError();
return securityGroups;
}
catch (Exception E)
{
LogException(E);
SetLastError("EXCH_GET_SECURITYGROUPS_EXCEPTION", E.Message);
}
finally
{
LogMethodEnd(CM);
}
return null;
}
// Hilfsmethoden zur Interaktion mit Exchange
internal async Task<bool> AddMemberToGroup(string groupName, string member, bool isSharedMailbox)
{
try
{
if (isSharedMailbox)
exchangeManager.AddMailboxPermission(groupName, member);
else
exchangeManager.AddMemberToDistributionGroup(groupName, member);
return true;
}
catch (Exception ex)
{
LogException(ex);
lastErrorMessage = $"Error adding member to group: {ex.Message}";
return false;
}
}
internal async Task<bool> RemoveMemberFromGroup(string groupName, string member, bool isSharedMailbox)
{
try
{
if (isSharedMailbox)
exchangeManager.RemoveMailboxPermission(groupName, member);
else
exchangeManager.RemoveMemberFromDistributionGroup(groupName, member);
return true;
}
catch (Exception ex)
{
LogException(ex);
lastErrorMessage = $"Error removing member from group: {ex.Message}";
return false;
}
}
public async Task<cLiamExchangeSecurityGroup> GetManagedByGroup(string groupDn)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (activeDirectoryBase.adContext == null)
{
LogEntry("Active Directory context not initialized", LogLevels.Error);
return null;
}
string ldapPath = $"LDAP://{groupDn}";
DirectoryEntry groupEntry = null;
try
{
groupEntry = new DirectoryEntry(
ldapPath,
this.Credential?.Identification,
this.Credential?.Secret,
AuthenticationTypes.Secure | AuthenticationTypes.Sealing);
if (groupEntry.Properties.Contains("managedBy") && groupEntry.Properties["managedBy"].Value != null)
{
string managedByDn = groupEntry.Properties["managedBy"].Value.ToString();
string managedByLdapPath = $"LDAP://{managedByDn}";
using (DirectoryEntry managedByEntry = new DirectoryEntry(
managedByLdapPath,
this.Credential?.Identification,
this.Credential?.Secret,
AuthenticationTypes.Secure | AuthenticationTypes.Sealing))
{
if (managedByEntry.SchemaClassName == "group")
{
byte[] sidBytes = (byte[])managedByEntry.Properties["objectSid"].Value;
SecurityIdentifier sid = new SecurityIdentifier(sidBytes, 0);
string displayName = managedByEntry.Properties["displayName"]?.Value?.ToString()
?? managedByEntry.Properties["name"]?.Value?.ToString();
return new cLiamExchangeSecurityGroup(this, displayName, sid.Value, managedByDn, sid.Value);
}
}
}
}
catch (Exception ex)
{
LogException(ex);
}
finally
{
groupEntry?.Dispose();
}
return null;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
}
public class cLiamExchangeSecurityGroup : cLiamDataAreaBase
{
public new readonly cLiamProviderExchange Provider = null;
public readonly string sid = null;
public readonly string dn = null;
// objectGuid wird nun als TechnicalName genutzt
public cLiamExchangeSecurityGroup(cLiamProviderExchange Provider, string displayName, string sid, string dn, string objectGuid) : base(Provider)
{
this.Provider = Provider;
this.TechnicalName = displayName;
this.DisplayName = displayName;
this.UID = sid;
this.sid = sid;
this.dn = dn;
}
public override Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
{
return Task.FromResult(new List<cLiamDataAreaBase>());
}
}
public class cLiamExchangeSharedMailbox : cLiamDataAreaBase
{
public new readonly cLiamProviderExchange Provider = null;
public readonly string PrimarySmtpAddress = null;
public readonly string Alias = null;
public string OwnerGroupIdentifier = "S-1-0-0";
public string FullAccessGroupSid = "S-1-0-0";
public string SendAsGroupSid = "S-1-0-0";
// objectGuid wird für TechnicalName genutzt
public cLiamExchangeSharedMailbox(cLiamProviderExchange Provider, string displayName, string primarySmtpAddress, string alias, string objectGuid) : base(Provider)
{
this.Provider = Provider;
this.TechnicalName = objectGuid;
this.DisplayName = displayName;
this.PrimarySmtpAddress = primarySmtpAddress;
this.Alias = alias;
this.UID = getUID(primarySmtpAddress);
this.Level = 0;
this.DataType = eLiamDataAreaTypes.ExchangeSharedMailbox;
this.SupportsOwners = true;
this.SupportsPermissions = true;
_ = assignPermissionGroups(Provider).ConfigureAwait(false);
}
internal static string getUID(string primarySmtpAddress)
{
return $"{(int)eLiamDataAreaTypes.ExchangeSharedMailbox}|{primarySmtpAddress}";
}
public static async Task<cLiamExchangeSharedMailbox> Load(cLiamProviderExchange Provider, string primarySmtpAddress)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var mailbox = Provider.exchangeManager.GetSharedMailboxByAddress(primarySmtpAddress);
if (mailbox == null)
return null;
var displayName = mailbox.Properties["DisplayName"]?.Value?.ToString();
var alias = mailbox.Properties["Alias"]?.Value?.ToString();
var objectGuid = cLiamProviderExchange.ExtractObjectGuid(mailbox.Properties);
return new cLiamExchangeSharedMailbox(Provider, displayName, primarySmtpAddress, alias, objectGuid);
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<List<cLiamUserInfo>> GetOwnersAsync()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var members = Provider.exchangeManager.GetMailboxPermissionMembers(this.TechnicalName);
if (members == null)
return new List<cLiamUserInfo>();
var ownersList = new List<cLiamUserInfo>();
foreach (var member in members)
{
var userInfo = new cLiamUserInfo
{
DisplayName = member.Properties["DisplayName"]?.Value?.ToString(),
UserPrincipalName = member.Properties["UserPrincipalName"]?.Value?.ToString(),
EMail = member.Properties["PrimarySmtpAddress"]?.Value?.ToString(),
SID = member.Properties["Sid"]?.Value?.ToString()
};
ownersList.Add(userInfo);
}
return ownersList;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<cLiamPermissionResult> GrantPermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
bool success = false;
switch (Role)
{
case eLiamAccessRoles.Owner:
success = await Provider.AddMemberToGroup(this.DisplayName, User.UserPrincipalName, true);
break;
case eLiamAccessRoles.Write:
success = await Provider.exchangeManager.AddSendAsPermission(this.DisplayName, User.UserPrincipalName);
break;
default:
LogEntry($"Unsupported permission role for Exchange mailbox: {Role}", LogLevels.Warning);
return new cLiamPermissionResult { Valid = false };
}
return new cLiamPermissionResult
{
Valid = success,
UserReference = User.UserPrincipalName
};
}
catch (Exception E)
{
LogException(E);
return new cLiamPermissionResult { Valid = false };
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<bool> RevokePermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
bool success = false;
switch (Role)
{
case eLiamAccessRoles.Owner:
success = await Provider.RemoveMemberFromGroup(this.DisplayName, User.UserPrincipalName, true);
break;
case eLiamAccessRoles.Write:
success = await Provider.exchangeManager.RemoveSendAsPermission(this.DisplayName, User.UserPrincipalName);
break;
default:
LogEntry($"Unsupported permission role for Exchange mailbox: {Role}", LogLevels.Warning);
return false;
}
return success;
}
catch (Exception E)
{
LogException(E);
return false;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
{
return new List<cLiamDataAreaBase>();
}
private async Task assignPermissionGroups(cLiamProviderExchange Provider)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var fullAccessNamingConvention = Provider.NamingConventions.FirstOrDefault(i =>
i.AccessRole == eLiamAccessRoles.ExchangeSMBFullAccess);
var sendAsNamingConvention = Provider.NamingConventions.FirstOrDefault(i =>
i.AccessRole == eLiamAccessRoles.ExchangeSMBSendAs);
if (fullAccessNamingConvention == null || sendAsNamingConvention == null)
{
LogEntry("Naming conventions for Exchange mailbox permissions not found", LogLevels.Warning);
return;
}
try
{
var fullAccessPermissions = Provider.exchangeManager.GetFullAccessPermissionGroups(this.TechnicalName);
if (fullAccessPermissions != null)
{
foreach (var permission in fullAccessPermissions)
{
string samAccountName = permission.Properties["SamAccountName"]?.Value?.ToString();
string sid = permission.Properties["Sid"]?.Value?.ToString();
if (!string.IsNullOrEmpty(samAccountName) && !string.IsNullOrEmpty(sid))
{
//if (Regex.IsMatch(samAccountName, fullAccessNamingConvention.Wildcard, RegexOptions.IgnoreCase))
{
this.FullAccessGroupSid = sid;
LogEntry($"Found FullAccess group {samAccountName} (SID: {sid}) for mailbox {this.DisplayName}", LogLevels.Debug);
string dn = permission.Properties["DistinguishedName"]?.Value?.ToString();
if (!string.IsNullOrEmpty(dn))
{
var managedByGroup = await Provider.GetManagedByGroup(dn);
if (managedByGroup != null)
{
this.OwnerGroupIdentifier = managedByGroup.sid;
LogEntry($"Found owner group {managedByGroup.TechnicalName} (SID: {managedByGroup.sid}) for mailbox {this.DisplayName}", LogLevels.Debug);
}
}
}
}
}
}
var sendAsPermissions = Provider.exchangeManager.GetSendAsPermissionGroups(this.TechnicalName);
if (sendAsPermissions != null)
{
foreach (var permission in sendAsPermissions)
{
string recipientType = permission.Properties["RecipientType"]?.Value?.ToString();
string samAccountName = permission.Properties["SamAccountName"]?.Value?.ToString();
string sid = permission.Properties["Sid"]?.Value?.ToString();
if (!string.IsNullOrEmpty(samAccountName) && !string.IsNullOrEmpty(sid))
{
//if (Regex.IsMatch(samAccountName, sendAsNamingConvention.Wildcard, RegexOptions.IgnoreCase))
{
this.SendAsGroupSid = sid;
LogEntry($"Found SendAs group {samAccountName} (SID: {sid}) for mailbox {this.DisplayName}", LogLevels.Debug);
}
}
}
}
}
catch (Exception ex)
{
LogException(ex);
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
LogMethodEnd(CM);
}
}
}
public class cLiamExchangeDistributionGroup : cLiamDataAreaBase
{
public new readonly cLiamProviderExchange Provider = null;
public readonly string PrimarySmtpAddress = null;
public readonly string Alias = null;
public string OwnerGroupIdentifier = "S-1-0-0";
public string MemberGroupSid = "S-1-0-0";
// objectGuid wird als TechnicalName gesetzt
public cLiamExchangeDistributionGroup(cLiamProviderExchange Provider, string displayName, string primarySmtpAddress, string alias, string objectGuid) : base(Provider)
{
this.Provider = Provider;
this.TechnicalName = objectGuid;
this.DisplayName = displayName;
this.PrimarySmtpAddress = primarySmtpAddress;
this.Alias = alias;
this.UID = getUID(primarySmtpAddress);
this.Level = 0;
this.DataType = eLiamDataAreaTypes.ExchangeDistributionGroup;
this.SupportsOwners = true;
this.SupportsPermissions = true;
_ = assignPermissionGroups(Provider).ConfigureAwait(false);
}
internal static string getUID(string primarySmtpAddress)
{
return $"{(int)eLiamDataAreaTypes.ExchangeDistributionGroup}|{primarySmtpAddress}";
}
public static async Task<cLiamExchangeDistributionGroup> Load(cLiamProviderExchange Provider, string primarySmtpAddress)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var group = Provider.exchangeManager.GetDistributionGroupByAddress(primarySmtpAddress);
if (group == null)
return null;
var displayName = group.Properties["DisplayName"]?.Value?.ToString();
var alias = group.Properties["Alias"]?.Value?.ToString();
var objectGuid = cLiamProviderExchange.ExtractObjectGuid(group.Properties);
return new cLiamExchangeDistributionGroup(Provider, displayName, primarySmtpAddress, alias, objectGuid);
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<List<cLiamUserInfo>> GetOwnersAsync()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var members = Provider.exchangeManager.GetDistributionGroupMembers(this.TechnicalName);
if (members == null)
return new List<cLiamUserInfo>();
var membersList = new List<cLiamUserInfo>();
foreach (var member in members)
{
var userInfo = new cLiamUserInfo
{
DisplayName = member.Properties["DisplayName"]?.Value?.ToString(),
UserPrincipalName = member.Properties["UserPrincipalName"]?.Value?.ToString(),
EMail = member.Properties["PrimarySmtpAddress"]?.Value?.ToString(),
SID = member.Properties["Sid"]?.Value?.ToString()
};
membersList.Add(userInfo);
}
return membersList;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<cLiamPermissionResult> GrantPermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (Role != eLiamAccessRoles.Owner)
{
LogEntry($"Only Owner role is supported for distribution groups, requested: {Role}", LogLevels.Warning);
return new cLiamPermissionResult { Valid = false };
}
bool success = await Provider.AddMemberToGroup(this.DisplayName, User.UserPrincipalName, false);
return new cLiamPermissionResult
{
Valid = success,
UserReference = User.UserPrincipalName
};
}
catch (Exception E)
{
LogException(E);
return new cLiamPermissionResult { Valid = false };
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<bool> RevokePermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (Role != eLiamAccessRoles.Owner)
{
LogEntry($"Only Owner role is supported for distribution groups, requested: {Role}", LogLevels.Warning);
return false;
}
return await Provider.RemoveMemberFromGroup(this.DisplayName, User.UserPrincipalName, false);
}
catch (Exception E)
{
LogException(E);
return false;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
{
return new List<cLiamDataAreaBase>();
}
private async Task assignPermissionGroups(cLiamProviderExchange Provider)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var namingConvention = Provider.NamingConventions
.FirstOrDefault(nc => nc.AccessRole == eLiamAccessRoles.ExchangeMLMember);
if (namingConvention == null)
{
LogEntry("Naming convention for DL-Member not found", LogLevels.Warning);
return;
}
try
{
// ruft alle Gruppen auf dem DL ab
var memberGroups = Provider.exchangeManager
.GetDistributionGroupMembers(this.TechnicalName);
foreach (var group in memberGroups)
{
var sam = group.Properties["SamAccountName"]?.Value?.ToString();
var sid = group.Properties["Sid"]?.Value?.ToString();
if (string.IsNullOrEmpty(sam) || string.IsNullOrEmpty(sid))
continue;
// falls gewünscht: Filter nach Namenskonvention
// if (!Regex.IsMatch(sam, namingConvention.Wildcard, RegexOptions.IgnoreCase))
// continue;
// hier beispielsweise in eine List<string> MemberGroupSids aufnehmen
this.MemberGroupSid = sid;
LogEntry($"Found DL-member group {sam} (SID: {sid}) for distribution list {this.DisplayName}", LogLevels.Debug);
// optional: falls die Gruppe ein ManagedBy hat
var dn = group.Properties["DistinguishedName"]?.Value?.ToString();
if (!string.IsNullOrEmpty(dn))
{
var mgr = await Provider.GetManagedByGroup(dn);
if (mgr != null)
{
this.OwnerGroupIdentifier = mgr.sid;
LogEntry($"Found owner group {mgr.TechnicalName} (SID: {mgr.sid}) for distribution list {this.DisplayName}", LogLevels.Debug);
}
}
}
}
catch (Exception ex)
{
LogException(ex);
}
}
catch (Exception E)
{
LogException(E);
}
finally
{
LogMethodEnd(CM);
}
}
}
}