support active directory trust relationships
This commit is contained in:
+31
-33
@@ -7,37 +7,37 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Services.Interop.ActiveDirectory
|
||||
{
|
||||
public class ADDiscoverForestServers : ScheduledTask
|
||||
public class ADDiscoverServers : ScheduledTask
|
||||
{
|
||||
public override string TaskName { get { return "Active Directory - Discover Forest Servers"; } }
|
||||
public override string TaskName { get { return "Active Directory - Discover Servers"; } }
|
||||
public override bool SingleInstanceTask { get { return true; } }
|
||||
public override bool CancelInitiallySupported { get { return false; } }
|
||||
internal static List<string> ForestServers { get; set; }
|
||||
internal static List<string> AllServers { get; set; }
|
||||
private static object _scheduleLock = new object();
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
var forestServers = DiscoverForestServers();
|
||||
ADDiscoverForestServers.ForestServers = forestServers;
|
||||
var allServers = DiscoverAllServers();
|
||||
AllServers = allServers;
|
||||
|
||||
// Restrict Searching Entire Forest if to many servers
|
||||
// Restrict Searching Entire Directory if to many servers
|
||||
using (DiscoDataContext Database = new DiscoDataContext())
|
||||
{
|
||||
var searchEntireForest = Database.DiscoConfiguration.ActiveDirectory.SearchAllForestServers;
|
||||
var searchAllServers = Database.DiscoConfiguration.ActiveDirectory.SearchAllServers;
|
||||
|
||||
// Check explicitly configured: No
|
||||
if (!searchEntireForest.HasValue || searchEntireForest.Value)
|
||||
if (!searchAllServers.HasValue || searchAllServers.Value)
|
||||
{
|
||||
// Not Configured, or explicitly configured: Yes
|
||||
if (forestServers.Count > ActiveDirectory.MaxForestServerSearch)
|
||||
if (allServers.Count > ActiveDirectory.MaxAllServerSearch)
|
||||
{
|
||||
// Update Database
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllForestServers = false;
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllServers = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllForestServers = true;
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllServers = true;
|
||||
}
|
||||
|
||||
Database.SaveChanges();
|
||||
@@ -47,69 +47,67 @@ namespace Disco.Services.Interop.ActiveDirectory
|
||||
|
||||
internal static ScheduledTaskStatus ScheduleNow()
|
||||
{
|
||||
var taskStatus = ScheduledTasks.GetTaskStatuses(typeof(ADDiscoverForestServers)).Where(ts => ts.IsRunning).FirstOrDefault();
|
||||
var taskStatus = ScheduledTasks.GetTaskStatuses(typeof(ADDiscoverServers)).Where(ts => ts.IsRunning).FirstOrDefault();
|
||||
if (taskStatus != null)
|
||||
return taskStatus;
|
||||
else
|
||||
{
|
||||
lock (_scheduleLock)
|
||||
{
|
||||
taskStatus = ScheduledTasks.GetTaskStatuses(typeof(ADDiscoverForestServers)).Where(ts => ts.IsRunning).FirstOrDefault();
|
||||
taskStatus = ScheduledTasks.GetTaskStatuses(typeof(ADDiscoverServers)).Where(ts => ts.IsRunning).FirstOrDefault();
|
||||
if (taskStatus != null)
|
||||
return taskStatus;
|
||||
else
|
||||
{
|
||||
var t = new ADDiscoverForestServers();
|
||||
var t = new ADDiscoverServers();
|
||||
return t.ScheduleTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<string> LoadForestServersBlocking()
|
||||
public static List<string> LoadAllServersSync()
|
||||
{
|
||||
if (ADDiscoverForestServers.ForestServers != null)
|
||||
return ADDiscoverForestServers.ForestServers;
|
||||
if (AllServers != null)
|
||||
return AllServers;
|
||||
|
||||
ScheduledTaskStatus status;
|
||||
lock (_scheduleLock)
|
||||
{
|
||||
if (ADDiscoverForestServers.ForestServers != null)
|
||||
return ADDiscoverForestServers.ForestServers;
|
||||
if (AllServers != null)
|
||||
return AllServers;
|
||||
|
||||
status = ADDiscoverForestServers.ScheduleNow();
|
||||
status = ScheduleNow();
|
||||
}
|
||||
|
||||
status.CompletionTask.Wait();
|
||||
return ForestServers;
|
||||
return AllServers;
|
||||
}
|
||||
|
||||
public static Task<List<string>> LoadForestServersAsync()
|
||||
public static Task<List<string>> LoadAllServersAsync()
|
||||
{
|
||||
if (ADDiscoverForestServers.ForestServers != null)
|
||||
return Task.FromResult(ADDiscoverForestServers.ForestServers);
|
||||
if (AllServers != null)
|
||||
return Task.FromResult(AllServers);
|
||||
|
||||
ScheduledTaskStatus status;
|
||||
lock (_scheduleLock)
|
||||
{
|
||||
if (ADDiscoverForestServers.ForestServers != null)
|
||||
return Task.FromResult(ADDiscoverForestServers.ForestServers);
|
||||
if (AllServers != null)
|
||||
return Task.FromResult(AllServers);
|
||||
|
||||
status = ADDiscoverForestServers.ScheduleNow();
|
||||
status = ScheduleNow();
|
||||
}
|
||||
|
||||
return status.CompletionTask.ContinueWith(t =>
|
||||
{
|
||||
return ADDiscoverForestServers.ForestServers;
|
||||
return AllServers;
|
||||
});
|
||||
}
|
||||
|
||||
private static List<string> DiscoverForestServers()
|
||||
private static List<string> DiscoverAllServers()
|
||||
{
|
||||
using (var computerDomain = Domain.GetComputerDomain())
|
||||
{
|
||||
return computerDomain.Forest.Domains.Cast<Domain>().SelectMany(d => d.FindAllDomainControllers().Cast<DomainController>()).Select(dc => dc.Name).ToList();
|
||||
}
|
||||
return ActiveDirectory.Context.Domains
|
||||
.SelectMany(d => d.Domain.FindAllDomainControllers().Cast<DomainController>().Select(dc => dc.Name)).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
||||
var ldapFilter = string.Format(ldapFilterTemplate, ADHelpers.EscapeLdapQuery(deviceSamAccountName));
|
||||
IEnumerable<ADDomainController> domainControllers;
|
||||
|
||||
if (context.SearchAllForestServers)
|
||||
if (context.SearchAllServers)
|
||||
domainControllers = deviceDomain.GetAllReachableDomainControllers();
|
||||
else
|
||||
domainControllers = deviceDomain.GetReachableSiteDomainControllers();
|
||||
@@ -122,7 +122,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
||||
|
||||
// Determine Domain Controllers to Query
|
||||
IEnumerable<Tuple<ADDomain, ADDomainController, List<string>>> serverQueries;
|
||||
if (context.SearchAllForestServers)
|
||||
if (context.SearchAllServers)
|
||||
serverQueries = domainQueries.SelectMany(q => q.Item1.GetAllReachableDomainControllers(), (q, dc) => Tuple.Create(q.Item1, dc, q.Item2));
|
||||
else
|
||||
serverQueries = domainQueries.SelectMany(q => q.Item1.GetReachableSiteDomainControllers(), (q, dc) => Tuple.Create(q.Item1, dc, q.Item2));
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
||||
{
|
||||
public const int SingleSearchResult = 1;
|
||||
public const int DefaultSearchResultLimit = 30;
|
||||
public const int MaxForestServerSearch = 30;
|
||||
public const int MaxAllServerSearch = 30;
|
||||
public const int DomainControllerUnavailableMinutes = 10;
|
||||
|
||||
private static ActiveDirectoryContext context;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
@@ -15,24 +16,24 @@ namespace Disco.Services.Interop.ActiveDirectory
|
||||
public List<ADDomain> Domains { get; private set; }
|
||||
public ActiveDirectoryManagedGroups ManagedGroups { get; private set; }
|
||||
|
||||
public List<string> ForestServers
|
||||
public List<string> AllServers
|
||||
{
|
||||
get
|
||||
{
|
||||
return ADDiscoverForestServers.LoadForestServersBlocking();
|
||||
return ADDiscoverServers.LoadAllServersSync();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _SearchAllForestServers { get; set; }
|
||||
public bool SearchAllForestServers
|
||||
private bool searchAllServers { get; set; }
|
||||
public bool SearchAllServers
|
||||
{
|
||||
get
|
||||
{
|
||||
var fs = ADDiscoverForestServers.ForestServers;
|
||||
if (fs != null && fs.Count > ActiveDirectory.MaxForestServerSearch)
|
||||
var fs = ADDiscoverServers.AllServers;
|
||||
if (fs != null && fs.Count > ActiveDirectory.MaxAllServerSearch)
|
||||
return false; // Never
|
||||
|
||||
return _SearchAllForestServers;
|
||||
return searchAllServers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +51,8 @@ namespace Disco.Services.Interop.ActiveDirectory
|
||||
|
||||
private void Initialize(DiscoDataContext Database)
|
||||
{
|
||||
// Search Entire Forest (default: true)
|
||||
_SearchAllForestServers = Database.DiscoConfiguration.ActiveDirectory.SearchAllForestServers ?? true;
|
||||
// Search Entire Directory (default: true)
|
||||
searchAllServers = Database.DiscoConfiguration.ActiveDirectory.SearchAllServers ?? true;
|
||||
|
||||
// Set Search LDAP Filters
|
||||
InitializeWildcardSearchSufixOnly(Database.DiscoConfiguration.ActiveDirectory.SearchWildcardSuffixOnly);
|
||||
@@ -62,11 +63,52 @@ namespace Disco.Services.Interop.ActiveDirectory
|
||||
|
||||
// Determine Domains
|
||||
var computerDomain = Domain.GetComputerDomain();
|
||||
Domains = computerDomain.Forest.Domains
|
||||
var domains = computerDomain.Forest.Domains
|
||||
.Cast<Domain>()
|
||||
.Select(d => new ADDomain(this, d))
|
||||
.ToList();
|
||||
PrimaryDomain = Domains.Where(d => d.Name == computerDomain.Name).First();
|
||||
|
||||
// Try adding forest trust relationships
|
||||
try
|
||||
{
|
||||
var trustRelationships = computerDomain.Forest.GetAllTrustRelationships();
|
||||
|
||||
foreach (TrustRelationshipInformation trustRelationship in trustRelationships)
|
||||
{
|
||||
var sourceDomain = trustRelationship.SourceName;
|
||||
if (!domains.Any(d => string.Equals(d.Name, sourceDomain, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var domain = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, sourceDomain));
|
||||
domains.Add(new ADDomain(this, domain));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogException($"ActiveDirectory Initialize Trust Domain: [{sourceDomain}]", ex);
|
||||
}
|
||||
}
|
||||
var targetDomain = trustRelationship.TargetName;
|
||||
if (!domains.Any(d => string.Equals(d.Name, targetDomain, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
try
|
||||
{
|
||||
var domain = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, targetDomain));
|
||||
domains.Add(new ADDomain(this, domain));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogException($"ActiveDirectory Initialize Trust Domain: [{targetDomain}]", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
SystemLog.LogException("ActiveDirectory Initialize Trust Domains", ex);
|
||||
}
|
||||
PrimaryDomain = domains.Where(d => d.Name == computerDomain.Name).First();
|
||||
Domains = domains;
|
||||
|
||||
// Determine Search Scope Containers
|
||||
ReinitializeSearchContainers(Database.DiscoConfiguration.ActiveDirectory.SearchContainers);
|
||||
@@ -180,7 +222,7 @@ namespace Disco.Services.Interop.ActiveDirectory
|
||||
|
||||
#region Searching
|
||||
|
||||
public IEnumerable<ADSearchResult> SearchEntireForest(string LdapFilter, string[] LoadProperties, int? ResultLimit = null)
|
||||
public IEnumerable<ADSearchResult> SearchEntireDirectory(string LdapFilter, string[] LoadProperties, int? ResultLimit = null)
|
||||
{
|
||||
var queries = Domains.Select(d => Tuple.Create(d, d.DistinguishedName));
|
||||
|
||||
@@ -249,27 +291,27 @@ namespace Disco.Services.Interop.ActiveDirectory
|
||||
}
|
||||
}
|
||||
|
||||
public bool UpdateSearchAllForestServers(DiscoDataContext Database, bool SearchAllForestServers)
|
||||
public bool UpdateSearchAllServers(DiscoDataContext Database, bool SearchAllServers)
|
||||
{
|
||||
if (SearchAllForestServers == false)
|
||||
if (SearchAllServers == false)
|
||||
{
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllForestServers = false;
|
||||
_SearchAllForestServers = false;
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllServers = false;
|
||||
searchAllServers = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var forestServers = ADDiscoverForestServers.LoadForestServersBlocking();
|
||||
if (forestServers.Count <= ActiveDirectory.MaxForestServerSearch)
|
||||
var allServers = ADDiscoverServers.LoadAllServersSync();
|
||||
if (allServers.Count <= ActiveDirectory.MaxAllServerSearch)
|
||||
{
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllForestServers = true;
|
||||
_SearchAllForestServers = true;
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllServers = true;
|
||||
searchAllServers = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllForestServers = false;
|
||||
_SearchAllForestServers = false;
|
||||
Database.DiscoConfiguration.ActiveDirectory.SearchAllServers = false;
|
||||
searchAllServers = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user