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)
This commit is contained in:
@@ -1,371 +1,371 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using C4IT.Logging;
|
||||
using C4IT.Matrix42.ServerInfo;
|
||||
using LiamAD;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static LiamAD.ADServiceGroupCreator;
|
||||
using static LiamAD.cActiveDirectoryBase;
|
||||
|
||||
namespace C4IT.LIAM
|
||||
{
|
||||
public static class LiamInitializer
|
||||
{
|
||||
static public cLiamProviderBase CreateInstance(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData)
|
||||
{
|
||||
return new cLiamProviderAD(LiamConfiguration, ProviderData);
|
||||
}
|
||||
}
|
||||
|
||||
public class cLiamProviderAD : cLiamProviderBase
|
||||
{
|
||||
public static Guid adModuleId = new Guid("e820a625-0653-ee11-b886-00155d300101");
|
||||
public readonly cActiveDirectoryBase activeDirectoryBase = new cActiveDirectoryBase();
|
||||
private readonly ADServiceGroupCreator _serviceGroupCreator;
|
||||
|
||||
|
||||
public cLiamProviderAD(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) :
|
||||
base(LiamConfiguration, ProviderData)
|
||||
{
|
||||
_serviceGroupCreator = new ADServiceGroupCreator(this);
|
||||
}
|
||||
|
||||
public List<Tuple<string, string, string, string>> CreateServiceGroups(
|
||||
string serviceName,
|
||||
string description = null,
|
||||
eLiamAccessRoleScopes gruppenbereich = eLiamAccessRoleScopes.Universal,
|
||||
ADGroupType gruppentyp = ADGroupType.Distribution,
|
||||
IEnumerable<string> ownerSidList = null,
|
||||
IEnumerable<string> memberSidList = null)
|
||||
{
|
||||
return _serviceGroupCreator.EnsureServiceGroups(
|
||||
serviceName,
|
||||
description,
|
||||
gruppenbereich,
|
||||
gruppentyp,
|
||||
ownerSidList,
|
||||
memberSidList);
|
||||
}
|
||||
|
||||
public override async Task<bool> LogonAsync()
|
||||
{
|
||||
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId))
|
||||
{
|
||||
LogEntry($"Error: License not valid", LogLevels.Error);
|
||||
return false;
|
||||
}
|
||||
return await LogonAsync(true);
|
||||
}
|
||||
|
||||
public async Task<bool> LogonAsync(bool force = false)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var LI = new cADLogonInfo()
|
||||
{
|
||||
Domain = Domain,
|
||||
User = Credential?.Identification,
|
||||
UserSecret = Credential?.Secret,
|
||||
TargetGroupPath = this.GroupPath
|
||||
};
|
||||
var RetVal = await activeDirectoryBase.LogonAsync(LI);
|
||||
return RetVal;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> getDataAreasAsync(int Depth = -1)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId))
|
||||
{
|
||||
LogEntry($"Error: License not valid", LogLevels.Error);
|
||||
return new List<cLiamDataAreaBase>();
|
||||
}
|
||||
if (!await LogonAsync())
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(this.GroupPath))
|
||||
return null;
|
||||
|
||||
// 1. Alle Roh-Resultate einlesen
|
||||
var rawList = await activeDirectoryBase.RequestSecurityGroupsListAsync(this.GroupFilter);
|
||||
if (rawList == null)
|
||||
return null;
|
||||
|
||||
// 2. Nur die, die dem RegEx entsprechen und deren Wert extrahieren
|
||||
var allResults = rawList
|
||||
.Where(entry =>
|
||||
string.IsNullOrEmpty(this.GroupRegEx)
|
||||
|| Regex.Match(entry.Value.DisplayName, this.GroupRegEx).Success)
|
||||
.Select(entry => (cSecurityGroupResult)entry.Value)
|
||||
.ToList();
|
||||
|
||||
// 3. ManagedBySID-Werte sammeln (ohne Null-/Leereinträge)
|
||||
var managedBySids = new HashSet<string>(
|
||||
allResults
|
||||
.Select(r => r.ManagedBySID)
|
||||
.Where(m => !string.IsNullOrEmpty(m))
|
||||
);
|
||||
|
||||
// 4. Nur die Gruppen, deren ID nicht in managedBySids enthalten ist
|
||||
var filteredResults = allResults
|
||||
.Where(r => !managedBySids.Contains(r.ID))
|
||||
.ToList();
|
||||
|
||||
// 5. In DataArea-Objekte umwandeln
|
||||
var SecurityGroups = new List<cLiamDataAreaBase>();
|
||||
foreach (var secGroup in filteredResults)
|
||||
{
|
||||
SecurityGroups.Add(new cLiamAdGroupAsDataArea(this, secGroup));
|
||||
}
|
||||
|
||||
return SecurityGroups;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> getSecurityGroupsAsync(string groupFilter)
|
||||
{
|
||||
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId))
|
||||
{
|
||||
LogEntry($"Error: License not valid", LogLevels.Error);
|
||||
return new List<cLiamDataAreaBase>();
|
||||
}
|
||||
if (!await LogonAsync())
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(this.GroupPath))
|
||||
return null;
|
||||
|
||||
var SecurityGroups = new List<cLiamDataAreaBase>();
|
||||
|
||||
var SGL = await activeDirectoryBase.RequestSecurityGroupsListAsync(groupFilter);
|
||||
if (SGL == null)
|
||||
return null;
|
||||
|
||||
foreach (var Entry in SGL)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(this.GroupRegEx) && !Regex.Match(Entry.Value.DisplayName, this.GroupRegEx).Success)
|
||||
continue;
|
||||
|
||||
|
||||
var SecurityGroup = new cLiamAdGroup2(this, (cSecurityGroupResult)Entry.Value);
|
||||
SecurityGroups.Add(SecurityGroup);
|
||||
}
|
||||
return SecurityGroups;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public int getDepth(string path)
|
||||
{
|
||||
return getDepth(this.RootPath, path);
|
||||
}
|
||||
public static int getDepth(DirectoryInfo root, DirectoryInfo folder)
|
||||
{
|
||||
var rootDepth = root.FullName.TrimEnd(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar).Length;
|
||||
var folderDepth = folder.FullName.TrimEnd(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar).Length;
|
||||
return folderDepth - rootDepth;
|
||||
|
||||
}
|
||||
public static int getDepth(string root, string folder)
|
||||
{
|
||||
return getDepth(new DirectoryInfo(root), new DirectoryInfo(folder));
|
||||
|
||||
}
|
||||
|
||||
public override string GetLastErrorMessage()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task<cLiamDataAreaBase> LoadDataArea(string UID)
|
||||
{
|
||||
//TODO implement LoadDataArea
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
await Task.Delay(0);
|
||||
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId))
|
||||
{
|
||||
LogEntry($"Error: License not valid", LogLevels.Error);
|
||||
return null;
|
||||
}
|
||||
var res = new cLiamAdGroupAsDataArea(this, new cSecurityGroupResult()
|
||||
{
|
||||
Path = UID
|
||||
});
|
||||
return res;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class cLiamAdGroupAsDataArea : cLiamDataAreaBase
|
||||
{
|
||||
public new readonly cLiamProviderAD Provider = null;
|
||||
public readonly string dn = null;
|
||||
public readonly string scope = null;
|
||||
public readonly string ManagedBySID;
|
||||
|
||||
public override Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public cLiamAdGroupAsDataArea(cLiamProviderAD Provider, cSecurityGroupResult secGroup) : base(Provider)
|
||||
{
|
||||
this.UID = secGroup.ID;
|
||||
this.TechnicalName = secGroup.Path;
|
||||
this.DisplayName = secGroup.DisplayName;
|
||||
this.Description = secGroup.Description;
|
||||
this.Provider = Provider;
|
||||
this.dn = secGroup.Path;
|
||||
this.scope = secGroup.Scope.ToString();
|
||||
this.ManagedBySID = secGroup.ManagedBySID;
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamUserInfo>> GetOwnersAsync()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
return await GetMembersAsync(true);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
private async Task<List<cLiamUserInfo>> GetMembersAsync(bool owners)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var AD = this.Provider?.activeDirectoryBase;
|
||||
if (AD == null)
|
||||
{
|
||||
LogEntry($"Could not get ad class from Provider for folder '{this.TechnicalName}'", LogLevels.Warning);
|
||||
return null;
|
||||
}
|
||||
cADCollectionBase lstMembers;
|
||||
if (owners && !string.IsNullOrEmpty(OwnerRef))
|
||||
lstMembers = await AD.GetMembersAsync(OwnerRef);
|
||||
else if (owners && !string.IsNullOrEmpty(dn))
|
||||
lstMembers = await AD.GetManagedByMembersAsync(this.dn);
|
||||
else
|
||||
lstMembers = null;
|
||||
if (lstMembers == null)
|
||||
{
|
||||
LogEntry($"Could not get owner list for folder '{this.TechnicalName}'", LogLevels.Warning);
|
||||
return null;
|
||||
}
|
||||
|
||||
var RetVal = new List<cLiamUserInfo>(lstMembers.Count);
|
||||
LogEntry($"Owners for folder found: {lstMembers.Count}", LogLevels.Debug);
|
||||
foreach (var MemberEntry in lstMembers.Values)
|
||||
{
|
||||
var User = new cLiamUserInfo()
|
||||
{
|
||||
DisplayName = MemberEntry.DisplayName,
|
||||
UserPrincipalName = (MemberEntry as cADUserResult).UserPrincipalName,
|
||||
SID = MemberEntry.ID
|
||||
};
|
||||
RetVal.Add(User);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
public class cLiamAdGroup2 : cLiamDataAreaBase
|
||||
{
|
||||
public new readonly cLiamProviderAD Provider = null;
|
||||
public readonly string dn = null;
|
||||
public readonly string scope = null;
|
||||
public override Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public cLiamAdGroup2(cLiamProviderAD Provider, cSecurityGroupResult secGroup) : base(Provider)
|
||||
{
|
||||
this.DisplayName = secGroup.DisplayName;
|
||||
this.UID = secGroup.ID;
|
||||
this.TechnicalName = secGroup.DisplayName;
|
||||
this.Provider = Provider;
|
||||
this.dn = secGroup.Path;
|
||||
this.scope = secGroup.Scope.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using C4IT.Logging;
|
||||
using C4IT.Matrix42.ServerInfo;
|
||||
using LiamAD;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
using static LiamAD.ADServiceGroupCreator;
|
||||
using static LiamAD.cActiveDirectoryBase;
|
||||
|
||||
namespace C4IT.LIAM
|
||||
{
|
||||
public static class LiamInitializer
|
||||
{
|
||||
static public cLiamProviderBase CreateInstance(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData)
|
||||
{
|
||||
return new cLiamProviderAD(LiamConfiguration, ProviderData);
|
||||
}
|
||||
}
|
||||
|
||||
public class cLiamProviderAD : cLiamProviderBase
|
||||
{
|
||||
public static Guid adModuleId = new Guid("e820a625-0653-ee11-b886-00155d300101");
|
||||
public readonly cActiveDirectoryBase activeDirectoryBase = new cActiveDirectoryBase();
|
||||
private readonly ADServiceGroupCreator _serviceGroupCreator;
|
||||
|
||||
|
||||
public cLiamProviderAD(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) :
|
||||
base(LiamConfiguration, ProviderData)
|
||||
{
|
||||
_serviceGroupCreator = new ADServiceGroupCreator(this);
|
||||
}
|
||||
|
||||
public List<Tuple<string, string, string, string>> CreateServiceGroups(
|
||||
string serviceName,
|
||||
string description = null,
|
||||
eLiamAccessRoleScopes gruppenbereich = eLiamAccessRoleScopes.Universal,
|
||||
ADGroupType gruppentyp = ADGroupType.Distribution,
|
||||
IEnumerable<string> ownerSidList = null,
|
||||
IEnumerable<string> memberSidList = null)
|
||||
{
|
||||
return _serviceGroupCreator.EnsureServiceGroups(
|
||||
serviceName,
|
||||
description,
|
||||
gruppenbereich,
|
||||
gruppentyp,
|
||||
ownerSidList,
|
||||
memberSidList);
|
||||
}
|
||||
|
||||
public override async Task<bool> LogonAsync()
|
||||
{
|
||||
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId))
|
||||
{
|
||||
LogEntry($"Error: License not valid", LogLevels.Error);
|
||||
return false;
|
||||
}
|
||||
return await LogonAsync(true);
|
||||
}
|
||||
|
||||
public async Task<bool> LogonAsync(bool force = false)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var LI = new cADLogonInfo()
|
||||
{
|
||||
Domain = Domain,
|
||||
User = Credential?.Identification,
|
||||
UserSecret = Credential?.Secret,
|
||||
TargetGroupPath = this.GroupPath
|
||||
};
|
||||
var RetVal = await activeDirectoryBase.LogonAsync(LI);
|
||||
return RetVal;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> getDataAreasAsync(int Depth = -1)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId))
|
||||
{
|
||||
LogEntry($"Error: License not valid", LogLevels.Error);
|
||||
return new List<cLiamDataAreaBase>();
|
||||
}
|
||||
if (!await LogonAsync())
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(this.GroupPath))
|
||||
return null;
|
||||
|
||||
// 1. Alle Roh-Resultate einlesen
|
||||
var rawList = await activeDirectoryBase.RequestSecurityGroupsListAsync(this.GroupFilter);
|
||||
if (rawList == null)
|
||||
return null;
|
||||
|
||||
// 2. Nur die, die dem RegEx entsprechen und deren Wert extrahieren
|
||||
var allResults = rawList
|
||||
.Where(entry =>
|
||||
string.IsNullOrEmpty(this.GroupRegEx)
|
||||
|| Regex.Match(entry.Value.DisplayName, this.GroupRegEx).Success)
|
||||
.Select(entry => (cSecurityGroupResult)entry.Value)
|
||||
.ToList();
|
||||
|
||||
// 3. ManagedBySID-Werte sammeln (ohne Null-/Leereinträge)
|
||||
var managedBySids = new HashSet<string>(
|
||||
allResults
|
||||
.Select(r => r.ManagedBySID)
|
||||
.Where(m => !string.IsNullOrEmpty(m))
|
||||
);
|
||||
|
||||
// 4. Nur die Gruppen, deren ID nicht in managedBySids enthalten ist
|
||||
var filteredResults = allResults
|
||||
.Where(r => !managedBySids.Contains(r.ID))
|
||||
.ToList();
|
||||
|
||||
// 5. In DataArea-Objekte umwandeln
|
||||
var SecurityGroups = new List<cLiamDataAreaBase>();
|
||||
foreach (var secGroup in filteredResults)
|
||||
{
|
||||
SecurityGroups.Add(new cLiamAdGroupAsDataArea(this, secGroup));
|
||||
}
|
||||
|
||||
return SecurityGroups;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override async Task<List<cLiamDataAreaBase>> getSecurityGroupsAsync(string groupFilter)
|
||||
{
|
||||
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId))
|
||||
{
|
||||
LogEntry($"Error: License not valid", LogLevels.Error);
|
||||
return new List<cLiamDataAreaBase>();
|
||||
}
|
||||
if (!await LogonAsync())
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(this.GroupPath))
|
||||
return null;
|
||||
|
||||
var SecurityGroups = new List<cLiamDataAreaBase>();
|
||||
|
||||
var SGL = await activeDirectoryBase.RequestSecurityGroupsListAsync(groupFilter);
|
||||
if (SGL == null)
|
||||
return null;
|
||||
|
||||
foreach (var Entry in SGL)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(this.GroupRegEx) && !Regex.Match(Entry.Value.DisplayName, this.GroupRegEx).Success)
|
||||
continue;
|
||||
|
||||
|
||||
var SecurityGroup = new cLiamAdGroup2(this, (cSecurityGroupResult)Entry.Value);
|
||||
SecurityGroups.Add(SecurityGroup);
|
||||
}
|
||||
return SecurityGroups;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
public int getDepth(string path)
|
||||
{
|
||||
return getDepth(this.RootPath, path);
|
||||
}
|
||||
public static int getDepth(DirectoryInfo root, DirectoryInfo folder)
|
||||
{
|
||||
var rootDepth = root.FullName.TrimEnd(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar).Length;
|
||||
var folderDepth = folder.FullName.TrimEnd(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar).Length;
|
||||
return folderDepth - rootDepth;
|
||||
|
||||
}
|
||||
public static int getDepth(string root, string folder)
|
||||
{
|
||||
return getDepth(new DirectoryInfo(root), new DirectoryInfo(folder));
|
||||
|
||||
}
|
||||
|
||||
public override string GetLastErrorMessage()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task<cLiamDataAreaBase> LoadDataArea(string UID)
|
||||
{
|
||||
//TODO implement LoadDataArea
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
await Task.Delay(0);
|
||||
if (!cC4ITLicenseM42ESM.Instance.IsValid || !cC4ITLicenseM42ESM.Instance.Modules.ContainsKey(adModuleId))
|
||||
{
|
||||
LogEntry($"Error: License not valid", LogLevels.Error);
|
||||
return null;
|
||||
}
|
||||
var res = new cLiamAdGroupAsDataArea(this, new cSecurityGroupResult()
|
||||
{
|
||||
Path = UID
|
||||
});
|
||||
return res;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class cLiamAdGroupAsDataArea : cLiamDataAreaBase
|
||||
{
|
||||
public new readonly cLiamProviderAD Provider = null;
|
||||
public readonly string dn = null;
|
||||
public readonly string scope = null;
|
||||
public readonly string ManagedBySID;
|
||||
|
||||
public override Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public cLiamAdGroupAsDataArea(cLiamProviderAD Provider, cSecurityGroupResult secGroup) : base(Provider)
|
||||
{
|
||||
this.UID = secGroup.ID;
|
||||
this.TechnicalName = secGroup.Path;
|
||||
this.DisplayName = secGroup.DisplayName;
|
||||
this.Description = secGroup.Description;
|
||||
this.Provider = Provider;
|
||||
this.dn = secGroup.Path;
|
||||
this.scope = secGroup.Scope.ToString();
|
||||
this.ManagedBySID = secGroup.ManagedBySID;
|
||||
}
|
||||
|
||||
public override async Task<List<cLiamUserInfo>> GetOwnersAsync()
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
return await GetMembersAsync(true);
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
private async Task<List<cLiamUserInfo>> GetMembersAsync(bool owners)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
var AD = this.Provider?.activeDirectoryBase;
|
||||
if (AD == null)
|
||||
{
|
||||
LogEntry($"Could not get ad class from Provider for folder '{this.TechnicalName}'", LogLevels.Warning);
|
||||
return null;
|
||||
}
|
||||
cADCollectionBase lstMembers;
|
||||
if (owners && !string.IsNullOrEmpty(OwnerRef))
|
||||
lstMembers = await AD.GetMembersAsync(OwnerRef);
|
||||
else if (owners && !string.IsNullOrEmpty(dn))
|
||||
lstMembers = await AD.GetManagedByMembersAsync(this.dn);
|
||||
else
|
||||
lstMembers = null;
|
||||
if (lstMembers == null)
|
||||
{
|
||||
LogEntry($"Could not get owner list for folder '{this.TechnicalName}'", LogLevels.Warning);
|
||||
return null;
|
||||
}
|
||||
|
||||
var RetVal = new List<cLiamUserInfo>(lstMembers.Count);
|
||||
LogEntry($"Owners for folder found: {lstMembers.Count}", LogLevels.Debug);
|
||||
foreach (var MemberEntry in lstMembers.Values)
|
||||
{
|
||||
var User = new cLiamUserInfo()
|
||||
{
|
||||
DisplayName = MemberEntry.DisplayName,
|
||||
UserPrincipalName = (MemberEntry as cADUserResult).UserPrincipalName,
|
||||
SID = MemberEntry.ID
|
||||
};
|
||||
RetVal.Add(User);
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
}
|
||||
}
|
||||
public class cLiamAdGroup2 : cLiamDataAreaBase
|
||||
{
|
||||
public new readonly cLiamProviderAD Provider = null;
|
||||
public readonly string dn = null;
|
||||
public readonly string scope = null;
|
||||
public override Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public cLiamAdGroup2(cLiamProviderAD Provider, cSecurityGroupResult secGroup) : base(Provider)
|
||||
{
|
||||
this.DisplayName = secGroup.DisplayName;
|
||||
this.UID = secGroup.ID;
|
||||
this.TechnicalName = secGroup.DisplayName;
|
||||
this.Provider = Provider;
|
||||
this.dn = secGroup.Path;
|
||||
this.scope = secGroup.Scope.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +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"
|
||||
}
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -1,74 +1,77 @@
|
||||
<?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>{AECA0AD2-8B91-4767-9AFA-E160F6662DBE}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>LIAMActiveDirectory</RootNamespace>
|
||||
<AssemblyName>LiamActiveDirectory</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
<TargetFrameworkProfile />
|
||||
</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.DirectoryServices" />
|
||||
<Reference Include="System.DirectoryServices.AccountManagement" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.6.1\lib\net462\System.ValueTuple.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="cActiveDirectoryBase.cs" />
|
||||
<Compile Include="C4IT.LIAM.AD.cs" />
|
||||
<Compile Include="cADBase.cs" />
|
||||
<Compile Include="cADServiceGroupCreator.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" />
|
||||
<?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>{AECA0AD2-8B91-4767-9AFA-E160F6662DBE}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>LIAMActiveDirectory</RootNamespace>
|
||||
<AssemblyName>LiamActiveDirectory</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
<TargetFrameworkProfile />
|
||||
</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.DirectoryServices" />
|
||||
<Reference Include="System.DirectoryServices.AccountManagement" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.6.1\lib\net462\System.ValueTuple.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="..\SharedAssemblyInfo.cs">
|
||||
<Link>Properties\SharedAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="cActiveDirectoryBase.cs" />
|
||||
<Compile Include="C4IT.LIAM.AD.cs" />
|
||||
<Compile Include="cADBase.cs" />
|
||||
<Compile Include="cADServiceGroupCreator.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>
|
||||
@@ -1,36 +1,19 @@
|
||||
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("LIAMActiveDirectory")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("LIAMActiveDirectory")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2024")]
|
||||
[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("aeca0ad2-8b91-4767-9afa-e160f6662dbe")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
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("LIAM AD Module")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[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("aeca0ad2-8b91-4767-9afa-e160f6662dbe")]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,142 +1,142 @@
|
||||
using C4IT.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LiamAD
|
||||
{
|
||||
public class cADBase
|
||||
{
|
||||
private cADLogonInfo privLogonInfo = null;
|
||||
private int scanningDepth;
|
||||
public PrincipalContext adContext = null;
|
||||
public Exception LastException { get; private set; } = null;
|
||||
public string LastErrorMessage { get; private set; } = null;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ResetError()
|
||||
{
|
||||
LastException = null;
|
||||
LastErrorMessage = null;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetErrorException(string Action, Exception E, LogLevels lev = LogLevels.Error)
|
||||
{
|
||||
LastException = E;
|
||||
LastErrorMessage = Action + ": " + E.Message;
|
||||
cLogManager.LogEntry(Action, lev);
|
||||
}
|
||||
|
||||
|
||||
[DllImport("mpr.dll")]
|
||||
private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);
|
||||
|
||||
[DllImport("mpr.dll")]
|
||||
private static extern int WNetCancelConnection2(string name, int flags,
|
||||
bool force);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class cADLogonInfo
|
||||
{
|
||||
public string Domain;
|
||||
public string User;
|
||||
public string UserSecret;
|
||||
public string TargetGroupPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class NetResource
|
||||
{
|
||||
public ResourceScope Scope;
|
||||
public ResourceType ResourceType;
|
||||
public ResourceDisplaytype DisplayType;
|
||||
public int Usage;
|
||||
public string LocalName;
|
||||
public string RemoteName;
|
||||
public string Comment;
|
||||
public string Provider;
|
||||
}
|
||||
|
||||
public enum ResourceScope : int
|
||||
{
|
||||
Connected = 1,
|
||||
GlobalNetwork,
|
||||
Remembered,
|
||||
Recent,
|
||||
Context
|
||||
};
|
||||
|
||||
public enum ResourceType : int
|
||||
{
|
||||
Any = 0,
|
||||
Disk = 1,
|
||||
Print = 2,
|
||||
Reserved = 8,
|
||||
}
|
||||
|
||||
public enum ResourceDisplaytype : int
|
||||
{
|
||||
Generic = 0x0,
|
||||
Domain = 0x01,
|
||||
Server = 0x02,
|
||||
Share = 0x03,
|
||||
File = 0x04,
|
||||
Group = 0x05,
|
||||
Network = 0x06,
|
||||
Root = 0x07,
|
||||
Shareadmin = 0x08,
|
||||
Directory = 0x09,
|
||||
Tree = 0x0a,
|
||||
Ndscontainer = 0x0b
|
||||
}
|
||||
|
||||
public enum NetError : uint
|
||||
{
|
||||
NERR_Success = 0,
|
||||
NERR_BASE = 2100,
|
||||
NERR_UnknownDevDir = (NERR_BASE + 16),
|
||||
NERR_DuplicateShare = (NERR_BASE + 18),
|
||||
NERR_BufTooSmall = (NERR_BASE + 23),
|
||||
}
|
||||
public enum SHARE_TYPE : uint
|
||||
{
|
||||
STYPE_DISKTREE = 0,
|
||||
STYPE_PRINTQ = 1,
|
||||
STYPE_DEVICE = 2,
|
||||
STYPE_IPC = 3,
|
||||
STYPE_SPECIAL = 0x80000000,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct SHARE_INFO_1
|
||||
{
|
||||
public string shi1_netname;
|
||||
public uint shi1_type;
|
||||
public string shi1_remark;
|
||||
public SHARE_INFO_1(string sharename, uint sharetype, string remark)
|
||||
{
|
||||
this.shi1_netname = sharename;
|
||||
this.shi1_type = sharetype;
|
||||
this.shi1_remark = remark;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return shi1_netname;
|
||||
}
|
||||
}
|
||||
}
|
||||
using C4IT.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace LiamAD
|
||||
{
|
||||
public class cADBase
|
||||
{
|
||||
private cADLogonInfo privLogonInfo = null;
|
||||
private int scanningDepth;
|
||||
public PrincipalContext adContext = null;
|
||||
public Exception LastException { get; private set; } = null;
|
||||
public string LastErrorMessage { get; private set; } = null;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ResetError()
|
||||
{
|
||||
LastException = null;
|
||||
LastErrorMessage = null;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetErrorException(string Action, Exception E, LogLevels lev = LogLevels.Error)
|
||||
{
|
||||
LastException = E;
|
||||
LastErrorMessage = Action + ": " + E.Message;
|
||||
cLogManager.LogEntry(Action, lev);
|
||||
}
|
||||
|
||||
|
||||
[DllImport("mpr.dll")]
|
||||
private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);
|
||||
|
||||
[DllImport("mpr.dll")]
|
||||
private static extern int WNetCancelConnection2(string name, int flags,
|
||||
bool force);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class cADLogonInfo
|
||||
{
|
||||
public string Domain;
|
||||
public string User;
|
||||
public string UserSecret;
|
||||
public string TargetGroupPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class NetResource
|
||||
{
|
||||
public ResourceScope Scope;
|
||||
public ResourceType ResourceType;
|
||||
public ResourceDisplaytype DisplayType;
|
||||
public int Usage;
|
||||
public string LocalName;
|
||||
public string RemoteName;
|
||||
public string Comment;
|
||||
public string Provider;
|
||||
}
|
||||
|
||||
public enum ResourceScope : int
|
||||
{
|
||||
Connected = 1,
|
||||
GlobalNetwork,
|
||||
Remembered,
|
||||
Recent,
|
||||
Context
|
||||
};
|
||||
|
||||
public enum ResourceType : int
|
||||
{
|
||||
Any = 0,
|
||||
Disk = 1,
|
||||
Print = 2,
|
||||
Reserved = 8,
|
||||
}
|
||||
|
||||
public enum ResourceDisplaytype : int
|
||||
{
|
||||
Generic = 0x0,
|
||||
Domain = 0x01,
|
||||
Server = 0x02,
|
||||
Share = 0x03,
|
||||
File = 0x04,
|
||||
Group = 0x05,
|
||||
Network = 0x06,
|
||||
Root = 0x07,
|
||||
Shareadmin = 0x08,
|
||||
Directory = 0x09,
|
||||
Tree = 0x0a,
|
||||
Ndscontainer = 0x0b
|
||||
}
|
||||
|
||||
public enum NetError : uint
|
||||
{
|
||||
NERR_Success = 0,
|
||||
NERR_BASE = 2100,
|
||||
NERR_UnknownDevDir = (NERR_BASE + 16),
|
||||
NERR_DuplicateShare = (NERR_BASE + 18),
|
||||
NERR_BufTooSmall = (NERR_BASE + 23),
|
||||
}
|
||||
public enum SHARE_TYPE : uint
|
||||
{
|
||||
STYPE_DISKTREE = 0,
|
||||
STYPE_PRINTQ = 1,
|
||||
STYPE_DEVICE = 2,
|
||||
STYPE_IPC = 3,
|
||||
STYPE_SPECIAL = 0x80000000,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct SHARE_INFO_1
|
||||
{
|
||||
public string shi1_netname;
|
||||
public uint shi1_type;
|
||||
public string shi1_remark;
|
||||
public SHARE_INFO_1(string sharename, uint sharetype, string remark)
|
||||
{
|
||||
this.shi1_netname = sharename;
|
||||
this.shi1_type = sharetype;
|
||||
this.shi1_remark = remark;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return shi1_netname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,288 +1,288 @@
|
||||
using System;
|
||||
using System.DirectoryServices;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using C4IT.Logging;
|
||||
using C4IT.LIAM;
|
||||
using LiamAD;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
|
||||
namespace LiamAD
|
||||
{
|
||||
/// <summary>
|
||||
/// Helfer für cLiamProviderAD: Erstellt AD Member- und Owner-Gruppen für Services
|
||||
/// nach konfigurierter Namenskonvention und setzt ManagedBy.
|
||||
/// </summary>
|
||||
public class ADServiceGroupCreator
|
||||
{
|
||||
private readonly cLiamProviderAD _provider;
|
||||
private readonly cActiveDirectoryBase _adBase;
|
||||
private readonly string _ldapRoot;
|
||||
private readonly string _user;
|
||||
private readonly string _password;
|
||||
public enum ADGroupType
|
||||
{
|
||||
Security, // Sicherheit
|
||||
Distribution // Verteiler
|
||||
}
|
||||
public ADServiceGroupCreator(cLiamProviderAD provider)
|
||||
{
|
||||
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
|
||||
_adBase = provider.activeDirectoryBase;
|
||||
_ldapRoot = $"LDAP://{provider.Domain}/{provider.GroupPath}";
|
||||
_user = provider.Credential.Identification;
|
||||
_password = new System.Net.NetworkCredential(_user, provider.Credential.Secret).Password;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Erstellt oder findet beide AD-Gruppen (Member & Owner) für einen Service.
|
||||
/// Neu mit: gruppenbereich (Scope) und gruppentyp (für Member-Gruppe).
|
||||
/// Owner-Gruppe ist immer Security.
|
||||
/// </summary>
|
||||
public List<Tuple<string, string, string, string>> EnsureServiceGroups(
|
||||
string serviceName,
|
||||
string description = null,
|
||||
eLiamAccessRoleScopes gruppenbereich = eLiamAccessRoleScopes.Universal,
|
||||
ADGroupType gruppentyp = ADGroupType.Distribution,
|
||||
IEnumerable<string> ownerSidList = null,
|
||||
IEnumerable<string> memberSidList = null)
|
||||
{
|
||||
const int MaxLoop = 50;
|
||||
var result = new List<Tuple<string, string, string, string>>();
|
||||
|
||||
// Konventionen für Member und Owner
|
||||
var ownerConv = _provider.NamingConventions
|
||||
.FirstOrDefault(nc => nc.AccessRole == eLiamAccessRoles.ADOwner);
|
||||
var memberConv = _provider.NamingConventions
|
||||
.FirstOrDefault(nc => nc.AccessRole == eLiamAccessRoles.ADMember);
|
||||
if (ownerConv == null || memberConv == null)
|
||||
throw new InvalidOperationException("Namenskonvention für ADMember oder ADOwner fehlt.");
|
||||
|
||||
// Tags
|
||||
_provider.CustomTags.TryGetValue("ADGroupPrefix", out var prefix);
|
||||
_provider.CustomTags.TryGetValue("ADOwner", out var ownerPostfix);
|
||||
_provider.CustomTags.TryGetValue("ADMember", out var memberPostfix);
|
||||
|
||||
// 1) Owner-Gruppe (immer Security)
|
||||
string ownerName = null;
|
||||
for (int loop = 0; loop <= MaxLoop; loop++)
|
||||
{
|
||||
string loopPart = loop > 0 ? "_" + loop : string.Empty;
|
||||
ownerName = ownerConv.NamingTemplate
|
||||
.Replace("{{ADGroupPrefix}}", prefix ?? string.Empty)
|
||||
.Replace("{{NAME}}", serviceName)
|
||||
.Replace("{{_LOOP}}", loopPart)
|
||||
.Replace("{{GROUPTYPEPOSTFIX}}", ownerPostfix);
|
||||
if (!GroupExists(ownerName)) break;
|
||||
if (loop == MaxLoop) throw new InvalidOperationException($"Kein eindeutiger Owner-Name für '{serviceName}' nach {MaxLoop} Versuchen.");
|
||||
}
|
||||
EnsureGroup(ownerName, ownerConv, description, managedByDn: null, gruppenbereich, ADGroupType.Security);
|
||||
AddMembersBySid(ownerName, ownerSidList); // NEU: SIDs als Owner hinzufügen
|
||||
var ownerDn = GetDistinguishedName(ownerName);
|
||||
var ownerSid = GetSid(ownerName);
|
||||
result.Add(Tuple.Create(eLiamAccessRoles.ADOwner.ToString(), ownerSid, ownerName, ownerDn));
|
||||
|
||||
|
||||
// 2) Member-Gruppe (Gruppentyp nach Parameter)
|
||||
string memberName = null;
|
||||
for (int loop = 0; loop <= MaxLoop; loop++)
|
||||
{
|
||||
string loopPart = loop > 0 ? "_" + loop : string.Empty;
|
||||
memberName = memberConv.NamingTemplate
|
||||
.Replace("{{ADGroupPrefix}}", prefix ?? string.Empty)
|
||||
.Replace("{{NAME}}", serviceName)
|
||||
.Replace("{{_LOOP}}", loopPart)
|
||||
.Replace("{{GROUPTYPEPOSTFIX}}", memberPostfix);
|
||||
if (!GroupExists(memberName)) break;
|
||||
if (loop == MaxLoop) throw new InvalidOperationException($"Kein eindeutiger Member-Name für '{serviceName}' nach {MaxLoop} Versuchen.");
|
||||
}
|
||||
EnsureGroup(memberName, memberConv, description, managedByDn: ownerDn, gruppenbereich, gruppentyp);
|
||||
AddMembersBySid(memberName, memberSidList); // NEU: SIDs als Member hinzufügen
|
||||
var memberDn = GetDistinguishedName(memberName);
|
||||
var memberSid = GetSid(memberName);
|
||||
result.Add(Tuple.Create(eLiamAccessRoles.ADMember.ToString(), memberSid, memberName, memberDn));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fügt einer bestehenden Gruppe per SID die entsprechenden AD-Objekte hinzu.
|
||||
/// </summary>
|
||||
private void AddMembersBySid(string groupName, IEnumerable<string> sidList)
|
||||
{
|
||||
if (sidList == null) return;
|
||||
|
||||
// Basis für die Suche: komplette Domäne, nicht nur der OU-Pfad
|
||||
string domainRoot = $"LDAP://{_provider.Domain}";
|
||||
using (var root = new DirectoryEntry(domainRoot, _user, _password, AuthenticationTypes.Secure))
|
||||
using (var grpSearch = new DirectorySearcher(root))
|
||||
{
|
||||
grpSearch.Filter = $"(&(objectCategory=group)(sAMAccountName={groupName}))";
|
||||
var grpRes = grpSearch.FindOne();
|
||||
if (grpRes == null) return;
|
||||
|
||||
var grpEntry = grpRes.GetDirectoryEntry();
|
||||
foreach (var sidStr in sidList)
|
||||
{
|
||||
// Leere oder null überspringen
|
||||
if (string.IsNullOrWhiteSpace(sidStr))
|
||||
continue;
|
||||
|
||||
SecurityIdentifier sid;
|
||||
try
|
||||
{
|
||||
sid = new SecurityIdentifier(sidStr);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ungültige SID-String-Darstellung überspringen
|
||||
continue;
|
||||
}
|
||||
|
||||
// In LDAP-Filter-Notation umwandeln
|
||||
var bytes = new byte[sid.BinaryLength];
|
||||
sid.GetBinaryForm(bytes, 0);
|
||||
var sb = new StringBuilder();
|
||||
foreach (var b in bytes)
|
||||
sb.AppendFormat("\\{0:X2}", b);
|
||||
string octetSid = sb.ToString();
|
||||
|
||||
// Suche nach dem Objekt in der Domäne
|
||||
using (var usrSearch = new DirectorySearcher(root))
|
||||
{
|
||||
usrSearch.Filter = $"(objectSid={octetSid})";
|
||||
var usrRes = usrSearch.FindOne();
|
||||
if (usrRes == null)
|
||||
continue;
|
||||
|
||||
var userDn = usrRes.Properties["distinguishedName"][0].ToString();
|
||||
// Doppelteinträge vermeiden
|
||||
if (!grpEntry.Properties["member"].Contains(userDn))
|
||||
grpEntry.Properties["member"].Add(userDn);
|
||||
}
|
||||
}
|
||||
|
||||
grpEntry.CommitChanges();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wandelt eine SID (String-Form) in das für LDAP nötige Oktet-String-Format um.
|
||||
/// </summary>
|
||||
private string SidStringToLdapFilter(string sidString)
|
||||
{
|
||||
var sid = new SecurityIdentifier(sidString);
|
||||
var bytes = new byte[sid.BinaryLength];
|
||||
sid.GetBinaryForm(bytes, 0);
|
||||
var sb = new StringBuilder();
|
||||
foreach (var b in bytes)
|
||||
sb.AppendFormat("\\{0:X2}", b);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
private string GetSid(string name)
|
||||
{
|
||||
using (var root = new DirectoryEntry(_ldapRoot, _user, _password, AuthenticationTypes.Secure))
|
||||
using (var ds = new DirectorySearcher(root))
|
||||
{
|
||||
ds.Filter = $"(&(objectCategory=group)(sAMAccountName={name}))";
|
||||
var r = ds.FindOne();
|
||||
if (r == null) return null;
|
||||
var de = r.GetDirectoryEntry();
|
||||
var sidBytes = (byte[])de.Properties["objectSid"][0];
|
||||
return new SecurityIdentifier(sidBytes, 0).Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string FormatName(cLiamNamingConvention conv, string serviceName, System.Collections.Generic.IDictionary<string, string> tags)
|
||||
{
|
||||
string tmpl = conv.NamingTemplate.Replace("{{NAME}}", serviceName);
|
||||
foreach (var kv in tags)
|
||||
tmpl = tmpl.Replace("{{" + kv.Key + "}}", kv.Value);
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stellt sicher, dass die Gruppe existiert – neu mit Scope & Type.
|
||||
/// </summary>
|
||||
private void EnsureGroup(
|
||||
string groupName,
|
||||
cLiamNamingConvention conv,
|
||||
string description,
|
||||
string managedByDn,
|
||||
eLiamAccessRoleScopes groupScope,
|
||||
ADGroupType groupType)
|
||||
{
|
||||
if (!GroupExists(groupName))
|
||||
{
|
||||
using (var root = new DirectoryEntry(_ldapRoot, _user, _password, AuthenticationTypes.Secure))
|
||||
{
|
||||
var grp = root.Children.Add("CN=" + groupName, "group");
|
||||
grp.Properties["sAMAccountName"].Value = groupName;
|
||||
grp.Properties["displayName"].Value = groupName;
|
||||
// Hier: Security-Bit (0x80000000) nur, wenn Security, sonst 0
|
||||
int typeBit = (groupType == ADGroupType.Security)
|
||||
? unchecked((int)0x80000000)
|
||||
: 0;
|
||||
// Scope-Bit aus Param
|
||||
grp.Properties["groupType"].Value = unchecked(typeBit | GetScopeBit(groupScope));
|
||||
|
||||
if (!string.IsNullOrEmpty(description))
|
||||
grp.Properties["description"].Value = description;
|
||||
if (managedByDn != null)
|
||||
grp.Properties["managedBy"].Value = managedByDn;
|
||||
grp.CommitChanges();
|
||||
}
|
||||
WaitReplication(groupName, TimeSpan.FromMinutes(2));
|
||||
}
|
||||
}
|
||||
|
||||
private bool GroupExists(string name)
|
||||
{
|
||||
return _adBase.directoryEntry.Children.Cast<DirectoryEntry>()
|
||||
.Any(c => string.Equals(
|
||||
c.Properties["sAMAccountName"]?.Value?.ToString(), name, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private void WaitReplication(string groupName, TimeSpan timeout)
|
||||
{
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
while (sw.Elapsed < timeout)
|
||||
{
|
||||
if (GroupExists(groupName))
|
||||
return;
|
||||
Thread.Sleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetDistinguishedName(string name)
|
||||
{
|
||||
using (var root = new DirectoryEntry(_ldapRoot, _user, _password, AuthenticationTypes.Secure))
|
||||
using (var ds = new DirectorySearcher(root))
|
||||
{
|
||||
ds.Filter = "(&(objectClass=group)(sAMAccountName=" + name + "))";
|
||||
var res = ds.FindOne();
|
||||
return res?.Properties["distinguishedName"]?[0]?.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private int GetScopeBit(eLiamAccessRoleScopes scope)
|
||||
{
|
||||
switch (scope)
|
||||
{
|
||||
case eLiamAccessRoleScopes.Universal:
|
||||
return 0x8;
|
||||
case eLiamAccessRoleScopes.Global:
|
||||
return 0x2;
|
||||
case eLiamAccessRoleScopes.DomainLocal:
|
||||
return 0x4;
|
||||
default:
|
||||
return 0x8;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.DirectoryServices;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using C4IT.Logging;
|
||||
using C4IT.LIAM;
|
||||
using LiamAD;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
|
||||
namespace LiamAD
|
||||
{
|
||||
/// <summary>
|
||||
/// Helfer für cLiamProviderAD: Erstellt AD Member- und Owner-Gruppen für Services
|
||||
/// nach konfigurierter Namenskonvention und setzt ManagedBy.
|
||||
/// </summary>
|
||||
public class ADServiceGroupCreator
|
||||
{
|
||||
private readonly cLiamProviderAD _provider;
|
||||
private readonly cActiveDirectoryBase _adBase;
|
||||
private readonly string _ldapRoot;
|
||||
private readonly string _user;
|
||||
private readonly string _password;
|
||||
public enum ADGroupType
|
||||
{
|
||||
Security, // Sicherheit
|
||||
Distribution // Verteiler
|
||||
}
|
||||
public ADServiceGroupCreator(cLiamProviderAD provider)
|
||||
{
|
||||
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
|
||||
_adBase = provider.activeDirectoryBase;
|
||||
_ldapRoot = $"LDAP://{provider.Domain}/{provider.GroupPath}";
|
||||
_user = provider.Credential.Identification;
|
||||
_password = new System.Net.NetworkCredential(_user, provider.Credential.Secret).Password;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Erstellt oder findet beide AD-Gruppen (Member & Owner) für einen Service.
|
||||
/// Neu mit: gruppenbereich (Scope) und gruppentyp (für Member-Gruppe).
|
||||
/// Owner-Gruppe ist immer Security.
|
||||
/// </summary>
|
||||
public List<Tuple<string, string, string, string>> EnsureServiceGroups(
|
||||
string serviceName,
|
||||
string description = null,
|
||||
eLiamAccessRoleScopes gruppenbereich = eLiamAccessRoleScopes.Universal,
|
||||
ADGroupType gruppentyp = ADGroupType.Distribution,
|
||||
IEnumerable<string> ownerSidList = null,
|
||||
IEnumerable<string> memberSidList = null)
|
||||
{
|
||||
const int MaxLoop = 50;
|
||||
var result = new List<Tuple<string, string, string, string>>();
|
||||
|
||||
// Konventionen für Member und Owner
|
||||
var ownerConv = _provider.NamingConventions
|
||||
.FirstOrDefault(nc => nc.AccessRole == eLiamAccessRoles.ADOwner);
|
||||
var memberConv = _provider.NamingConventions
|
||||
.FirstOrDefault(nc => nc.AccessRole == eLiamAccessRoles.ADMember);
|
||||
if (ownerConv == null || memberConv == null)
|
||||
throw new InvalidOperationException("Namenskonvention für ADMember oder ADOwner fehlt.");
|
||||
|
||||
// Tags
|
||||
_provider.CustomTags.TryGetValue("ADGroupPrefix", out var prefix);
|
||||
_provider.CustomTags.TryGetValue("ADOwner", out var ownerPostfix);
|
||||
_provider.CustomTags.TryGetValue("ADMember", out var memberPostfix);
|
||||
|
||||
// 1) Owner-Gruppe (immer Security)
|
||||
string ownerName = null;
|
||||
for (int loop = 0; loop <= MaxLoop; loop++)
|
||||
{
|
||||
string loopPart = loop > 0 ? "_" + loop : string.Empty;
|
||||
ownerName = ownerConv.NamingTemplate
|
||||
.Replace("{{ADGroupPrefix}}", prefix ?? string.Empty)
|
||||
.Replace("{{NAME}}", serviceName)
|
||||
.Replace("{{_LOOP}}", loopPart)
|
||||
.Replace("{{GROUPTYPEPOSTFIX}}", ownerPostfix);
|
||||
if (!GroupExists(ownerName)) break;
|
||||
if (loop == MaxLoop) throw new InvalidOperationException($"Kein eindeutiger Owner-Name für '{serviceName}' nach {MaxLoop} Versuchen.");
|
||||
}
|
||||
EnsureGroup(ownerName, ownerConv, description, managedByDn: null, gruppenbereich, ADGroupType.Security);
|
||||
AddMembersBySid(ownerName, ownerSidList); // NEU: SIDs als Owner hinzufügen
|
||||
var ownerDn = GetDistinguishedName(ownerName);
|
||||
var ownerSid = GetSid(ownerName);
|
||||
result.Add(Tuple.Create(eLiamAccessRoles.ADOwner.ToString(), ownerSid, ownerName, ownerDn));
|
||||
|
||||
|
||||
// 2) Member-Gruppe (Gruppentyp nach Parameter)
|
||||
string memberName = null;
|
||||
for (int loop = 0; loop <= MaxLoop; loop++)
|
||||
{
|
||||
string loopPart = loop > 0 ? "_" + loop : string.Empty;
|
||||
memberName = memberConv.NamingTemplate
|
||||
.Replace("{{ADGroupPrefix}}", prefix ?? string.Empty)
|
||||
.Replace("{{NAME}}", serviceName)
|
||||
.Replace("{{_LOOP}}", loopPart)
|
||||
.Replace("{{GROUPTYPEPOSTFIX}}", memberPostfix);
|
||||
if (!GroupExists(memberName)) break;
|
||||
if (loop == MaxLoop) throw new InvalidOperationException($"Kein eindeutiger Member-Name für '{serviceName}' nach {MaxLoop} Versuchen.");
|
||||
}
|
||||
EnsureGroup(memberName, memberConv, description, managedByDn: ownerDn, gruppenbereich, gruppentyp);
|
||||
AddMembersBySid(memberName, memberSidList); // NEU: SIDs als Member hinzufügen
|
||||
var memberDn = GetDistinguishedName(memberName);
|
||||
var memberSid = GetSid(memberName);
|
||||
result.Add(Tuple.Create(eLiamAccessRoles.ADMember.ToString(), memberSid, memberName, memberDn));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fügt einer bestehenden Gruppe per SID die entsprechenden AD-Objekte hinzu.
|
||||
/// </summary>
|
||||
private void AddMembersBySid(string groupName, IEnumerable<string> sidList)
|
||||
{
|
||||
if (sidList == null) return;
|
||||
|
||||
// Basis für die Suche: komplette Domäne, nicht nur der OU-Pfad
|
||||
string domainRoot = $"LDAP://{_provider.Domain}";
|
||||
using (var root = new DirectoryEntry(domainRoot, _user, _password, AuthenticationTypes.Secure))
|
||||
using (var grpSearch = new DirectorySearcher(root))
|
||||
{
|
||||
grpSearch.Filter = $"(&(objectCategory=group)(sAMAccountName={groupName}))";
|
||||
var grpRes = grpSearch.FindOne();
|
||||
if (grpRes == null) return;
|
||||
|
||||
var grpEntry = grpRes.GetDirectoryEntry();
|
||||
foreach (var sidStr in sidList)
|
||||
{
|
||||
// Leere oder null überspringen
|
||||
if (string.IsNullOrWhiteSpace(sidStr))
|
||||
continue;
|
||||
|
||||
SecurityIdentifier sid;
|
||||
try
|
||||
{
|
||||
sid = new SecurityIdentifier(sidStr);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ungültige SID-String-Darstellung überspringen
|
||||
continue;
|
||||
}
|
||||
|
||||
// In LDAP-Filter-Notation umwandeln
|
||||
var bytes = new byte[sid.BinaryLength];
|
||||
sid.GetBinaryForm(bytes, 0);
|
||||
var sb = new StringBuilder();
|
||||
foreach (var b in bytes)
|
||||
sb.AppendFormat("\\{0:X2}", b);
|
||||
string octetSid = sb.ToString();
|
||||
|
||||
// Suche nach dem Objekt in der Domäne
|
||||
using (var usrSearch = new DirectorySearcher(root))
|
||||
{
|
||||
usrSearch.Filter = $"(objectSid={octetSid})";
|
||||
var usrRes = usrSearch.FindOne();
|
||||
if (usrRes == null)
|
||||
continue;
|
||||
|
||||
var userDn = usrRes.Properties["distinguishedName"][0].ToString();
|
||||
// Doppelteinträge vermeiden
|
||||
if (!grpEntry.Properties["member"].Contains(userDn))
|
||||
grpEntry.Properties["member"].Add(userDn);
|
||||
}
|
||||
}
|
||||
|
||||
grpEntry.CommitChanges();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wandelt eine SID (String-Form) in das für LDAP nötige Oktet-String-Format um.
|
||||
/// </summary>
|
||||
private string SidStringToLdapFilter(string sidString)
|
||||
{
|
||||
var sid = new SecurityIdentifier(sidString);
|
||||
var bytes = new byte[sid.BinaryLength];
|
||||
sid.GetBinaryForm(bytes, 0);
|
||||
var sb = new StringBuilder();
|
||||
foreach (var b in bytes)
|
||||
sb.AppendFormat("\\{0:X2}", b);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
private string GetSid(string name)
|
||||
{
|
||||
using (var root = new DirectoryEntry(_ldapRoot, _user, _password, AuthenticationTypes.Secure))
|
||||
using (var ds = new DirectorySearcher(root))
|
||||
{
|
||||
ds.Filter = $"(&(objectCategory=group)(sAMAccountName={name}))";
|
||||
var r = ds.FindOne();
|
||||
if (r == null) return null;
|
||||
var de = r.GetDirectoryEntry();
|
||||
var sidBytes = (byte[])de.Properties["objectSid"][0];
|
||||
return new SecurityIdentifier(sidBytes, 0).Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string FormatName(cLiamNamingConvention conv, string serviceName, System.Collections.Generic.IDictionary<string, string> tags)
|
||||
{
|
||||
string tmpl = conv.NamingTemplate.Replace("{{NAME}}", serviceName);
|
||||
foreach (var kv in tags)
|
||||
tmpl = tmpl.Replace("{{" + kv.Key + "}}", kv.Value);
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stellt sicher, dass die Gruppe existiert – neu mit Scope & Type.
|
||||
/// </summary>
|
||||
private void EnsureGroup(
|
||||
string groupName,
|
||||
cLiamNamingConvention conv,
|
||||
string description,
|
||||
string managedByDn,
|
||||
eLiamAccessRoleScopes groupScope,
|
||||
ADGroupType groupType)
|
||||
{
|
||||
if (!GroupExists(groupName))
|
||||
{
|
||||
using (var root = new DirectoryEntry(_ldapRoot, _user, _password, AuthenticationTypes.Secure))
|
||||
{
|
||||
var grp = root.Children.Add("CN=" + groupName, "group");
|
||||
grp.Properties["sAMAccountName"].Value = groupName;
|
||||
grp.Properties["displayName"].Value = groupName;
|
||||
// Hier: Security-Bit (0x80000000) nur, wenn Security, sonst 0
|
||||
int typeBit = (groupType == ADGroupType.Security)
|
||||
? unchecked((int)0x80000000)
|
||||
: 0;
|
||||
// Scope-Bit aus Param
|
||||
grp.Properties["groupType"].Value = unchecked(typeBit | GetScopeBit(groupScope));
|
||||
|
||||
if (!string.IsNullOrEmpty(description))
|
||||
grp.Properties["description"].Value = description;
|
||||
if (managedByDn != null)
|
||||
grp.Properties["managedBy"].Value = managedByDn;
|
||||
grp.CommitChanges();
|
||||
}
|
||||
WaitReplication(groupName, TimeSpan.FromMinutes(2));
|
||||
}
|
||||
}
|
||||
|
||||
private bool GroupExists(string name)
|
||||
{
|
||||
return _adBase.directoryEntry.Children.Cast<DirectoryEntry>()
|
||||
.Any(c => string.Equals(
|
||||
c.Properties["sAMAccountName"]?.Value?.ToString(), name, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private void WaitReplication(string groupName, TimeSpan timeout)
|
||||
{
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
while (sw.Elapsed < timeout)
|
||||
{
|
||||
if (GroupExists(groupName))
|
||||
return;
|
||||
Thread.Sleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetDistinguishedName(string name)
|
||||
{
|
||||
using (var root = new DirectoryEntry(_ldapRoot, _user, _password, AuthenticationTypes.Secure))
|
||||
using (var ds = new DirectorySearcher(root))
|
||||
{
|
||||
ds.Filter = "(&(objectClass=group)(sAMAccountName=" + name + "))";
|
||||
var res = ds.FindOne();
|
||||
return res?.Properties["distinguishedName"]?[0]?.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private int GetScopeBit(eLiamAccessRoleScopes scope)
|
||||
{
|
||||
switch (scope)
|
||||
{
|
||||
case eLiamAccessRoleScopes.Universal:
|
||||
return 0x8;
|
||||
case eLiamAccessRoleScopes.Global:
|
||||
return 0x2;
|
||||
case eLiamAccessRoleScopes.DomainLocal:
|
||||
return 0x4;
|
||||
default:
|
||||
return 0x8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
|
||||
|
||||
@@ -1,4 +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")]
|
||||
// <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.
@@ -1,14 +1,28 @@
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamBaseClasses.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamHelper.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\Newtonsoft.Json.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamBaseClasses.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamHelper.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.csproj.AssemblyReference.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.csproj.CoreCompileInputs.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActi.8091FDFC.Up2Date
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\System.ValueTuple.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\System.ValueTuple.xml
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamBaseClasses.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamHelper.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\Newtonsoft.Json.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamBaseClasses.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\LiamHelper.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.csproj.AssemblyReference.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.csproj.CoreCompileInputs.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActi.8091FDFC.Up2Date
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\System.ValueTuple.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Debug\System.ValueTuple.xml
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamBaseClasses.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamHelper.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\System.ValueTuple.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\Newtonsoft.Json.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamBaseClasses.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\LiamHelper.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Debug\System.ValueTuple.xml
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.csproj.AssemblyReference.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.csproj.CoreCompileInputs.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActi.8091FDFC.Up2Date
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Debug\LiamActiveDirectory.pdb
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
88ca960765b758a5c4edcddedf6dc811f2a49d840cd7ade015d7644911a99c77
|
||||
0f439131d442d0ee4d6473d1fe79783624433c39a44374a60e15e079e468a4be
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
|
||||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
|
||||
|
||||
Binary file not shown.
@@ -1,14 +1,28 @@
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LIAMActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LIAMActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LiamBaseClasses.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LiamHelper.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\Newtonsoft.Json.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LiamBaseClasses.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LiamHelper.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LIAMActiveDirectory.csproj.AssemblyReference.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LIAMActiveDirectory.csproj.CoreCompileInputs.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LIAMActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LIAMActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LiamActi.8091FDFC.Up2Date
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\System.ValueTuple.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\System.ValueTuple.xml
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LIAMActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LIAMActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LiamBaseClasses.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LiamHelper.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\Newtonsoft.Json.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LiamBaseClasses.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\LiamHelper.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LIAMActiveDirectory.csproj.AssemblyReference.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LIAMActiveDirectory.csproj.CoreCompileInputs.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LIAMActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LIAMActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\obj\Release\LiamActi.8091FDFC.Up2Date
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\System.ValueTuple.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service\LIAMActiveDirectory\bin\Release\System.ValueTuple.xml
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActiveDirectory.csproj.AssemblyReference.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActiveDirectory.csproj.CoreCompileInputs.cache
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamActiveDirectory.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamActiveDirectory.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamBaseClasses.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamHelper.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\System.ValueTuple.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\Newtonsoft.Json.dll
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamBaseClasses.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\LiamHelper.pdb
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\bin\Release\System.ValueTuple.xml
|
||||
C:\Workspace\C4IT DEV LIAM WEB Service_git\LIAMActiveDirectory\obj\Release\LiamActi.8091FDFC.Up2Date
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
ab9bb136583040c5ab0b8fc2b80edba3f154caa1532f30973b39973f0def47e6
|
||||
e6f9f5153aa55a3a910f7c5ef0287e4500a3f354c3a1c3198c24d7eea04e0de2
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="System.ValueTuple" version="4.6.1" targetFramework="net462" />
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="System.ValueTuple" version="4.6.1" targetFramework="net462" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user