initial
This commit is contained in:
329
LieamExchange/C4IT.LIAM.Exchange-Update.cs
Normal file
329
LieamExchange/C4IT.LIAM.Exchange-Update.cs
Normal file
@@ -0,0 +1,329 @@
|
||||
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<List<cLiamDataAreaBase>> 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<cLiamDataAreaBase>();
|
||||
}
|
||||
|
||||
if (!await LogonAsync())
|
||||
return null;
|
||||
|
||||
var DataAreas = new List<cLiamDataAreaBase>();
|
||||
|
||||
// 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<List<cLiamDataAreaBase>> 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<cLiamDataAreaBase>();
|
||||
}
|
||||
|
||||
if (!await LogonAsync())
|
||||
return null;
|
||||
|
||||
var securityGroups = new List<cLiamDataAreaBase>();
|
||||
|
||||
// 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<bool> 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<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
||||
{
|
||||
await Task.Delay(0); // Just to make the method async
|
||||
return new List<cLiamDataAreaBase>(); // AD-Gruppen haben keine Kinder
|
||||
}
|
||||
}
|
||||
}
|
||||
535
LieamExchange/C4IT.LIAM.Exchange.cs
Normal file
535
LieamExchange/C4IT.LIAM.Exchange.cs
Normal file
@@ -0,0 +1,535 @@
|
||||
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
|
||||
{
|
||||
public static class LiamExchangeProviderRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// This registry helps us manage Exchange providers since they can't be registered in the enum
|
||||
/// </summary>
|
||||
private static Dictionary<Guid, cLiamProviderExchange> _registeredProviders = new Dictionary<Guid, cLiamProviderExchange>();
|
||||
|
||||
/// <summary>
|
||||
/// Register an Exchange provider
|
||||
/// </summary>
|
||||
public static void RegisterProvider(Guid configId, cLiamProviderExchange provider)
|
||||
{
|
||||
if (_registeredProviders.ContainsKey(configId))
|
||||
{
|
||||
_registeredProviders[configId] = provider;
|
||||
}
|
||||
else
|
||||
{
|
||||
_registeredProviders.Add(configId, provider);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a registered Exchange provider
|
||||
/// </summary>
|
||||
public static cLiamProviderExchange GetProvider(Guid configId)
|
||||
{
|
||||
if (_registeredProviders.ContainsKey(configId))
|
||||
{
|
||||
return _registeredProviders[configId];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LiamInitializer
|
||||
{
|
||||
public static Guid exchangeModuleId = new Guid("f8a23b4c-2d92-ec11-5437-00155d500102");
|
||||
|
||||
static public cLiamProviderBase CreateInstance(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData)
|
||||
{
|
||||
return new cLiamProviderExchange(LiamConfiguration, ProviderData);
|
||||
}
|
||||
}
|
||||
|
||||
public class cLiamProviderExchange : cLiamProviderBase
|
||||
{
|
||||
private ExchangeManager _exchangeManager = null;
|
||||
private bool _isOnline = false;
|
||||
public string LastErrorMessage { get; private set; } = null;
|
||||
public Exception LastException { get; private set; } = null;
|
||||
|
||||
public cLiamProviderExchange(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) :
|
||||
base(LiamConfiguration, ProviderData)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<bool> LogonAsync()
|
||||
{
|
||||
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(LiamInitializer.exchangeModuleId))
|
||||
{
|
||||
LogEntry($"Error: License not valid", LogLevels.Error);
|
||||
return false;
|
||||
}
|
||||
return await LogonAsync(true);
|
||||
}
|
||||
|
||||
public async Task<bool> LogonAsync(bool force = false)
|
||||
{
|
||||
if (!force && _isOnline)
|
||||
return true;
|
||||
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (_exchangeManager != null)
|
||||
{
|
||||
_exchangeManager.Dispose();
|
||||
_exchangeManager = null;
|
||||
}
|
||||
|
||||
SecureString securePassword = new SecureString();
|
||||
if (this.Credential?.Secret != null)
|
||||
{
|
||||
foreach (char c in this.Credential.Secret)
|
||||
{
|
||||
securePassword.AppendChar(c);
|
||||
}
|
||||
securePassword.MakeReadOnly();
|
||||
}
|
||||
|
||||
_exchangeManager = new ExchangeManager(
|
||||
this.RootPath, // Exchange Server FQDN
|
||||
this.Credential?.Identification,
|
||||
securePassword
|
||||
);
|
||||
|
||||
_isOnline = true;
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
LastException = E;
|
||||
LastErrorMessage = $"Exchange login failed: {E.Message}";
|
||||
_isOnline = false;
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetLastErrorMessage()
|
||||
{
|
||||
return LastErrorMessage;
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> 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<cLiamDataAreaBase>();
|
||||
}
|
||||
|
||||
if (!await LogonAsync())
|
||||
return null;
|
||||
|
||||
var DataAreas = new List<cLiamDataAreaBase>();
|
||||
|
||||
// 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;
|
||||
|
||||
var sharedMailbox = new cLiamExchangeSharedMailbox(this, new cExchangeResultSharedMailbox
|
||||
{
|
||||
DisplayName = displayName,
|
||||
EmailAddress = email,
|
||||
Alias = alias,
|
||||
PSObject = mailbox
|
||||
});
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
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<cLiamDataAreaBase> LoadDataArea(string UID)
|
||||
{
|
||||
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 null;
|
||||
}
|
||||
|
||||
if (!await LogonAsync())
|
||||
return null;
|
||||
|
||||
// Parse the UID to determine the type and ID
|
||||
var parts = UID.Split('|');
|
||||
if (parts.Length < 2)
|
||||
return null;
|
||||
|
||||
string type = parts[0];
|
||||
string id = parts[1];
|
||||
|
||||
if (type.Equals("SharedMailbox", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Implement loading a specific shared mailbox
|
||||
// This would require a command like Get-Mailbox -Identity <id>
|
||||
return null; // Placeholder, implement actual loading
|
||||
}
|
||||
else if (type.Equals("DistributionGroup", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Implement loading a specific distribution group
|
||||
// This would require a command like Get-DistributionGroup -Identity <id>
|
||||
return null; // Placeholder, implement actual loading
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
LastException = E;
|
||||
LastErrorMessage = $"Failed to load Exchange data area: {E.Message}";
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> getSecurityGroupsAsync(string groupFilter)
|
||||
{
|
||||
await Task.Delay(0); // Just to make the method async
|
||||
return new List<cLiamDataAreaBase>(); // Not implemented for Exchange provider
|
||||
}
|
||||
|
||||
// Method to create a new shared mailbox
|
||||
public async Task<bool> CreateSharedMailbox(string name, string alias, string userPrincipalName, string organizationalUnit = null)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (!await LogonAsync())
|
||||
return false;
|
||||
|
||||
_exchangeManager.CreateSharedMailbox(name, alias, userPrincipalName, organizationalUnit);
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
LastException = E;
|
||||
LastErrorMessage = $"Failed to create shared mailbox: {E.Message}";
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
// Method to create a new distribution group
|
||||
public async Task<bool> CreateDistributionGroup(string name, string alias, string organizationalUnit = null, string managedBy = null)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (!await LogonAsync())
|
||||
return false;
|
||||
|
||||
_exchangeManager.CreateDistributionGroup(name, alias, organizationalUnit, managedBy);
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
LastException = E;
|
||||
LastErrorMessage = $"Failed to create distribution group: {E.Message}";
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
// Method to add member to distribution group
|
||||
public async Task<bool> AddMemberToDistributionGroup(string groupIdentity, string memberIdentity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (!await LogonAsync())
|
||||
return false;
|
||||
|
||||
_exchangeManager.AddMemberToDistributionGroup(groupIdentity, memberIdentity);
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
LastException = E;
|
||||
LastErrorMessage = $"Failed to add member to distribution group: {E.Message}";
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
// Method to add full access permission to a shared mailbox
|
||||
public async Task<bool> AddFullAccessPermission(string mailboxIdentity, string userIdentity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (!await LogonAsync())
|
||||
return false;
|
||||
|
||||
_exchangeManager.AddFullAccessPermission(mailboxIdentity, userIdentity);
|
||||
return true;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
LastException = E;
|
||||
LastErrorMessage = $"Failed to add full access permission: {E.Message}";
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
// Dispose pattern to clean up Exchange manager
|
||||
private bool disposed = false;
|
||||
|
||||
public void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_exchangeManager != null)
|
||||
{
|
||||
_exchangeManager.Dispose();
|
||||
_exchangeManager = null;
|
||||
}
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
~cLiamProviderExchange()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Base class for Exchange results
|
||||
public class cExchangeResultBase
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
public string EmailAddress { get; set; }
|
||||
public string Alias { get; set; }
|
||||
public PSObject PSObject { get; set; }
|
||||
}
|
||||
|
||||
// Class for Shared Mailbox results
|
||||
public class cExchangeResultSharedMailbox : cExchangeResultBase
|
||||
{
|
||||
}
|
||||
|
||||
// Class for Distribution Group results
|
||||
public class cExchangeResultDistributionGroup : cExchangeResultBase
|
||||
{
|
||||
}
|
||||
|
||||
// Class representing an Exchange Shared Mailbox
|
||||
public class cLiamExchangeSharedMailbox : cLiamDataAreaBase
|
||||
{
|
||||
public new readonly cLiamProviderExchange Provider = null;
|
||||
private readonly cExchangeResultSharedMailbox Mailbox = null;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
||||
{
|
||||
await Task.Delay(0); // Just to make the method async
|
||||
return new List<cLiamDataAreaBase>(); // Shared mailboxes don't have children
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamPermissionInfo>> GetPermissionsAsync(bool force = false)
|
||||
{
|
||||
// Implementation would retrieve permissions for the mailbox
|
||||
await Task.Delay(0);
|
||||
return null; // Placeholder, actual implementation would query Exchange
|
||||
}
|
||||
|
||||
public override async Task<cLiamPermissionResult> GrantPermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
|
||||
{
|
||||
var result = new cLiamPermissionResult { Valid = false };
|
||||
|
||||
try
|
||||
{
|
||||
// Convert LIAM access role to Exchange permission
|
||||
if (Role == eLiamAccessRoles.Owner || Role == eLiamAccessRoles.Write)
|
||||
{
|
||||
// Add full access permission
|
||||
bool success = await Provider.AddFullAccessPermission(Mailbox.Alias, User.UserPrincipalName);
|
||||
if (success)
|
||||
{
|
||||
result.Valid = true;
|
||||
result.UserReference = User.UserPrincipalName;
|
||||
}
|
||||
}
|
||||
// Could also implement Send-As permissions here
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Class representing an Exchange Distribution Group
|
||||
public class cLiamExchangeDistributionGroup : cLiamDataAreaBase
|
||||
{
|
||||
public new readonly cLiamProviderExchange Provider = null;
|
||||
private readonly cExchangeResultDistributionGroup Group = null;
|
||||
|
||||
public cLiamExchangeDistributionGroup(cLiamProviderExchange Provider, cExchangeResultDistributionGroup Group) :
|
||||
base(Provider)
|
||||
{
|
||||
this.Provider = Provider;
|
||||
this.Group = Group;
|
||||
|
||||
this.DisplayName = Group.DisplayName;
|
||||
this.TechnicalName = Group.EmailAddress;
|
||||
this.UID = $"DistributionGroup|{Group.Alias}";
|
||||
this.Level = 0;
|
||||
this.DataType = eLiamDataAreaTypes.Unknown; // No specific type for Exchange in the enum
|
||||
this.SupportsPermissions = true;
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
||||
{
|
||||
await Task.Delay(0); // Just to make the method async
|
||||
return new List<cLiamDataAreaBase>(); // Groups could potentially have members as children
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamPermissionInfo>> GetPermissionsAsync(bool force = false)
|
||||
{
|
||||
// Implementation would retrieve members of the group
|
||||
await Task.Delay(0);
|
||||
return null; // Placeholder, actual implementation would query Exchange
|
||||
}
|
||||
|
||||
public override async Task<cLiamPermissionResult> GrantPermissionAsync(cLiamUserInfo User, eLiamAccessRoles Role)
|
||||
{
|
||||
var result = new cLiamPermissionResult { Valid = false };
|
||||
|
||||
try
|
||||
{
|
||||
// Add user to the distribution group
|
||||
bool success = await Provider.AddMemberToDistributionGroup(Group.Alias, User.UserPrincipalName);
|
||||
if (success)
|
||||
{
|
||||
result.Valid = true;
|
||||
result.UserReference = User.UserPrincipalName;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
543
LieamExchange/ExchangeManager.cs
Normal file
543
LieamExchange/ExchangeManager.cs
Normal file
@@ -0,0 +1,543 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Security;
|
||||
using System.Reflection;
|
||||
|
||||
using C4IT.Logging;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace C4IT.LIAM
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages connections and operations for a local Microsoft Exchange Server
|
||||
/// using PowerShell Remoting with explicit credentials.
|
||||
/// </summary>
|
||||
public class ExchangeManager : IDisposable
|
||||
{
|
||||
private readonly string _exchangeServerFqdn;
|
||||
private readonly PSCredential _credential;
|
||||
private Runspace _runspace;
|
||||
private bool _isConnected = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the ExchangeManager for connection with explicit credentials.
|
||||
/// </summary>
|
||||
/// <param name="exchangeServerFqdn">Fully qualified domain name of the Exchange Server.</param>
|
||||
/// <param name="userName">Username for the connection (e.g. user@domain.com or DOMAIN\user).</param>
|
||||
/// <param name="password">The user's password as a SecureString.</param>
|
||||
public ExchangeManager(string exchangeServerFqdn, string userName, SecureString password)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
_exchangeServerFqdn = exchangeServerFqdn ?? throw new ArgumentNullException(nameof(exchangeServerFqdn));
|
||||
if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException(nameof(userName));
|
||||
_credential = new PSCredential(userName, password ?? throw new ArgumentNullException(nameof(password)));
|
||||
|
||||
InitializeRunspace();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
// Initializes the PowerShell Runspace for remote connection
|
||||
private void InitializeRunspace()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
// Use HTTPS for Basic Authentication!
|
||||
var connectionUri = new Uri($"https://{_exchangeServerFqdn}/powershell?serializationLevel=Full");
|
||||
|
||||
var connectionInfo = new WSManConnectionInfo(
|
||||
connectionUri,
|
||||
"http://schemas.microsoft.com/powershell/Microsoft.Exchange",
|
||||
_credential
|
||||
)
|
||||
{
|
||||
// Set authentication to Basic (or Negotiate/Kerberos depending on server config)
|
||||
// Basic Auth MUST be enabled on the Exchange Server for the PowerShell vDir!
|
||||
AuthenticationMechanism = AuthenticationMechanism.Basic
|
||||
};
|
||||
|
||||
_runspace = RunspaceFactory.CreateRunspace(connectionInfo);
|
||||
|
||||
LogEntry($"Attempting to connect to {connectionUri} with user '{_credential.UserName}' and method '{connectionInfo.AuthenticationMechanism}'...", LogLevels.Info);
|
||||
_runspace.Open();
|
||||
_isConnected = true;
|
||||
LogEntry("Connection established successfully.", LogLevels.Info);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
LogEntry($"Error opening runspace to Exchange server. Check server name, credentials, and PowerShell remoting settings.", LogLevels.Error);
|
||||
throw new InvalidOperationException($"Error opening runspace to Exchange. Details: {E.Message}", E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
// Private helper method to execute PowerShell commands
|
||||
private IEnumerable<PSObject> ExecuteExchangeCommand(string script, Dictionary<string, object> parameters = null)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
if (_runspace == null || _runspace.RunspaceStateInfo.State != RunspaceState.Opened)
|
||||
{
|
||||
throw new InvalidOperationException("Runspace is not open or initialized.");
|
||||
}
|
||||
|
||||
LogEntry($"Executing script: {script}", LogLevels.Debug);
|
||||
if (parameters != null && parameters.Any())
|
||||
{
|
||||
LogEntry("With parameters: " + string.Join(", ", parameters.Select(kvp => $"{kvp.Key}=***")), LogLevels.Debug);
|
||||
}
|
||||
|
||||
using (PowerShell ps = PowerShell.Create())
|
||||
{
|
||||
ps.Runspace = _runspace;
|
||||
ps.AddScript(script);
|
||||
|
||||
if (parameters != null)
|
||||
{
|
||||
ps.AddParameters(parameters);
|
||||
}
|
||||
|
||||
var results = ps.Invoke();
|
||||
|
||||
// Check for errors (important!)
|
||||
if (ps.Streams.Error.Count > 0)
|
||||
{
|
||||
var errorMessages = ps.Streams.Error.Select(e => e.ToString()).ToList();
|
||||
LogEntry($"Error in PowerShell execution (User: '{_credential.UserName}'):", LogLevels.Error);
|
||||
foreach (var errMsg in errorMessages)
|
||||
{
|
||||
LogEntry($"- {errMsg}", LogLevels.Error);
|
||||
}
|
||||
// Throw exception to surface the error
|
||||
throw new Exception($"Error in Exchange PowerShell command execution. First error message: {errorMessages.FirstOrDefault()}");
|
||||
}
|
||||
|
||||
LogEntry("Script executed successfully.", LogLevels.Debug);
|
||||
return results;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
// *** Methods for managing Shared Mailboxes ***
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Shared Mailbox. The associated AD account is disabled by default.
|
||||
/// </summary>
|
||||
public void CreateSharedMailbox(string name, string alias, string userPrincipalName, string organizationalUnit = null)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
string script = @"New-Mailbox -Name $Name -Alias $Alias -UserPrincipalName $UserPrincipalName -Shared";
|
||||
var parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "Name", name },
|
||||
{ "Alias", alias },
|
||||
{ "UserPrincipalName", userPrincipalName }
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(organizationalUnit))
|
||||
{
|
||||
script += " -OrganizationalUnit $OrganizationalUnit";
|
||||
parameters.Add("OrganizationalUnit", organizationalUnit);
|
||||
}
|
||||
|
||||
ExecuteExchangeCommand(script, parameters);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about all Shared Mailboxes.
|
||||
/// </summary>
|
||||
public IEnumerable<PSObject> GetSharedMailboxes()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
return ExecuteExchangeCommand("Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited");
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds full access permissions for a user to a mailbox.
|
||||
/// </summary>
|
||||
public void AddFullAccessPermission(string mailboxIdentity, string userIdentity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
ExecuteExchangeCommand(
|
||||
"Add-MailboxPermission -Identity $MailboxIdentity -User $UserIdentity -AccessRights FullAccess -InheritanceType All",
|
||||
new Dictionary<string, object> { { "MailboxIdentity", mailboxIdentity }, { "UserIdentity", userIdentity } }
|
||||
);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes full access permissions for a user from a mailbox.
|
||||
/// </summary>
|
||||
public void RemoveFullAccessPermission(string mailboxIdentity, string userIdentity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
ExecuteExchangeCommand(
|
||||
"Remove-MailboxPermission -Identity $MailboxIdentity -User $UserIdentity -AccessRights FullAccess -InheritanceType All -Confirm:$false",
|
||||
new Dictionary<string, object> { { "MailboxIdentity", mailboxIdentity }, { "UserIdentity", userIdentity } }
|
||||
);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds "Send As" permissions for a user to a mailbox.
|
||||
/// </summary>
|
||||
public void AddSendAsPermission(string mailboxIdentity, string userIdentity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
ExecuteExchangeCommand(
|
||||
"Add-ADPermission -Identity $MailboxIdentity -User $UserIdentity -ExtendedRights 'Send As'",
|
||||
new Dictionary<string, object> { { "MailboxIdentity", mailboxIdentity }, { "UserIdentity", userIdentity } }
|
||||
);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
// *** Methods for managing Distribution Groups (Mailing Lists) ***
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Distribution Group (mailing list).
|
||||
/// </summary>
|
||||
public void CreateDistributionGroup(string name, string alias, string organizationalUnit = null, string managedBy = null)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
string script = @"New-DistributionGroup -Name $Name -Alias $Alias -Type Distribution";
|
||||
var parameters = new Dictionary<string, object> { { "Name", name }, { "Alias", alias } };
|
||||
|
||||
if (!string.IsNullOrEmpty(organizationalUnit))
|
||||
{
|
||||
script += " -OrganizationalUnit $OrganizationalUnit";
|
||||
parameters.Add("OrganizationalUnit", organizationalUnit);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(managedBy))
|
||||
{
|
||||
script += " -ManagedBy $ManagedBy";
|
||||
parameters.Add("ManagedBy", managedBy);
|
||||
}
|
||||
|
||||
ExecuteExchangeCommand(script, parameters);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about all Distribution Groups.
|
||||
/// </summary>
|
||||
public IEnumerable<PSObject> GetDistributionGroups()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
return ExecuteExchangeCommand("Get-DistributionGroup -ResultSize Unlimited");
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a member to a Distribution Group.
|
||||
/// </summary>
|
||||
public void AddMemberToDistributionGroup(string groupIdentity, string memberIdentity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
ExecuteExchangeCommand(
|
||||
"Add-DistributionGroupMember -Identity $GroupIdentity -Member $MemberIdentity",
|
||||
new Dictionary<string, object> { { "GroupIdentity", groupIdentity }, { "MemberIdentity", memberIdentity } }
|
||||
);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a member from a Distribution Group.
|
||||
/// </summary>
|
||||
public void RemoveMemberFromDistributionGroup(string groupIdentity, string memberIdentity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
ExecuteExchangeCommand(
|
||||
"Remove-DistributionGroupMember -Identity $GroupIdentity -Member $MemberIdentity -Confirm:$false",
|
||||
new Dictionary<string, object> { { "GroupIdentity", groupIdentity }, { "MemberIdentity", memberIdentity } }
|
||||
);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the members of a Distribution Group.
|
||||
/// </summary>
|
||||
public IEnumerable<PSObject> GetDistributionGroupMembers(string groupIdentity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
return ExecuteExchangeCommand(
|
||||
"Get-DistributionGroupMember -Identity $GroupIdentity",
|
||||
new Dictionary<string, object> { { "GroupIdentity", groupIdentity } }
|
||||
);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the permissions for a mailbox.
|
||||
/// </summary>
|
||||
public IEnumerable<PSObject> GetMailboxPermissions(string mailboxIdentity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
return ExecuteExchangeCommand(
|
||||
"Get-MailboxPermission -Identity $MailboxIdentity | Where-Object {$_.User -ne 'NT AUTHORITY\\SELF' -and $_.IsInherited -eq $false}",
|
||||
new Dictionary<string, object> { { "MailboxIdentity", mailboxIdentity } }
|
||||
);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about a specific mailbox.
|
||||
/// </summary>
|
||||
public PSObject GetMailbox(string identity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
var results = ExecuteExchangeCommand(
|
||||
"Get-Mailbox -Identity $Identity",
|
||||
new Dictionary<string, object> { { "Identity", identity } }
|
||||
);
|
||||
return results.FirstOrDefault();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets information about a specific distribution group.
|
||||
/// </summary>
|
||||
public PSObject GetDistributionGroup(string identity)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
|
||||
try
|
||||
{
|
||||
var results = ExecuteExchangeCommand(
|
||||
"Get-DistributionGroup -Identity $Identity",
|
||||
new Dictionary<string, object> { { "Identity", identity } }
|
||||
);
|
||||
return results.FirstOrDefault();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of IDisposable to clean up the runspace
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && _runspace != null)
|
||||
{
|
||||
if (_runspace.RunspaceStateInfo.State == RunspaceState.Opened)
|
||||
{
|
||||
LogEntry("Closing Runspace...", LogLevels.Debug);
|
||||
_runspace.Close();
|
||||
}
|
||||
_runspace.Dispose();
|
||||
_runspace = null;
|
||||
LogEntry("Runspace closed and resources released.", LogLevels.Debug);
|
||||
}
|
||||
}
|
||||
|
||||
~ExchangeManager()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
LieamExchange/LieamExchange.csproj
Normal file
69
LieamExchange/LieamExchange.csproj
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{C74D679E-5A8B-44BB-938F-CB6E7E1A518E}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>LieamExchange</RootNamespace>
|
||||
<AssemblyName>LieamExchange</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.PowerShell.5.ReferenceAssemblies.1.1.0\lib\net4\System.Management.Automation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="C4IT.LIAM.Exchange.cs" />
|
||||
<Compile Include="ExchangeManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LiamBaseClasses\LiamBaseClasses.csproj">
|
||||
<Project>{3531c9e6-cf6e-458e-b604-4a5a8d1c7ab0}</Project>
|
||||
<Name>LiamBaseClasses</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\LiamHelper\LiamHelper.csproj">
|
||||
<Project>{6b0e73a6-f918-42d5-9525-d59d4d16283d}</Project>
|
||||
<Name>LiamHelper</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
10
LieamExchange/LieamExchange.csproj.vspscc
Normal file
10
LieamExchange/LieamExchange.csproj.vspscc
Normal file
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
||||
}
|
||||
33
LieamExchange/Properties/AssemblyInfo.cs
Normal file
33
LieamExchange/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("LieamExchange")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("LieamExchange")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2025")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("c74d679e-5a8b-44bb-938f-cb6e7e1a518e")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
4
LieamExchange/packages.config
Normal file
4
LieamExchange/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.PowerShell.5.ReferenceAssemblies" version="1.1.0" targetFramework="net472" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user