initial
This commit is contained in:
371
LIAMActiveDirectory/C4IT.LIAM.AD.cs
Normal file
371
LIAMActiveDirectory/C4IT.LIAM.AD.cs
Normal file
@@ -0,0 +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();
|
||||
}
|
||||
}
|
||||
}
|
||||
10
LIAMActiveDirectory/LIAMActiveDirectory.csproj.vspscc
Normal file
10
LIAMActiveDirectory/LIAMActiveDirectory.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"
|
||||
}
|
||||
74
LIAMActiveDirectory/LiamActiveDirectory.csproj
Normal file
74
LIAMActiveDirectory/LiamActiveDirectory.csproj
Normal file
@@ -0,0 +1,74 @@
|
||||
<?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" />
|
||||
</Project>
|
||||
36
LIAMActiveDirectory/Properties/AssemblyInfo.cs
Normal file
36
LIAMActiveDirectory/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
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")]
|
||||
BIN
LIAMActiveDirectory/bin/Debug/LiamActiveDirectory.dll
Normal file
BIN
LIAMActiveDirectory/bin/Debug/LiamActiveDirectory.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Debug/LiamActiveDirectory.pdb
Normal file
BIN
LIAMActiveDirectory/bin/Debug/LiamActiveDirectory.pdb
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Debug/LiamBaseClasses.dll
Normal file
BIN
LIAMActiveDirectory/bin/Debug/LiamBaseClasses.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Debug/LiamBaseClasses.pdb
Normal file
BIN
LIAMActiveDirectory/bin/Debug/LiamBaseClasses.pdb
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Debug/LiamHelper.dll
Normal file
BIN
LIAMActiveDirectory/bin/Debug/LiamHelper.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Debug/LiamHelper.pdb
Normal file
BIN
LIAMActiveDirectory/bin/Debug/LiamHelper.pdb
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Debug/Newtonsoft.Json.dll
Normal file
BIN
LIAMActiveDirectory/bin/Debug/Newtonsoft.Json.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Debug/System.ValueTuple.dll
Normal file
BIN
LIAMActiveDirectory/bin/Debug/System.ValueTuple.dll
Normal file
Binary file not shown.
1299
LIAMActiveDirectory/bin/Debug/System.ValueTuple.xml
Normal file
1299
LIAMActiveDirectory/bin/Debug/System.ValueTuple.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
LIAMActiveDirectory/bin/Release/LiamActiveDirectory.dll
Normal file
BIN
LIAMActiveDirectory/bin/Release/LiamActiveDirectory.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Release/LiamActiveDirectory.pdb
Normal file
BIN
LIAMActiveDirectory/bin/Release/LiamActiveDirectory.pdb
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Release/LiamBaseClasses.dll
Normal file
BIN
LIAMActiveDirectory/bin/Release/LiamBaseClasses.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Release/LiamBaseClasses.pdb
Normal file
BIN
LIAMActiveDirectory/bin/Release/LiamBaseClasses.pdb
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Release/LiamHelper.dll
Normal file
BIN
LIAMActiveDirectory/bin/Release/LiamHelper.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Release/LiamHelper.pdb
Normal file
BIN
LIAMActiveDirectory/bin/Release/LiamHelper.pdb
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Release/Newtonsoft.Json.dll
Normal file
BIN
LIAMActiveDirectory/bin/Release/Newtonsoft.Json.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/bin/Release/System.ValueTuple.dll
Normal file
BIN
LIAMActiveDirectory/bin/Release/System.ValueTuple.dll
Normal file
Binary file not shown.
1299
LIAMActiveDirectory/bin/Release/System.ValueTuple.xml
Normal file
1299
LIAMActiveDirectory/bin/Release/System.ValueTuple.xml
Normal file
File diff suppressed because it is too large
Load Diff
142
LIAMActiveDirectory/cADBase.cs
Normal file
142
LIAMActiveDirectory/cADBase.cs
Normal file
@@ -0,0 +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;
|
||||
}
|
||||
}
|
||||
}
|
||||
288
LIAMActiveDirectory/cADServiceGroupCreator.cs
Normal file
288
LIAMActiveDirectory/cADServiceGroupCreator.cs
Normal file
@@ -0,0 +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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
516
LIAMActiveDirectory/cActiveDirectoryBase.cs
Normal file
516
LIAMActiveDirectory/cActiveDirectoryBase.cs
Normal file
@@ -0,0 +1,516 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.DirectoryServices;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using C4IT.Logging;
|
||||
using static C4IT.Logging.cLogManager;
|
||||
|
||||
namespace LiamAD
|
||||
{
|
||||
public class cActiveDirectoryBase
|
||||
{
|
||||
private cADLogonInfo privLogonInfo = null;
|
||||
public PrincipalContext adContext = null;
|
||||
public DirectoryEntry directoryEntry = 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);
|
||||
}
|
||||
|
||||
private async Task<bool> privLogonAsync(cADLogonInfo LogonInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
//TODO: remove dummy delay?
|
||||
await Task.Delay(0);
|
||||
ResetError();
|
||||
adContext = new PrincipalContext(ContextType.Domain, LogonInfo.Domain, LogonInfo.User, new NetworkCredential("", LogonInfo.UserSecret).Password);
|
||||
var ldapPath = $"LDAP://{LogonInfo.Domain}/{LogonInfo.TargetGroupPath}";
|
||||
directoryEntry = new DirectoryEntry
|
||||
{
|
||||
Path = ldapPath,
|
||||
Username = LogonInfo.User,
|
||||
Password = new NetworkCredential(LogonInfo.User, LogonInfo.UserSecret).Password,
|
||||
AuthenticationType = AuthenticationTypes.Secure | AuthenticationTypes.Sealing
|
||||
};
|
||||
return adContext != null;
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
SetErrorException("exception error while ad login", E, LogLevels.Debug);
|
||||
cLogManager.LogException(E, LogLevels.Debug);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<bool> privRelogon()
|
||||
{
|
||||
if (privLogonInfo == null)
|
||||
return false;
|
||||
var RetVal = await privLogonAsync(privLogonInfo);
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
public async Task<bool> LogonAsync(cADLogonInfo LogonInfo)
|
||||
{
|
||||
var RetVal = await privLogonAsync(LogonInfo);
|
||||
if (RetVal == true)
|
||||
privLogonInfo = LogonInfo;
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
internal AuthorizationRuleCollection GetAccessControlList(string path)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
DirectoryInfo dADir = new DirectoryInfo(path);
|
||||
var dAACL = dADir.GetAccessControl();
|
||||
return dAACL.GetAccessRules(true, false, typeof(System.Security.Principal.SecurityIdentifier));
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal string resolveSid(string sid)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
return new System.Security.Principal.SecurityIdentifier(sid).Translate(typeof(System.Security.Principal.NTAccount)).ToString();
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<cADCollectionBase> RequestSecurityGroupsListAsync(string groupFilter)
|
||||
{
|
||||
var CM = MethodBase.GetCurrentMethod();
|
||||
LogMethodBegin(CM);
|
||||
try
|
||||
{
|
||||
await Task.Delay(0);
|
||||
|
||||
var Result = privRequestSecurityGroupsListAsync(groupFilter);
|
||||
if (Result != null)
|
||||
{
|
||||
var RetVal = new cADCollectionBase(Result.Count);
|
||||
foreach (var Entry in Result)
|
||||
{
|
||||
var res = new cSecurityGroupResult(Entry);
|
||||
RetVal.Add(res);
|
||||
}
|
||||
return RetVal;
|
||||
}
|
||||
}
|
||||
catch (Exception E)
|
||||
{
|
||||
LogException(E);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogMethodEnd(CM);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<cSecurityGroupResult> privRequestSecurityGroupsListAsync(string groupFilter = null, string rawLDAPFilter = null)
|
||||
{
|
||||
ResetError();
|
||||
List<cSecurityGroupResult> securityGroups = new List<cSecurityGroupResult>();
|
||||
|
||||
if (String.IsNullOrEmpty(privLogonInfo.TargetGroupPath) ||
|
||||
(string.IsNullOrEmpty(groupFilter) && string.IsNullOrEmpty(rawLDAPFilter)))
|
||||
{
|
||||
return new List<cSecurityGroupResult>();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var ctx = adContext;
|
||||
var entry = directoryEntry;
|
||||
|
||||
using (DirectorySearcher dSearch = new DirectorySearcher(entry))
|
||||
{
|
||||
dSearch.Filter = string.IsNullOrEmpty(rawLDAPFilter) ? "(&(" + groupFilter + ")(objectClass=group))" : rawLDAPFilter;
|
||||
dSearch.PageSize = 100000;
|
||||
|
||||
SearchResultCollection sr = dSearch.FindAll();
|
||||
if (sr.Count > 0)
|
||||
{
|
||||
foreach (SearchResult k in sr)
|
||||
{
|
||||
var sid = new SecurityIdentifier(k.Properties["objectSid"][0] as byte[], 0).Value;
|
||||
var dn = k.Properties["distinguishedname"][0].ToString();
|
||||
|
||||
// Initialisieren Sie die managedBy-SID als null
|
||||
string managedBySid = null;
|
||||
|
||||
// Prüfen, ob das managedBy-Attribut existiert und nicht null ist
|
||||
if (k.Properties.Contains("managedBy") && k.Properties["managedBy"].Count > 0)
|
||||
{
|
||||
// managedBy-DN erhalten
|
||||
string managedByDn = k.Properties["managedBy"][0].ToString();
|
||||
|
||||
// Erstellen eines DirectoryEntry-Objekts für den managedBy-DN
|
||||
using (DirectoryEntry managedByEntry = new DirectoryEntry($"LDAP://{managedByDn}"))
|
||||
{
|
||||
if (managedByEntry.Properties.Contains("objectSid") && managedByEntry.Properties["objectSid"].Count > 0)
|
||||
{
|
||||
// SID des managedBy-Objekts erhalten
|
||||
managedBySid = new SecurityIdentifier(managedByEntry.Properties["objectSid"][0] as byte[], 0).Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Neues SecurityGroup-Objekt erstellen
|
||||
cSecurityGroupResult group = new cSecurityGroupResult()
|
||||
{
|
||||
ID = sid,
|
||||
Path = dn,
|
||||
DisplayName = k.Properties["Name"][0].ToString(),
|
||||
Description = k.Properties.Contains("Description") ? k.Properties["Description"][0].ToString() : string.Empty,
|
||||
Scope = (GroupScope)GroupPrincipal.FindByIdentity(ctx, IdentityType.Sid, sid).GroupScope,
|
||||
ManagedBySID = managedBySid
|
||||
};
|
||||
|
||||
securityGroups.Add(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
cLogManager.LogException(e);
|
||||
return new List<cSecurityGroupResult>(securityGroups);
|
||||
}
|
||||
|
||||
return securityGroups;
|
||||
}
|
||||
|
||||
public class cADCollectionBase : SortedList<string, cADResultBase>
|
||||
{
|
||||
public cADCollectionBase() { }
|
||||
public cADCollectionBase(int n) : base(n) { }
|
||||
|
||||
public void Add(cADResultBase adr)
|
||||
{
|
||||
if (!this.ContainsKey(adr.ID))
|
||||
this.Add(adr.ID, adr);
|
||||
}
|
||||
}
|
||||
|
||||
public class cSecurityGroupResult : cADResultBase
|
||||
{
|
||||
public cSecurityGroupResult() { }
|
||||
public cSecurityGroupResult(cADResultBase b) : base(b)
|
||||
{
|
||||
this.ManagedBySID = (b as cSecurityGroupResult)?.ManagedBySID;
|
||||
}
|
||||
public GroupScope Scope { get; internal set; }
|
||||
public string ManagedBySID { get; internal set; }
|
||||
}
|
||||
public class cADUserResult : cADResultBase
|
||||
{
|
||||
public string GivenName { get; internal set; }
|
||||
public string SurName { get; internal set; }
|
||||
public string UserPrincipalName { get; internal set; }
|
||||
public string Email { get; internal set; }
|
||||
public cADUserResult() { }
|
||||
public cADUserResult(cADResultBase b) : base(b)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public cADUserResult(Principal Result) : base(Result)
|
||||
{
|
||||
UserPrincipalName = Result.UserPrincipalName;
|
||||
}
|
||||
|
||||
public GroupScope Scope { get; internal set; }
|
||||
}
|
||||
public class cADResultBase
|
||||
{
|
||||
public string ID { get; set; } = null;
|
||||
public string DisplayName { get; set; } = null;
|
||||
public string Path { get; set; } = null;
|
||||
public DateTime CreatedDate { get; set; } = DateTime.MinValue;
|
||||
public string Description { get; set; } = null;
|
||||
|
||||
public cADResultBase()
|
||||
{ }
|
||||
public cADResultBase(cADResultBase Result)
|
||||
{
|
||||
if (Result == null)
|
||||
return;
|
||||
|
||||
ID = Result.ID;
|
||||
DisplayName = Result.DisplayName;
|
||||
Description = Result.Description;
|
||||
Path = Result.Path;
|
||||
}
|
||||
public cADResultBase(Principal Result)
|
||||
{
|
||||
if (Result == null)
|
||||
return;
|
||||
|
||||
ID = Result.Sid.ToString();
|
||||
DisplayName = Result.DisplayName;
|
||||
Path = Result.DistinguishedName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchrones Abrufen des managedBy-Attributs einer AD-Gruppe anhand ihrer SID.
|
||||
/// Gibt den Distinguished Name (DN) des Managers zurück.
|
||||
/// </summary>
|
||||
/// <param name="groupSid">Die SID der AD-Gruppe.</param>
|
||||
/// <returns>Der DN des Managers oder null, falls nicht gefunden.</returns>
|
||||
public async Task<string> GetManagedByDnAsync(string dn)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Simuliert einen asynchronen Aufruf
|
||||
await Task.Yield();
|
||||
|
||||
using (var group = GroupPrincipal.FindByIdentity(adContext, IdentityType.DistinguishedName, dn))
|
||||
{
|
||||
if (group == null)
|
||||
{
|
||||
cLogManager.LogEntry($"Gruppe mit dn {dn} nicht gefunden.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Zugriff auf das underlying DirectoryEntry, um das managedBy-Attribut zu lesen
|
||||
var directoryEntry = group.GetUnderlyingObject() as DirectoryEntry;
|
||||
if (directoryEntry != null && directoryEntry.Properties.Contains("managedBy"))
|
||||
{
|
||||
var managedByValue = directoryEntry.Properties["managedBy"].Value as string;
|
||||
if (!string.IsNullOrEmpty(managedByValue))
|
||||
{
|
||||
return managedByValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
cLogManager.LogEntry($"managedBy-Attribut für Gruppe mit dn {dn} ist leer.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cLogManager.LogEntry($"Gruppe mit dn {dn} hat kein managedBy-Attribut.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
cLogManager.LogException(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchrones Abrufen der Mitglieder des Managers einer AD-Gruppe anhand des groupSid.
|
||||
/// Verwendet den DN des Managers.
|
||||
/// </summary>
|
||||
/// <param name="groupSid">Die SID der AD-Gruppe.</param>
|
||||
/// <returns>Eine cADCollectionBase mit den Mitgliedern oder null.</returns>
|
||||
public async Task<cADCollectionBase> GetManagedByMembersAsync(string groupSid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var managedByDn = await GetManagedByDnAsync(groupSid);
|
||||
if (!string.IsNullOrEmpty(managedByDn))
|
||||
{
|
||||
return await GetMembersByDnAsync(managedByDn);
|
||||
}
|
||||
else
|
||||
{
|
||||
cLogManager.LogEntry($"Keine gültige managedBy DN für Gruppe mit SID {groupSid} gefunden.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
cLogManager.LogException(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchrones Abrufen der Mitglieder einer AD-Gruppe anhand des Distinguished Name (DN).
|
||||
/// </summary>
|
||||
/// <param name="dn">Der Distinguished Name der AD-Gruppe.</param>
|
||||
/// <returns>Eine cADCollectionBase mit den Mitgliedern oder null.</returns>
|
||||
public async Task<cADCollectionBase> GetMembersByDnAsync(string dn)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Simuliert einen asynchronen Aufruf
|
||||
await Task.Yield();
|
||||
|
||||
var result = privGetMembersByDnAsync(dn).ToList();
|
||||
if (result != null && result.Any())
|
||||
{
|
||||
var retVal = new cADCollectionBase(result.Count);
|
||||
foreach (var entry in result)
|
||||
{
|
||||
var res = new cADUserResult(entry);
|
||||
if (!string.IsNullOrEmpty(res.Path))
|
||||
retVal.Add(res);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cLogManager.LogEntry($"Keine Mitglieder für Gruppe mit DN {dn} gefunden.");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
cLogManager.LogException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interne Methode zum Abrufen der Mitglieder einer AD-Gruppe anhand des Distinguished Name (DN).
|
||||
/// </summary>
|
||||
/// <param name="dn">Der Distinguished Name der AD-Gruppe.</param>
|
||||
/// <returns>Eine PrincipalSearchResult mit den Mitgliedern oder null.</returns>
|
||||
private PrincipalSearchResult<Principal> privGetMembersByDnAsync(string dn)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var group = GroupPrincipal.FindByIdentity(adContext, IdentityType.DistinguishedName, dn))
|
||||
{
|
||||
if (group == null)
|
||||
{
|
||||
cLogManager.LogEntry($"Gruppe mit DN {dn} nicht gefunden.");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return group.GetMembers(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
cLogManager.LogException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchrones Abrufen der Mitglieder einer AD-Gruppe anhand ihrer SID.
|
||||
/// Diese Methode bleibt unverändert und kann weiterhin verwendet werden.
|
||||
/// </summary>
|
||||
/// <param name="sid">Die SID der AD-Gruppe.</param>
|
||||
/// <returns>Eine cADCollectionBase mit den Mitgliedern oder null.</returns>
|
||||
internal async Task<cADCollectionBase> GetMembersAsync(string sid)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Simuliert einen asynchronen Aufruf
|
||||
await Task.Yield();
|
||||
|
||||
var result = privGetMembersAsync(sid).ToList();
|
||||
if (result != null && result.Any())
|
||||
{
|
||||
var retVal = new cADCollectionBase(result.Count);
|
||||
foreach (var entry in result)
|
||||
{
|
||||
var res = new cADUserResult(entry);
|
||||
if (!string.IsNullOrEmpty(res.Path))
|
||||
retVal.Add(res);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
cLogManager.LogEntry($"Keine Mitglieder für Gruppe mit SID {sid} gefunden.");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
cLogManager.LogException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interne Methode zum Abrufen der Mitglieder einer AD-Gruppe anhand ihrer SID.
|
||||
/// Diese Methode bleibt unverändert und kann weiterhin verwendet werden.
|
||||
/// </summary>
|
||||
/// <param name="sid">Die SID der AD-Gruppe.</param>
|
||||
/// <returns>Eine PrincipalSearchResult mit den Mitgliedern oder null.</returns>
|
||||
private PrincipalSearchResult<Principal> privGetMembersAsync(string sid)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var group = GroupPrincipal.FindByIdentity(adContext, IdentityType.Sid, sid))
|
||||
{
|
||||
if (group == null)
|
||||
{
|
||||
cLogManager.LogEntry($"Gruppe mit SID {sid} nicht gefunden.");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return group.GetMembers(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
cLogManager.LogException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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")]
|
||||
@@ -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.
@@ -0,0 +1,14 @@
|
||||
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
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
88ca960765b758a5c4edcddedf6dc811f2a49d840cd7ade015d7644911a99c77
|
||||
BIN
LIAMActiveDirectory/obj/Debug/LiamActiveDirectory.dll
Normal file
BIN
LIAMActiveDirectory/obj/Debug/LiamActiveDirectory.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/obj/Debug/LiamActiveDirectory.pdb
Normal file
BIN
LIAMActiveDirectory/obj/Debug/LiamActiveDirectory.pdb
Normal file
Binary file not shown.
@@ -0,0 +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")]
|
||||
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
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
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
ab9bb136583040c5ab0b8fc2b80edba3f154caa1532f30973b39973f0def47e6
|
||||
BIN
LIAMActiveDirectory/obj/Release/LiamActiveDirectory.dll
Normal file
BIN
LIAMActiveDirectory/obj/Release/LiamActiveDirectory.dll
Normal file
Binary file not shown.
BIN
LIAMActiveDirectory/obj/Release/LiamActiveDirectory.pdb
Normal file
BIN
LIAMActiveDirectory/obj/Release/LiamActiveDirectory.pdb
Normal file
Binary file not shown.
4
LIAMActiveDirectory/packages.config
Normal file
4
LIAMActiveDirectory/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?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