bug: AD ignore foreign security principals

This commit is contained in:
Gary Sharp
2024-12-30 14:25:08 +11:00
parent 26bac92e5a
commit 4006bdbcc6
2 changed files with 46 additions and 34 deletions
@@ -143,7 +143,7 @@ namespace Disco.Services.Interop.ActiveDirectory
#endregion #endregion
#region Machine Accounts #region Machine Accounts
public ADMachineAccount RetrieveADMachineAccount(string Id, System.Guid? UUIDNetbootGUID, System.Guid? MacAddressNetbootGUID, string[] AdditionalProperties = null) public ADMachineAccount RetrieveADMachineAccount(string Id, Guid? UUIDNetbootGUID, Guid? MacAddressNetbootGUID, string[] AdditionalProperties = null)
{ {
if (string.IsNullOrWhiteSpace(Id)) if (string.IsNullOrWhiteSpace(Id))
throw new ArgumentNullException("Id"); throw new ArgumentNullException("Id");
@@ -186,7 +186,7 @@ namespace Disco.Services.Interop.ActiveDirectory
{ {
return RetrieveADMachineAccount(Id, null, null, AdditionalProperties); return RetrieveADMachineAccount(Id, null, null, AdditionalProperties);
} }
public ADMachineAccount RetrieveADMachineAccount(string Id, System.Guid? NetbootGUID, string[] AdditionalProperties = null) public ADMachineAccount RetrieveADMachineAccount(string Id, Guid? NetbootGUID, string[] AdditionalProperties = null)
{ {
return RetrieveADMachineAccount(Id, NetbootGUID, null, AdditionalProperties); return RetrieveADMachineAccount(Id, NetbootGUID, null, AdditionalProperties);
} }
@@ -256,23 +256,31 @@ namespace Disco.Services.Interop.ActiveDirectory
else else
{ {
var objectCategory = result.Value<string>("objectCategory"); var objectCategory = result.Value<string>("objectCategory");
objectCategory = objectCategory.Substring(0, objectCategory.IndexOf(',')).ToLower();
switch (objectCategory) if (objectCategory == null || objectCategory.Length == 0)
{ throw new InvalidOperationException("objectCategory is null or empty");
case "cn=person":
if (objectCategory.StartsWith("CN=Person,", StringComparison.OrdinalIgnoreCase))
return result.AsADUserAccount(Quick, AdditionalProperties); return result.AsADUserAccount(Quick, AdditionalProperties);
case "cn=computer": else if (objectCategory.StartsWith("CN=Computer,", StringComparison.OrdinalIgnoreCase))
return result.AsADMachineAccount(AdditionalProperties); return result.AsADMachineAccount(AdditionalProperties);
case "cn=group": else if (objectCategory.StartsWith("CN=Group,", StringComparison.OrdinalIgnoreCase))
return result.AsADGroup(AdditionalProperties); return result.AsADGroup(AdditionalProperties);
default: else if (objectCategory.StartsWith("CN=Foreign-Security-Principal,", StringComparison.OrdinalIgnoreCase))
return null;
else
throw new InvalidOperationException("Unexpected objectCategory"); throw new InvalidOperationException("Unexpected objectCategory");
} }
} }
}
public IADObject RetrieveADObjectByDistinguishedName(string distinguishedName, bool quick, string[] additionalProperties = null) public IADObject RetrieveADObjectByDistinguishedName(string distinguishedName, bool quick, string[] additionalProperties = null)
{ {
// ignore foreign security principals
var containerIndex = distinguishedName.IndexOf(',') + 1;
var container = distinguishedName.Substring(containerIndex, distinguishedName.IndexOf(',', containerIndex) - containerIndex);
if (string.Equals("CN=ForeignSecurityPrincipals", container, StringComparison.OrdinalIgnoreCase))
return null;
using (var entry = RetrieveDirectoryEntry(distinguishedName, additionalProperties)) using (var entry = RetrieveDirectoryEntry(distinguishedName, additionalProperties))
{ {
if (entry == null) if (entry == null)
@@ -319,7 +327,7 @@ namespace Disco.Services.Interop.ActiveDirectory
var slashIndex = Id.IndexOf('\\'); var slashIndex = Id.IndexOf('\\');
if (!Domain.NetBiosName.Equals(Id.Substring(0, slashIndex), StringComparison.OrdinalIgnoreCase)) if (!Domain.NetBiosName.Equals(Id.Substring(0, slashIndex), StringComparison.OrdinalIgnoreCase))
throw new ArgumentException(string.Format("The Id [{0}] is invalid for this domain [{1}]", Id, Domain.Name), "Id"); throw new ArgumentException($"The Id [{Id}] is invalid for this domain [{Domain.Name}]", "Id");
var ldapFilter = string.Format(LdapFilterTemplate, Id.Substring(slashIndex + 1)); var ldapFilter = string.Format(LdapFilterTemplate, Id.Substring(slashIndex + 1));
@@ -340,10 +348,10 @@ namespace Disco.Services.Interop.ActiveDirectory
public string OfflineDomainJoinProvision(string ComputerSamAccountName, string OrganisationalUnit, ref ADMachineAccount MachineAccount, out string DiagnosticInformation) public string OfflineDomainJoinProvision(string ComputerSamAccountName, string OrganisationalUnit, ref ADMachineAccount MachineAccount, out string DiagnosticInformation)
{ {
if (MachineAccount != null && MachineAccount.IsCriticalSystemObject) if (MachineAccount != null && MachineAccount.IsCriticalSystemObject)
throw new InvalidOperationException(string.Format("This account {0} is a Critical System Active Directory Object and Disco ICT refuses to modify it", MachineAccount.DistinguishedName)); throw new InvalidOperationException($"This account {MachineAccount.DistinguishedName} is a Critical System Active Directory Object and Disco ICT refuses to modify it");
if (!IsWritable) if (!IsWritable)
throw new InvalidOperationException(string.Format("The domain controller [{0}] is not writable. This action (Offline Domain Join Provision) requires a writable domain controller.", Name)); throw new InvalidOperationException($"The domain controller [{Name}] is not writable. This action (Offline Domain Join Provision) requires a writable domain controller.");
StringBuilder diagnosticInfo = new StringBuilder(); StringBuilder diagnosticInfo = new StringBuilder();
string DJoinResult = null; string DJoinResult = null;
@@ -355,7 +363,7 @@ namespace Disco.Services.Interop.ActiveDirectory
// NetBIOS Limit (16 characters; "{ComputerName}$"; 15 characters allowed) // NetBIOS Limit (16 characters; "{ComputerName}$"; 15 characters allowed)
if (string.IsNullOrWhiteSpace(ComputerSamAccountName) || ComputerSamAccountName.Length > 15) if (string.IsNullOrWhiteSpace(ComputerSamAccountName) || ComputerSamAccountName.Length > 15)
throw new System.ArgumentException("Invalid Computer Name; > 0 and <= 15", "ComputerName"); throw new ArgumentException("Invalid Computer Name; > 0 and <= 15", "ComputerName");
// Ensure Specified OU Exists // Ensure Specified OU Exists
if (!string.IsNullOrEmpty(OrganisationalUnit)) if (!string.IsNullOrEmpty(OrganisationalUnit))
@@ -417,12 +425,15 @@ namespace Disco.Services.Interop.ActiveDirectory
System.IO.File.Delete(tempFileName); System.IO.File.Delete(tempFileName);
} }
if (string.IsNullOrWhiteSpace(DJoinResult)) if (string.IsNullOrWhiteSpace(DJoinResult))
throw new System.InvalidOperationException(string.Format("Domain Join Unsuccessful{0}Error: {1}{0}Output: {2}", System.Environment.NewLine, stdError, stdOutput)); throw new InvalidOperationException(
$@"Domain Join Unsuccessful
Error: {stdError}
Output: {stdOutput}");
DiagnosticInformation = diagnosticInfo.ToString(); DiagnosticInformation = diagnosticInfo.ToString();
// Reload Machine Account // Reload Machine Account
MachineAccount = RetrieveADMachineAccount(string.Format(@"{0}\{1}", Domain.NetBiosName, ComputerSamAccountName), (MachineAccount == null ? null : MachineAccount.LoadedProperties.Keys.ToArray())); MachineAccount = RetrieveADMachineAccount($@"{Domain.NetBiosName}\{ComputerSamAccountName}", (MachineAccount == null ? null : MachineAccount.LoadedProperties.Keys.ToArray()));
return DJoinResult; return DJoinResult;
} }
@@ -98,21 +98,22 @@ namespace Disco.Services
public static IADObject AsADObject(this ADDirectoryEntry directoryEntry, bool quick, string[] additionalProperties) public static IADObject AsADObject(this ADDirectoryEntry directoryEntry, bool quick, string[] additionalProperties)
{ {
var properties = directoryEntry.Entry.Properties; var objectCategory = directoryEntry.Entry.Properties.Value<string>("objectCategory");
var objectCategory = properties.Value<string>("objectCategory");
objectCategory = objectCategory.Substring(0, objectCategory.IndexOf(',')).ToLower(); if (objectCategory == null || objectCategory.Length == 0)
switch (objectCategory) throw new InvalidOperationException("objectCategory is null or empty");
{
case "cn=person": if (objectCategory.StartsWith("CN=Person,", StringComparison.OrdinalIgnoreCase))
return ADUserAccount.FromDirectoryEntry(directoryEntry, quick, additionalProperties); return ADUserAccount.FromDirectoryEntry(directoryEntry, quick, additionalProperties);
case "cn=computer": else if (objectCategory.StartsWith("CN=Computer,", StringComparison.OrdinalIgnoreCase))
return ADMachineAccount.FromDirectoryEntry(directoryEntry, additionalProperties); return ADMachineAccount.FromDirectoryEntry(directoryEntry, additionalProperties);
case "cn=group": else if (objectCategory.StartsWith("CN=Group,", StringComparison.OrdinalIgnoreCase))
return ADGroup.FromDirectoryEntry(directoryEntry, additionalProperties); return ADGroup.FromDirectoryEntry(directoryEntry, additionalProperties);
default: else if (objectCategory.StartsWith("CN=Foreign-Security-Principal,", StringComparison.OrdinalIgnoreCase))
return null;
else
throw new InvalidOperationException("Unexpected objectCategory"); throw new InvalidOperationException("Unexpected objectCategory");
} }
}
#endregion #endregion