fix: await exchange permission resolution

This commit is contained in:
Meik
2026-03-09 09:33:47 +01:00
parent e4b907856c
commit 3e0ae58e9d
561 changed files with 229 additions and 477445 deletions

View File

@@ -23,12 +23,12 @@ namespace C4IT.LIAM
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;
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)
@@ -66,8 +66,8 @@ namespace C4IT.LIAM
/// 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)
{
internal static string ExtractObjectGuid(dynamic properties)
{
// Erstversuch: objectGUID (wie in AD)
var value = properties["objectGUID"]?.Value;
if (value == null || string.IsNullOrEmpty(value.ToString()))
@@ -79,80 +79,80 @@ namespace C4IT.LIAM
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);
}
return value?.ToString() ?? string.Empty;
}
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
{
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);
}
}
@@ -162,88 +162,90 @@ namespace C4IT.LIAM
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);
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);
await exchangeMailbox.ResolvePermissionGroupsAsync();
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);
await exchangeGroup.ResolvePermissionGroupsAsync();
DataAreas.Add(exchangeGroup);
}
ClearLastError();
return DataAreas;
}
catch (Exception E)
{
LogException(E);
SetLastError("EXCH_GET_DATAAREAS_EXCEPTION", E.Message);
}
finally
{
LogMethodEnd(CM);
}
return null;
}
@@ -289,59 +291,59 @@ namespace C4IT.LIAM
}
}
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);
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;
}
@@ -496,7 +498,6 @@ namespace C4IT.LIAM
this.DataType = eLiamDataAreaTypes.ExchangeSharedMailbox;
this.SupportsOwners = true;
this.SupportsPermissions = true;
_ = assignPermissionGroups(Provider).ConfigureAwait(false);
}
internal static string getUID(string primarySmtpAddress)
@@ -518,7 +519,9 @@ namespace C4IT.LIAM
var alias = mailbox.Properties["Alias"]?.Value?.ToString();
var objectGuid = cLiamProviderExchange.ExtractObjectGuid(mailbox.Properties);
return new cLiamExchangeSharedMailbox(Provider, displayName, primarySmtpAddress, alias, objectGuid);
var mailboxDataArea = new cLiamExchangeSharedMailbox(Provider, displayName, primarySmtpAddress, alias, objectGuid);
await mailboxDataArea.ResolvePermissionGroupsAsync();
return mailboxDataArea;
}
catch (Exception E)
{
@@ -639,7 +642,7 @@ namespace C4IT.LIAM
return new List<cLiamDataAreaBase>();
}
private async Task assignPermissionGroups(cLiamProviderExchange Provider)
public async Task ResolvePermissionGroupsAsync()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
@@ -745,7 +748,6 @@ namespace C4IT.LIAM
this.DataType = eLiamDataAreaTypes.ExchangeDistributionGroup;
this.SupportsOwners = true;
this.SupportsPermissions = true;
_ = assignPermissionGroups(Provider).ConfigureAwait(false);
}
internal static string getUID(string primarySmtpAddress)
@@ -767,7 +769,9 @@ namespace C4IT.LIAM
var alias = group.Properties["Alias"]?.Value?.ToString();
var objectGuid = cLiamProviderExchange.ExtractObjectGuid(group.Properties);
return new cLiamExchangeDistributionGroup(Provider, displayName, primarySmtpAddress, alias, objectGuid);
var groupDataArea = new cLiamExchangeDistributionGroup(Provider, displayName, primarySmtpAddress, alias, objectGuid);
await groupDataArea.ResolvePermissionGroupsAsync();
return groupDataArea;
}
catch (Exception E)
{
@@ -875,7 +879,7 @@ namespace C4IT.LIAM
return new List<cLiamDataAreaBase>();
}
private async Task assignPermissionGroups(cLiamProviderExchange Provider)
public async Task ResolvePermissionGroupsAsync()
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);