diff --git a/ConfigMgrWebService.Release.zip b/ConfigMgrWebService.Release.zip
new file mode 100644
index 0000000..75e481b
Binary files /dev/null and b/ConfigMgrWebService.Release.zip differ
diff --git a/ConfigMgrWebService/ADComputer.cs b/ConfigMgrWebService/ADComputer.cs
index 6639004..4cabe14 100644
--- a/ConfigMgrWebService/ADComputer.cs
+++ b/ConfigMgrWebService/ADComputer.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Web;
+using System.DirectoryServices;
namespace ConfigMgrWebService
{
@@ -11,5 +10,33 @@ public class ADComputer
public string CanonicalName { get; set; }
public string DnsHostName { get; set; }
public string DistinguishedName { get; set; }
+
+ public ADComputer() { }
+
+ ///
+ /// The 2nd constructor for . Using the specified ,
+ /// this will populate the class's properties.
+ ///
+ /// The to use when populating this class's properties.
+ public ADComputer(DirectoryEntry dirEntry)
+ {
+ using (dirEntry)
+ {
+ this.DistinguishedName = dirEntry.Properties[ConfigMgrWebService.DISTINGUISHED_NAME].Value as string;
+ this.CanonicalName = dirEntry.Properties[ConfigMgrWebService.COMMON_NAME].Value as string;
+ this.DnsHostName = dirEntry.Properties[ConfigMgrWebService.DNS_HOST_NAME].Value as string;
+ this.SamAccountName = dirEntry.Properties[ConfigMgrWebService.SAM_ACCOUNT_NAME].Value as string;
+ }
+ }
+
+ private ADComputer(ADComputerFromDC withDC)
+ {
+ this.CanonicalName = withDC.CanonicalName;
+ this.SamAccountName = withDC.SamAccountName;
+ this.DistinguishedName = withDC.DistinguishedName;
+ this.DnsHostName = withDC.DnsHostName;
+ }
+
+ public static explicit operator ADComputer(ADComputerFromDC compFromDC) => new ADComputer(compFromDC);
}
}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADComputerFromDC.cs b/ConfigMgrWebService/ADComputerFromDC.cs
new file mode 100644
index 0000000..aae3e5a
--- /dev/null
+++ b/ConfigMgrWebService/ADComputerFromDC.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.DirectoryServices;
+
+namespace ConfigMgrWebService
+{
+ public class ADComputerFromDC
+ {
+ public string SamAccountName { get; set; }
+ public string CanonicalName { get; set; }
+ public string DnsHostName { get; set; }
+ public string DistinguishedName { get; set; }
+ public string RespondingDC { get; set; }
+
+ public ADComputerFromDC() { }
+
+ ///
+ /// The 2nd constructor for . Using the specified ,
+ /// this will populate the class's properties. It also specfies the DomainController that responding with the
+ /// .
+ ///
+ /// The to use when populating this class's properties.
+ /// The responding domain controller of the .
+ public ADComputerFromDC(DirectoryEntry dirEntry, string dc)
+ {
+ this.RespondingDC = dc;
+ using (dirEntry)
+ {
+ this.DistinguishedName = dirEntry.Properties[ConfigMgrWebService.DISTINGUISHED_NAME].Value as string;
+ this.CanonicalName = dirEntry.Properties[ConfigMgrWebService.COMMON_NAME].Value as string;
+ this.DnsHostName = dirEntry.Properties[ConfigMgrWebService.DNS_HOST_NAME].Value as string;
+ this.SamAccountName = dirEntry.Properties[ConfigMgrWebService.SAM_ACCOUNT_NAME].Value as string;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADDomain.cs b/ConfigMgrWebService/ADDomain.cs
index 5842075..a342b4d 100644
--- a/ConfigMgrWebService/ADDomain.cs
+++ b/ConfigMgrWebService/ADDomain.cs
@@ -1,13 +1,105 @@
using System;
using System.Collections.Generic;
+using System.DirectoryServices;
+using System.DirectoryServices.ActiveDirectory;
using System.Linq;
using System.Web;
namespace ConfigMgrWebService
{
- public class ADDomain
+ public class ADDomain : IDisposable
{
+ private Domain _domain;
+ private string _typeName => this.GetType().FullName;
+ private bool _isDisp;
+
public string DomainName { get; set; }
public string DefaultNamingContext { get; set; }
+ public string Path { get; set; }
+
+ public ADDomain() { }
+
+ private ADDomain(Domain domain)
+ {
+ this.DomainName = domain.Name;
+ using (DirectoryEntry de = domain.GetDirectoryEntry())
+ {
+ this.DefaultNamingContext = de.Properties[ConfigMgrWebService.DISTINGUISHED_NAME].Value as string;
+ this.Path = de.Path;
+ }
+ _domain = domain;
+ }
+
+ public DomainControllerCollection GetAllDomainControllers()
+ {
+ this.CheckIfDisposed();
+ return _domain.FindAllDomainControllers();
+ }
+
+ public DomainController FindDomainController()
+ {
+ this.CheckIfDisposed();
+ return _domain.FindDomainController();
+ }
+
+ public bool IsDC(string computerName)
+ {
+ bool result = false;
+ DomainControllerCollection dcCol = this.GetAllDomainControllers();
+ if (dcCol.Count <= 0)
+ return result;
+
+ foreach (DomainController dc in dcCol)
+ {
+ using (dc)
+ {
+ using (DirectoryEntry dcEntry = dc.GetDirectoryEntry())
+ {
+ if (computerName.Equals(
+ dcEntry.Properties[ConfigMgrWebService.NAME].Value as string,
+ StringComparison.CurrentCultureIgnoreCase))
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ #region IDISPOSABLE METHODS
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_isDisp)
+ return;
+
+ if (disposing)
+ _domain.Dispose();
+
+ _isDisp = true;
+ }
+
+ private void CheckIfDisposed()
+ {
+ if (_isDisp)
+ throw new ObjectDisposedException(_typeName);
+ }
+
+ #endregion
+
+ public static implicit operator ADDomain(Domain domain) => new ADDomain(domain);
+
+ public static implicit operator Domain(ADDomain adDomain)
+ {
+ adDomain.CheckIfDisposed();
+ return adDomain._domain;
+ }
}
}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADGroup.cs b/ConfigMgrWebService/ADGroup.cs
index 524a9c2..5b5f5c9 100644
--- a/ConfigMgrWebService/ADGroup.cs
+++ b/ConfigMgrWebService/ADGroup.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.DirectoryServices;
using System.Linq;
using System.Web;
@@ -7,7 +8,27 @@ namespace ConfigMgrWebService
{
public class ADGroup
{
- public string samAccountName { get; set; }
+ public string SamAccountName { get; set; }
public string DistinguishedName { get; set; }
+ public string RespondingDC { get; }
+
+ public ADGroup() { }
+
+ ///
+ /// The 2nd constructor for . Using the specified ,
+ /// this will populate the class's properties. It also specfies the DomainController that responding with the
+ /// .
+ ///
+ /// The to use when populating this class's properties.
+ /// The responding domain controller of the .
+ public ADGroup(DirectoryEntry dirEntry, string dc)
+ {
+ this.RespondingDC = dc;
+ using (dirEntry)
+ {
+ this.SamAccountName = dirEntry.Properties["sAMAccountName"].Value as string;
+ this.DistinguishedName = dirEntry.Properties["distinguishedName"].Value as string;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/AddADComputerToGroupByDC.cs b/ConfigMgrWebService/ADOperations/AddADComputerToGroupByDC.cs
new file mode 100644
index 0000000..7b4eee5
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/AddADComputerToGroupByDC.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.DirectoryServices.ActiveDirectory;
+using System.Linq;
+using System.Reflection;
+using System.Web;
+using System.Web.Services;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ [WebMethod(Description = "")]
+ public bool AddADComputerToGroupByDC(string secret, string groupName, string computerName, string domainController)
+ {
+ var method = MethodBase.GetCurrentMethod();
+ MethodBegin(method);
+
+ //' Variable for return value
+ bool returnValue = false;
+
+ //' Validate secret key
+ if (secret == secretKey)
+ {
+ //' Log that secret key was accepted
+ WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
+
+ //' Get AD object distinguished name for computer and group
+ string computerDistinguishedName = (GetADObject(computerName, ADObjectClass.Computer, ADObjectType.distinguishedName, domainController)).Remove(0, 7);
+ string groupDistinguishedName = GetADObject(groupName, ADObjectClass.Group, ADObjectType.distinguishedName, domainController);
+
+ if (!string.IsNullOrEmpty(computerDistinguishedName) && !string.IsNullOrEmpty(groupDistinguishedName))
+ {
+ try
+ {
+ //' Add computer to group and commit
+ var groupEntry = new DirectoryEntry(groupDistinguishedName);
+ groupEntry.Properties["member"].Add(computerDistinguishedName);
+ groupEntry.CommitChanges();
+
+ //' Dispose object
+ groupEntry.Dispose();
+
+ returnValue = true;
+ }
+ catch (Exception ex)
+ {
+ WriteEventLog(string.Format("An error occured when attempting to add a computer object in Active Directory to a group. Error message: {0}", ex.Message), EventLogEntryType.Error);
+ }
+ }
+ }
+
+ MethodEnd(method);
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/AddADUserToGroupByDC.cs b/ConfigMgrWebService/ADOperations/AddADUserToGroupByDC.cs
new file mode 100644
index 0000000..2feceaf
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/AddADUserToGroupByDC.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.Reflection;
+using System.Web.Services;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ [WebMethod(Description = "Add a user in Active Directory to a specific group on the specified domain controller")]
+ public bool AddADUserToGroupByDC(string secret, string groupName, string userName, string domainController)
+ {
+ MethodBase method = MethodBase.GetCurrentMethod();
+ MethodBegin(method);
+
+ //' Variable for return value
+ bool returnValue = false;
+
+ //' Validate secret key
+ if (secret == secretKey)
+ {
+ //' Log that secret key was accepted
+ WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
+
+ //' Get AD object distinguished name for computer and group
+ string userDistinguishedName = (GetADObject(userName, ADObjectClass.User, ADObjectType.distinguishedName)).Remove(0, 7);
+ string groupDistinguishedName = GetADObject(groupName, ADObjectClass.Group, ADObjectType.distinguishedName);
+
+ if (!String.IsNullOrEmpty(userDistinguishedName) && !String.IsNullOrEmpty(groupDistinguishedName))
+ {
+ try
+ {
+ //' Add user to group and commit
+ DirectoryEntry groupEntry = new DirectoryEntry(groupDistinguishedName);
+ groupEntry.Properties["member"].Add(userDistinguishedName);
+ groupEntry.CommitChanges();
+
+ //' Dispose object
+ groupEntry.Dispose();
+
+ returnValue = true;
+ }
+ catch (Exception ex)
+ {
+ WriteEventLog(String.Format("An error occured when attempting to add an user object in Active Directory to a group. Error message: {0}", ex.Message), EventLogEntryType.Error);
+ }
+ }
+ }
+
+ MethodEnd(method);
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/GetADComputerByDC.cs b/ConfigMgrWebService/ADOperations/GetADComputerByDC.cs
new file mode 100644
index 0000000..9b25c8f
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/GetADComputerByDC.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.DirectoryServices.ActiveDirectory;
+using System.Reflection;
+using System.Web.Services;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ [WebMethod(Description = "Check if a computer object exists in Active Directory on the specified domain controller")]
+ public ADComputerFromDC GetADComputerByDC(string secret, string computerName, string dc)
+ {
+ var method = MethodBase.GetCurrentMethod();
+ MethodBegin(method);
+
+ //' Instatiate return value variable
+ ADComputerFromDC returnValue = null;
+
+ //' Validate secret key
+ if (secret == secretKey)
+ {
+ //' Log that secret key was accepted
+ WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
+
+ //' Set empty value for search result
+ SearchResult searchResult = null;
+ DirectoryEntry directoryObject = null;
+
+ //' Get default naming context of current domain
+ var domain = Domain.GetComputerDomain();
+ string respondingDC = GetRespondingDomainController(domain, dc);
+
+ //' Construct directory entry for directory searcher
+
+ string sFilter = string.Format("(&(objectClass=computer)((sAMAccountName={0}$)))", computerName);
+ var directorySearcher = new DirectorySearcher(domain.GetDirectoryEntry(), sFilter, COMPUTER_PROPERTIES);
+
+ //' Invoke directory searcher
+ try
+ {
+ searchResult = directorySearcher.FindOne();
+ if (searchResult != null)
+ {
+ //' Get computer object from search result
+ directoryObject = searchResult.GetDirectoryEntry();
+
+ if (directoryObject != null)
+ {
+ returnValue = new ADComputerFromDC(directoryObject, respondingDC);
+
+ // Dispose directory object
+ directoryObject.Dispose();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteEventLog(
+ string.Format(
+ "An error occured when attempting to locate Active Directory object. Error message: {0}",
+ ex.Message
+ ),
+ EventLogEntryType.Error
+ );
+ }
+
+ //' Dispose objects
+ directorySearcher.Dispose();
+ domain.Dispose();
+ }
+
+ MethodEnd(method);
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/GetADGroupMembersByDC.cs b/ConfigMgrWebService/ADOperations/GetADGroupMembersByDC.cs
new file mode 100644
index 0000000..3dc4170
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/GetADGroupMembersByDC.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.Reflection;
+using System.Web.Services;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ [WebMethod(Description = "Get all members of an Active Directory group on the specified domain controller.")]
+ public List GetADGroupMembersByDC(string secret, string groupName, string domainController)
+ {
+ var method = MethodBase.GetCurrentMethod();
+ MethodBegin(method);
+
+ //' Set return value variable
+ var returnValue = new List();
+
+ //' Validate secret key
+ if (secret == secretKey)
+ {
+ //' Log that secret key was accepted
+ WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
+
+ //' Get AD group object
+ string groupDistinguishedName = GetADObject(groupName, ADObjectClass.Group, ADObjectType.distinguishedName, domainController);
+
+ if (!string.IsNullOrEmpty(groupDistinguishedName))
+ {
+ try
+ {
+ var groupEntry = new DirectoryEntry(groupDistinguishedName);
+ returnValue = GetADGroupMemberList(groupEntry);
+ }
+ catch (Exception ex)
+ {
+ WriteEventLog(string.Format("An error occured when retrieving Active Directory group members. Error message: {0}", ex.Message), EventLogEntryType.Error);
+ }
+ }
+ }
+
+ MethodEnd(method);
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/GetADGroupsByUserByDC.cs b/ConfigMgrWebService/ADOperations/GetADGroupsByUserByDC.cs
new file mode 100644
index 0000000..a8d54d4
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/GetADGroupsByUserByDC.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.DirectoryServices.ActiveDirectory;
+using System.Reflection;
+using System.Web.Services;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ [WebMethod(Description = "Get Active Directory groups for a specific user on the specified domain controller.")]
+ public List GetADGroupsByUserByDC(string secret, string userName, string domainController)
+ {
+ var method = MethodBase.GetCurrentMethod();
+ MethodBegin(method);
+
+ //' Set return value variable
+ var returnValue = new List();
+
+ //' Validate secret key
+ if (secret == secretKey)
+ {
+ //' Log that secret key was accepted
+ WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
+
+ try
+ {
+ //' Get AD user object
+ string userDistinguishedName = GetADObject(userName, ADObjectClass.User, ADObjectType.distinguishedName, domainController);
+
+ //' Get AD groups for user distinguished name
+ var groupMemberships = new ArrayList();
+ ArrayList groups = GetADAttributeValues("memberOf", userDistinguishedName, groupMemberships, true);
+
+ foreach (string group in groups)
+ {
+ string attributeValue = GetADAttributeValue(group, "samAccountName");
+ returnValue.Add(new ADGroup() { DistinguishedName = group, SamAccountName = attributeValue });
+ }
+ }
+ catch (Exception ex)
+ {
+ WriteEventLog($"An error occurred while retrieving Active Directory group memberships for user. Error message: { ex.Message }", EventLogEntryType.Error);
+ }
+ }
+
+ MethodEnd(method);
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/GetADObject.cs b/ConfigMgrWebService/ADOperations/GetADObject.cs
new file mode 100644
index 0000000..457944b
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/GetADObject.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.DirectoryServices.ActiveDirectory;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ private string GetADObject(string name, ADObjectClass objectClass, ADObjectType objectType, string domainController = null)
+ {
+ //' Set empty value for return object and search result
+ string returnValue = string.Empty;
+ SearchResult searchResult = null;
+
+ string ldapFormat = string.IsNullOrEmpty(domainController)
+ ? "LDAP://{0}"
+ : "LDAP://{0}/{1}";
+
+ //' Get default naming context of current domain
+ string defaultNamingContext = GetADDefaultNamingContext();
+
+ string currentDomain = string.IsNullOrEmpty(domainController)
+ ? string.Format(ldapFormat, defaultNamingContext)
+ : string.Format(ldapFormat, domainController, defaultNamingContext);
+
+ //' Construct directory entry for directory searcher
+ var domain = new DirectoryEntry(currentDomain);
+ var directorySearcher = new DirectorySearcher(domain);
+ directorySearcher.PropertiesToLoad.Add("distinguishedName");
+
+ switch (objectClass)
+ {
+ case ADObjectClass.DomainController:
+ directorySearcher.Filter = string.Format("(&(objectClass=computer)((dNSHostName={0})))", name);
+ break;
+ case ADObjectClass.Computer:
+ directorySearcher.Filter = string.Format("(&(objectClass=computer)((sAMAccountName={0}$)))", name);
+ break;
+ case ADObjectClass.Group:
+ directorySearcher.Filter = string.Format("(&(objectClass=group)((sAMAccountName={0})))", name);
+ break;
+ case ADObjectClass.User:
+ directorySearcher.Filter = string.Format("(&(objectClass=user)((sAMAccountName={0})))", name);
+ break;
+ }
+
+ //' Invoke directory searcher
+ try
+ {
+ searchResult = directorySearcher.FindOne();
+ }
+ catch (Exception ex)
+ {
+ WriteEventLog(string.Format("An error occured when attempting to locate Active Directory object. Error message: {0}", ex.Message), EventLogEntryType.Error);
+ return returnValue;
+ }
+
+ //' Return selected object type value
+ if (searchResult != null)
+ {
+ DirectoryEntry directoryObject = searchResult.GetDirectoryEntry();
+
+ if (objectType.Equals(ADObjectType.objectGuid))
+ {
+ returnValue = directoryObject.Guid.ToString();
+ }
+
+ if (objectType.Equals(ADObjectType.distinguishedName))
+ {
+ returnValue = string.Format(ldapFormat, directoryObject.Properties["distinguishedName"].Value);
+ }
+ }
+
+ //' Dispose objects
+ directorySearcher.Dispose();
+ domain.Dispose();
+
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/RemoveADComputerByDC.cs b/ConfigMgrWebService/ADOperations/RemoveADComputerByDC.cs
new file mode 100644
index 0000000..56c0153
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/RemoveADComputerByDC.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.DirectoryServices.AccountManagement;
+using System.DirectoryServices.ActiveDirectory;
+using System.Reflection;
+using System.Web.Services;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ [WebMethod(Description = "Remove a computer object from Active Directory on the specified domain controller (Prohibits removal of domain controllers)")]
+ public bool RemoveADComputerByDC(string secret, string samAccountName, string dc)
+ {
+ var method = MethodBase.GetCurrentMethod();
+ MethodBegin(method);
+
+ //' Instatiate return value variable
+ bool returnValue = false;
+ ComputerPrincipal compPrin = null;
+ DirectoryEntry dirEntry = null;
+ string respondingDC = null;
+
+ //' Validate secret key
+ if (secret == secretKey)
+ {
+ //' Log that secret key was accepted
+ WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
+
+ using (ADDomain domain = Domain.GetComputerDomain())
+ {
+ if (!domain.IsDC(samAccountName))
+ {
+ WriteEventLog(string.Format("{0} is not a domain controller. Continuing with removal.", samAccountName), EventLogEntryType.Information);
+ compPrin = FindComputerObject(samAccountName, dc, out respondingDC);
+ if (compPrin == null)
+ {
+ WriteEventLog(string.Format("{0} was not found in active directory!", samAccountName), EventLogEntryType.Error);
+ }
+ else
+ {
+ dirEntry = (DirectoryEntry)compPrin.GetUnderlyingObject();
+ try
+ {
+ dirEntry.DeleteTree();
+ dirEntry.CommitChanges();
+ returnValue = true;
+ WriteEventLog(string.Format("{0} was successfully deleted from Active Directory on {1}.", samAccountName, respondingDC), EventLogEntryType.Information);
+ }
+ catch (DirectoryServicesCOMException comEx)
+ {
+ WriteEventLog(string.Format("{0}:{1}{1}{2}", comEx.Message, Environment.NewLine, comEx.ExtendedErrorMessage), EventLogEntryType.Error);
+ }
+ catch (AppDomainUnloadedException unloadEx)
+ {
+ WriteEventLog(string.Format("{0}{1}{1}{2}", unloadEx.Message, Environment.NewLine, unloadEx.StackTrace), EventLogEntryType.Error);
+ }
+ catch (Exception e)
+ {
+ WriteEventLog(e.Message, EventLogEntryType.Error);
+ }
+ }
+ }
+ else
+ {
+ WriteEventLog(string.Format("{0} matches the name of an existing domain controller! We are not allowed to remove domain controllers. Stopping the execution.", samAccountName), EventLogEntryType.Error);
+ }
+ }
+ }
+
+ dirEntry.Dispose();
+ compPrin.Dispose();
+
+ MethodEnd(method);
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/RemoveADComputerFromGroupByDC.cs b/ConfigMgrWebService/ADOperations/RemoveADComputerFromGroupByDC.cs
new file mode 100644
index 0000000..f7e3973
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/RemoveADComputerFromGroupByDC.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.Reflection;
+using System.Web.Services;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ [WebMethod(Description = "Remove a computer in Active Directory from a specific group on the specified domain controller.")]
+ public bool RemoveADComputerFromGroupByDC(string secret, string groupName, string computerName, string domainController)
+ {
+ var method = MethodBase.GetCurrentMethod();
+ MethodBegin(method);
+
+ //' Set return value variable
+ bool returnValue = false;
+
+ //' Validate secret key
+ if (secret == secretKey)
+ {
+ //' Log that secret key was accepted
+ WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
+
+ //' Get AD object distinguished name for computer and group
+ string computerDistinguishedName = (GetADObject(computerName, ADObjectClass.Computer, ADObjectType.distinguishedName, domainController)).Remove(0, 7);
+ string groupDistinguishedName = GetADObject(groupName, ADObjectClass.Group, ADObjectType.distinguishedName, domainController);
+
+ if (!string.IsNullOrEmpty(computerDistinguishedName) && !string.IsNullOrEmpty(groupDistinguishedName))
+ {
+ try
+ {
+ //' Check if computer is member of group
+ var groupEntry = new DirectoryEntry(groupDistinguishedName);
+ List groupMembers = GetADGroupMemberList(groupEntry);
+ bool memberOf = groupMembers.Contains(computerDistinguishedName);
+ if (memberOf == true)
+ {
+ //' Remove computer from group and commit
+ groupEntry.Properties["member"].Remove(computerDistinguishedName);
+ groupEntry.CommitChanges();
+
+ returnValue = true;
+ }
+
+ //' Dispose object
+ groupEntry.Dispose();
+ }
+ catch (Exception ex)
+ {
+ WriteEventLog(string.Format("An error occured when attempting to remove a computer object in Active Directory from a group. Error message: {0}", ex.Message), EventLogEntryType.Error);
+ }
+ }
+ }
+
+ MethodEnd(method);
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/SetADComputerManagedByByDC.cs b/ConfigMgrWebService/ADOperations/SetADComputerManagedByByDC.cs
new file mode 100644
index 0000000..6054937
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/SetADComputerManagedByByDC.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.DirectoryServices.ActiveDirectory;
+using System.Reflection;
+using System.Web;
+using System.Web.Services;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ [WebMethod(Description = "Set ManagedBy attribute for a specific computer with specified user name on the specified domain controller.")]
+ public bool SetADComputerManagedByByDC(string secret, string computerName, string userName, string domainController)
+ {
+ var method = MethodBase.GetCurrentMethod();
+ MethodBegin(method);
+
+ //' Variable for return value
+ bool returnValue = false;
+
+ //' Validate secret key
+ if (secret == secretKey)
+ {
+ //' Log that secret key was accepted
+ WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
+
+ //' Get AD computer and user object distinguished names
+ string computerDistinguishedName = GetADObject(computerName, ADObjectClass.Computer, ADObjectType.distinguishedName, domainController);
+ string userDistinguishedName = (GetADObject(userName, ADObjectClass.User, ADObjectType.distinguishedName, domainController)).Remove(0, 7);
+
+ if (!string.IsNullOrEmpty(computerDistinguishedName) && !string.IsNullOrEmpty(userDistinguishedName))
+ {
+ try
+ {
+ //' Add user to ManagedBy attribute and commit
+ var computerEntry = new DirectoryEntry(computerDistinguishedName);
+ computerEntry.Properties["ManagedBy"].Clear();
+ computerEntry.Properties["ManagedBy"].Add(userDistinguishedName);
+ computerEntry.CommitChanges();
+
+ //' Dispose object
+ computerEntry.Dispose();
+
+ returnValue = true;
+ }
+ catch (Exception ex)
+ {
+ WriteEventLog(string.Format("An error occured when attempting to add a user as ManagedBy for a computer object in Active Directory. Error message: {0}", ex.Message), EventLogEntryType.Error);
+ }
+ }
+ }
+
+ MethodEnd(method);
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOperations/SetADOrganizationalUnitForComputerByDC.cs b/ConfigMgrWebService/ADOperations/SetADOrganizationalUnitForComputerByDC.cs
new file mode 100644
index 0000000..0130589
--- /dev/null
+++ b/ConfigMgrWebService/ADOperations/SetADOrganizationalUnitForComputerByDC.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Diagnostics;
+using System.DirectoryServices;
+using System.DirectoryServices.ActiveDirectory;
+using System.Reflection;
+using System.Web;
+using System.Web.Services;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ [WebMethod(Description = "Move a computer in Active Directory to a specific organizational unit via the specified domain controller.")]
+ public bool SetADOrganizationalUnitForComputerByDC(string secret, string organizationalUnitLocation, string computerName, string domainController)
+ {
+ var method = MethodBase.GetCurrentMethod();
+ MethodBegin(method);
+
+ //' Variable for return value
+ bool returnValue = false;
+
+ //' Validate secret key
+ if (secret == secretKey)
+ {
+ //' Log that secret key was accepted
+ WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
+
+ //' Determine if ldap prefix needs to be appended
+ if (organizationalUnitLocation.StartsWith("LDAP://") == false && string.IsNullOrEmpty(domainController))
+ {
+ organizationalUnitLocation = string.Format("LDAP://{0}", organizationalUnitLocation);
+ }
+ else if (!string.IsNullOrEmpty(domainController))
+ {
+ string fullLDAP = "LDAP://{0}/{1}";
+ organizationalUnitLocation = string.Format(fullLDAP, domainController, organizationalUnitLocation);
+ }
+
+ //' Get AD object distinguished name
+ string currentDistinguishedName = GetADObject(computerName, ADObjectClass.Computer, ADObjectType.distinguishedName, domainController);
+
+ if (!string.IsNullOrEmpty(currentDistinguishedName))
+ {
+ try
+ {
+ //' Move current object to new location
+ var currentObject = new DirectoryEntry(currentDistinguishedName);
+ var newLocation = new DirectoryEntry(organizationalUnitLocation);
+ currentObject.MoveTo(newLocation, currentObject.Name);
+
+ returnValue = true;
+ }
+ catch (Exception ex)
+ {
+ WriteEventLog(string.Format("An error occured when attempting to move Active Directory object. Error message: {0}", ex.Message), EventLogEntryType.Error);
+ }
+ }
+ }
+
+ MethodEnd(method);
+ return returnValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ADOrganizationalUnit.cs b/ConfigMgrWebService/ADOrganizationalUnit.cs
index 821d190..612e0f4 100644
--- a/ConfigMgrWebService/ADOrganizationalUnit.cs
+++ b/ConfigMgrWebService/ADOrganizationalUnit.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.DirectoryServices;
using System.Linq;
using System.Web;
@@ -7,8 +8,61 @@ namespace ConfigMgrWebService
{
public class ADOrganizationalUnit
{
+
+ private string Path { get; set; }
+
public string Name { set; get; }
public string DistinguishedName { set; get; }
public bool HasChildren { set; get; }
+
+ public ADOrganizationalUnit() { }
+
+ ///
+ /// The 2nd constructor for . Using the specified ,
+ /// this will populate the class's properties.
+ ///
+ /// The to use when populating this class's properties.
+ public ADOrganizationalUnit(DirectoryEntry dirEntry)
+ {
+ using (dirEntry)
+ {
+ if (dirEntry.SchemaClassName != ConfigMgrWebService.ORG_UNIT)
+ throw new ArgumentException("The provided DirectoryEntry is not a valid Organizational Unit!");
+
+ this.HasChildren = false;
+ this.Name = dirEntry.Properties[ConfigMgrWebService.NAME].Value as string;
+ this.DistinguishedName = dirEntry.Properties[ConfigMgrWebService.DISTINGUISHED_NAME].Value as string;
+ foreach (DirectoryEntry child in dirEntry.Children)
+ {
+ if (child.SchemaClassName == ConfigMgrWebService.ORG_UNIT)
+ {
+ this.HasChildren = true;
+ break;
+ }
+ }
+ this.Path = dirEntry.Path;
+ }
+ }
+
+ public IEnumerable GetChildrenOUs()
+ {
+ if (this.HasChildren)
+ {
+ var list = new List();
+ using (DirectoryEntry de = this.GetDirectoryEntry())
+ {
+ foreach (DirectoryEntry entry in de.Children)
+ {
+ if (entry.SchemaClassName == ConfigMgrWebService.ORG_UNIT)
+ list.Add(new ADOrganizationalUnit(entry));
+ }
+ }
+ return list;
+ }
+ else
+ return null;
+ }
+
+ private DirectoryEntry GetDirectoryEntry() => new DirectoryEntry(this.Path);
}
}
\ No newline at end of file
diff --git a/ConfigMgrWebService/ConfigMgrWebService.asmx.cs b/ConfigMgrWebService/ConfigMgrWebService.asmx.cs
index 644cce9..61a8cdc 100644
--- a/ConfigMgrWebService/ConfigMgrWebService.asmx.cs
+++ b/ConfigMgrWebService/ConfigMgrWebService.asmx.cs
@@ -1,26 +1,28 @@
-using System;
+using Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine;
+using Microsoft.ConfigurationManagement.ManagementProvider;
+using SqlExtensions;
+using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.DirectoryServices;
using System.Collections;
-using System.Diagnostics;
-using System.Web.Services;
-using System.Management;
-using System.Web.Configuration;
+using System.ComponentModel;
using System.Data.SqlClient;
-using Microsoft.ConfigurationManagement.ManagementProvider;
-using Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine;
-using System.Text;
using System.Data;
-using System.Reflection;
-using System.DirectoryServices.ActiveDirectory;
+using System.Diagnostics;
using System.DirectoryServices.AccountManagement;
+using System.DirectoryServices.ActiveDirectory;
+using System.DirectoryServices;
+using System.Globalization;
+using System.Linq;
+using System.Management;
using System.Net;
-using System.Security;
+using System.Reflection;
using System.Runtime.InteropServices;
-using System.Globalization;
-using SqlExtensions;
+using System.Security;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Web.Configuration;
+using System.Web.Services;
+using System.Web;
namespace SqlExtensions
{
@@ -41,9 +43,9 @@ namespace ConfigMgrWebService
{
[WebService(Name = "ConfigMgr WebService", Description = "Web service for ConfigMgr Current Branch developed by Nickolaj Andersen (1.7.0)", Namespace = "http://www.scconfigmgr.com")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
- [System.ComponentModel.ToolboxItem(false)]
+ [ToolboxItem(false)]
- public class ConfigMgrWebService : System.Web.Services.WebService
+ public partial class ConfigMgrWebService : WebService
{
//' Read required application settings from web.config
private string secretKey = WebConfigurationManager.AppSettings["SecretKey"];
@@ -2726,309 +2728,30 @@ public CMTaskSequence GetCMTaskSequence(string secret, string packageID)
}
[WebMethod(Description = "Move a computer in Active Directory to a specific organizational unit")]
- public bool SetADOrganizationalUnitForComputer(string secret, string organizationalUnitLocation, string computerName)
- {
- MethodBase method = MethodBase.GetCurrentMethod();
- MethodBegin(method);
-
- //' Variable for return value
- bool returnValue = false;
-
- //' Validate secret key
- if (secret == secretKey)
- {
- //' Log that secret key was accepted
- WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
-
- //' Determine if ldap prefix needs to be appended
- if (organizationalUnitLocation.StartsWith("LDAP://") == false)
- {
- organizationalUnitLocation = String.Format("LDAP://{0}", organizationalUnitLocation);
- }
-
- //' Get AD object distinguished name
- string currentDistinguishedName = GetADObject(computerName, ADObjectClass.Computer, ADObjectType.distinguishedName);
-
- if (!String.IsNullOrEmpty(currentDistinguishedName))
- {
- try
- {
- //' Move current object to new location
- DirectoryEntry currentObject = new DirectoryEntry(currentDistinguishedName);
- DirectoryEntry newLocation = new DirectoryEntry(organizationalUnitLocation);
- currentObject.MoveTo(newLocation, currentObject.Name);
-
- returnValue = true;
- }
- catch (Exception ex)
- {
- WriteEventLog(String.Format("An error occured when attempting to move Active Directory object. Error message: {0}", ex.Message), EventLogEntryType.Error);
- }
- }
- }
-
- MethodEnd(method);
- return returnValue;
- }
+ public bool SetADOrganizationalUnitForComputer(string secret, string organizationalUnitLocation, string computerName) =>
+ this.SetADOrganizationalUnitForComputerByDC(secret, organizationalUnitLocation, computerName, null);
[WebMethod(Description = "Set ManagedBy attribute for a specific computer with specified user name")]
- public bool SetADComputerManagedBy(string secret, string computerName, string userName)
- {
- MethodBase method = MethodBase.GetCurrentMethod();
- MethodBegin(method);
-
- //' Variable for return value
- bool returnValue = false;
-
- //' Validate secret key
- if (secret == secretKey)
- {
- //' Log that secret key was accepted
- WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
-
- //' Get AD computer and user object distinguished names
- string computerDistinguishedName = GetADObject(computerName, ADObjectClass.Computer, ADObjectType.distinguishedName);
- string userDistinguishedName = (GetADObject(userName, ADObjectClass.User, ADObjectType.distinguishedName)).Remove(0, 7);
-
- if (!String.IsNullOrEmpty(computerDistinguishedName) && !String.IsNullOrEmpty(userDistinguishedName))
- {
- try
- {
- //' Add user to ManagedBy attribute and commit
- DirectoryEntry computerEntry = new DirectoryEntry(computerDistinguishedName);
- computerEntry.Properties["ManagedBy"].Clear();
- computerEntry.Properties["ManagedBy"].Add(userDistinguishedName);
- computerEntry.CommitChanges();
-
- //' Dispose object
- computerEntry.Dispose();
-
- returnValue = true;
- }
- catch (Exception ex)
- {
- WriteEventLog(String.Format("An error occured when attempting to add a user as ManagedBy for a computer object in Active Directory. Error message: {0}", ex.Message), EventLogEntryType.Error);
- }
- }
- }
-
- MethodEnd(method);
- return returnValue;
- }
+ public bool SetADComputerManagedBy(string secret, string computerName, string userName) =>
+ this.SetADComputerManagedBy(secret, computerName, null);
[WebMethod(Description = "Add a computer in Active Directory to a specific group")]
- public bool AddADComputerToGroup(string secret, string groupName, string computerName)
- {
- MethodBase method = MethodBase.GetCurrentMethod();
- MethodBegin(method);
-
- //' Variable for return value
- bool returnValue = false;
-
- //' Validate secret key
- if (secret == secretKey)
- {
- //' Log that secret key was accepted
- WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
-
- //' Get AD object distinguished name for computer and group
- string computerDistinguishedName = (GetADObject(computerName, ADObjectClass.Computer, ADObjectType.distinguishedName)).Remove(0, 7);
- string groupDistinguishedName = GetADObject(groupName, ADObjectClass.Group, ADObjectType.distinguishedName);
-
- if (!String.IsNullOrEmpty(computerDistinguishedName) && !String.IsNullOrEmpty(groupDistinguishedName))
- {
- try
- {
- //' Add computer to group and commit
- DirectoryEntry groupEntry = new DirectoryEntry(groupDistinguishedName);
- groupEntry.Properties["member"].Add(computerDistinguishedName);
- groupEntry.CommitChanges();
-
- //' Dispose object
- groupEntry.Dispose();
-
- returnValue = true;
- }
- catch (Exception ex)
- {
- WriteEventLog(String.Format("An error occured when attempting to add a computer object in Active Directory to a group. Error message: {0}", ex.Message), EventLogEntryType.Error);
- }
- }
- }
-
- MethodEnd(method);
- return returnValue;
- }
+ public bool AddADComputerToGroup(string secret, string groupName, string computerName) =>
+ this.AddADComputerToGroupByDC(secret, groupName, computerName, null);
[WebMethod(Description = "Add a user in Active Directory to a specific group")]
- public bool AddADUserToGroup(string secret, string groupName, string userName)
- {
- MethodBase method = MethodBase.GetCurrentMethod();
- MethodBegin(method);
-
- //' Variable for return value
- bool returnValue = false;
-
- //' Validate secret key
- if (secret == secretKey)
- {
- //' Log that secret key was accepted
- WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
-
- //' Get AD object distinguished name for computer and group
- string userDistinguishedName = (GetADObject(userName, ADObjectClass.User, ADObjectType.distinguishedName)).Remove(0, 7);
- string groupDistinguishedName = GetADObject(groupName, ADObjectClass.Group, ADObjectType.distinguishedName);
-
- if (!String.IsNullOrEmpty(userDistinguishedName) && !String.IsNullOrEmpty(groupDistinguishedName))
- {
- try
- {
- //' Add user to group and commit
- DirectoryEntry groupEntry = new DirectoryEntry(groupDistinguishedName);
- groupEntry.Properties["member"].Add(userDistinguishedName);
- groupEntry.CommitChanges();
-
- //' Dispose object
- groupEntry.Dispose();
-
- returnValue = true;
- }
- catch (Exception ex)
- {
- WriteEventLog(String.Format("An error occured when attempting to add an user object in Active Directory to a group. Error message: {0}", ex.Message), EventLogEntryType.Error);
- }
- }
- }
-
- MethodEnd(method);
- return returnValue;
- }
+ public bool AddADUserToGroup(string secret, string groupName, string userName) =>
+ this.AddADUserToGroupByDC(secret, groupName, userName, null);
[WebMethod(Description = "Remove a computer in Active Directory from a specific group")]
- public bool RemoveADComputerFromGroup(string secret, string groupName, string computerName)
- {
- MethodBase method = MethodBase.GetCurrentMethod();
- MethodBegin(method);
-
- //' Set return value variable
- bool returnValue = false;
-
- //' Validate secret key
- if (secret == secretKey)
- {
- //' Log that secret key was accepted
- WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
-
- //' Get AD object distinguished name for computer and group
- string computerDistinguishedName = (GetADObject(computerName, ADObjectClass.Computer, ADObjectType.distinguishedName)).Remove(0,7);
- string groupDistinguishedName = GetADObject(groupName, ADObjectClass.Group, ADObjectType.distinguishedName);
-
- if (!String.IsNullOrEmpty(computerDistinguishedName) && !String.IsNullOrEmpty(groupDistinguishedName))
- {
- try
- {
- //' Check if computer is member of group
- DirectoryEntry groupEntry = new DirectoryEntry(groupDistinguishedName);
- List groupMembers = GetADGroupMemberList(groupEntry);
- bool memberOf = groupMembers.Contains(computerDistinguishedName);
- if (memberOf == true)
- {
- //' Remove computer from group and commit
- groupEntry.Properties["member"].Remove(computerDistinguishedName);
- groupEntry.CommitChanges();
-
- returnValue = true;
- }
-
- //' Dispose object
- groupEntry.Dispose();
- }
- catch (Exception ex)
- {
- WriteEventLog(String.Format("An error occured when attempting to remove a computer object in Active Directory from a group. Error message: {0}", ex.Message), EventLogEntryType.Error);
- }
- }
- }
-
- MethodEnd(method);
- return returnValue;
- }
+ public bool RemoveADComputerFromGroup(string secret, string groupName, string computerName) =>
+ this.RemoveADComputerFromGroupByDC(secret, groupName, computerName, null);
[WebMethod(Description = "Get all members of an Active Directory group")]
- public List GetADGroupMembers(string secret, string groupName)
- {
- MethodBase method = MethodBase.GetCurrentMethod();
- MethodBegin(method);
-
- //' Set return value variable
- List returnValue = new List();
-
- //' Validate secret key
- if (secret == secretKey)
- {
- //' Log that secret key was accepted
- WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
-
- //' Get AD group object
- string groupDistinguishedName = GetADObject(groupName, ADObjectClass.Group, ADObjectType.distinguishedName);
-
- if (!String.IsNullOrEmpty(groupDistinguishedName))
- {
- try
- {
- DirectoryEntry groupEntry = new DirectoryEntry(groupDistinguishedName);
- returnValue = GetADGroupMemberList(groupEntry);
- }
- catch (Exception ex)
- {
- WriteEventLog(String.Format("An error occured when retrieving Active Directory group members. Error message: {0}", ex.Message), EventLogEntryType.Error);
- }
- }
- }
-
- MethodEnd(method);
- return returnValue;
- }
+ public List GetADGroupMembers(string secret, string groupName) => this.GetADGroupMembersByDC(secret, groupName, null);
[WebMethod(Description = "Get Active Directory groups for a specific user")]
- public List GetADGroupsByUser(string secret, string userName)
- {
- MethodBase method = MethodBase.GetCurrentMethod();
- MethodBegin(method);
-
- //' Set return value variable
- List returnValue = new List();
-
- //' Validate secret key
- if (secret == secretKey)
- {
- //' Log that secret key was accepted
- WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
-
- try
- {
- //' Get AD user object
- string userDistinguishedName = GetADObject(userName, ADObjectClass.User, ADObjectType.distinguishedName);
-
- //' Get AD groups for user distinguished name
- ArrayList groupMemberships = new ArrayList();
- ArrayList groups = GetADAttributeValues("memberOf", userDistinguishedName, groupMemberships, true);
-
- foreach (string group in groups)
- {
- string attributeValue = GetADAttributeValue(group, "samAccountName");
- returnValue.Add(new ADGroup() { DistinguishedName = group, samAccountName = attributeValue });
- }
- }
- catch (Exception ex)
- {
- WriteEventLog($"An error occurred while retrieving Active Directory group memberships for user. Error message: { ex.Message }", EventLogEntryType.Error);
- }
- }
-
- MethodEnd(method);
- return returnValue;
- }
+ public List GetADGroupsByUser(string secret, string userName) => this.GetADGroupsByUserByDC(secret, userName, null);
[WebMethod(Description = "Set the description field for a computer in Active Directory")]
public bool SetADComputerDescription(string secret, string computerName, string description)
@@ -3244,82 +2967,19 @@ public bool GetADGroupMemberByComputer(string secret, string computerName, strin
}
[WebMethod(Description = "Check if a computer object exists in Active Directory")]
- public ADComputer GetADComputer(string secret, string computerName)
- {
- MethodBase method = MethodBase.GetCurrentMethod();
- MethodBegin(method);
-
- //' Instatiate return value variable
- ADComputer returnValue = new ADComputer();
-
- //' Validate secret key
- if (secret == secretKey)
- {
- //' Log that secret key was accepted
- WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
-
- //' Set empty value for search result
- SearchResult searchResult = null;
- DirectoryEntry directoryObject = null;
-
- //' Get default naming context of current domain
- string defaultNamingContext = GetADDefaultNamingContext();
- string currentDomain = String.Format("GC://{0}", defaultNamingContext);
-
- //' Construct directory entry for directory searcher
- DirectoryEntry domain = new DirectoryEntry(currentDomain);
- DirectorySearcher directorySearcher = new DirectorySearcher(domain)
- {
- Filter = String.Format("(&(objectClass=computer)((sAMAccountName={0}$)))", computerName)
- };
- directorySearcher.PropertiesToLoad.Add("distinguishedName");
- directorySearcher.PropertiesToLoad.Add("sAMAccountName");
- directorySearcher.PropertiesToLoad.Add("cn");
- directorySearcher.PropertiesToLoad.Add("dNSHostName");
-
- //' Invoke directory searcher
- try
- {
- searchResult = directorySearcher.FindOne();
- if (searchResult != null)
- {
- //' Get computer object from search result
- directoryObject = searchResult.GetDirectoryEntry();
-
- if (directoryObject != null)
- {
- returnValue.SamAccountName = (string)directoryObject.Properties["sAMAccountName"].Value;
- returnValue.CanonicalName = (string)directoryObject.Properties["cn"].Value;
- returnValue.DistinguishedName = (string)directoryObject.Properties["distinguishedName"].Value;
- returnValue.DnsHostName = (string)directoryObject.Properties["dNSHostName"].Value;
-
- // Dispose directory object
- directoryObject.Dispose();
- }
- }
- }
- catch (Exception ex)
- {
- WriteEventLog(String.Format("An error occured when attempting to locate Active Directory object. Error message: {0}", ex.Message), EventLogEntryType.Error);
- }
-
- //' Dispose objects
- directorySearcher.Dispose();
- domain.Dispose();
- }
-
- MethodEnd(method);
- return returnValue;
- }
+ public ADComputer GetADComputer(string secret, string computerName) => (ADComputer)this.GetADComputerByDC(secret, computerName, null);
[WebMethod(Description = "Remove a computer object from Active Directory (Prohibits removal of domain controllers)")]
- public bool RemoveADComputer(string secret, string samAccountName)
+ public bool RemoveADComputer(string secret, string samAccountName) => RemoveADComputerByDC(secret, samAccountName, null);
+
+ [WebMethod(Description = "Get the domain details for current domain")]
+ public ADDomain GetADDomain(string secret)
{
MethodBase method = MethodBase.GetCurrentMethod();
MethodBegin(method);
//' Instatiate return value variable
- bool returnValue = false;
+ ADDomain domain = null;
//' Validate secret key
if (secret == secretKey)
@@ -3327,100 +2987,29 @@ public bool RemoveADComputer(string secret, string samAccountName)
//' Log that secret key was accepted
WriteEventLog("Secret key was accepted", EventLogEntryType.Information);
- //' Construct list for all domain controllers
- List domainControllers = new List();
-
- //' Configure domain context
- Domain currentDomain = Domain.GetCurrentDomain();
- PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, currentDomain.Name, null, ContextOptions.Negotiate);
- WriteEventLog(String.Format("Using current domain for domain controller lookup: {0}", currentDomain.Name), EventLogEntryType.Information);
-
- //' Get a list of all domain controllers in the current domain
try
{
- foreach (DomainController domainController in currentDomain.DomainControllers)
- {
- //' Add domain controller distinguished name to list
- DirectoryEntry domainControllerEntry = domainController.GetDirectoryEntry();
- string domainControllerName = (string)domainControllerEntry.Properties["name"].Value;
-
- //' Debug
- WriteEventLog(String.Format("Detected domain controller name: {0}", domainControllerName), EventLogEntryType.Information);
-
- ComputerPrincipal dcPrincipal = ComputerPrincipal.FindByIdentity(principalContext, IdentityType.Name, domainControllerName);
- domainControllers.Add(dcPrincipal.DistinguishedName);
-
- //' Dispose objects
- domainControllerEntry.Dispose();
- dcPrincipal.Dispose();
- }
+ DirectoryContext ctx = new DirectoryContext(DirectoryContextType.Domain);
+ domain = Domain.GetDomain(ctx);
}
catch (Exception ex)
{
- WriteEventLog(String.Format("Unable to detect domain controllers in current domain. Error message: {0}", ex.Message), EventLogEntryType.Error);
- returnValue = false;
- }
-
- if (domainControllers.Count >= 1)
- {
- //' Get computer principal eligible for removal
- ComputerPrincipal computerPrincipal = ComputerPrincipal.FindByIdentity(principalContext, samAccountName);
-
- if (computerPrincipal != null)
- {
- if (domainControllers.Contains(computerPrincipal.DistinguishedName) == false)
- {
- try
- {
- //' Delete computer object including any leaf objects
- DirectoryEntry subEntry = (DirectoryEntry)computerPrincipal.GetUnderlyingObject();
-
- if (subEntry != null)
- {
- subEntry.DeleteTree();
- subEntry.CommitChanges();
-
- WriteEventLog(String.Format("Successfully removed computer object named '{0}'", computerPrincipal.Name), EventLogEntryType.Information);
- }
-
- //' Dispose object
- subEntry.Dispose();
-
- returnValue = true;
- }
- catch (Exception ex)
- {
- WriteEventLog(String.Format("Unable to remove computer object '{0}'. Error message: {1}", samAccountName, ex.Message), EventLogEntryType.Error);
- returnValue = false;
- }
- }
-
- //' Dispose object
- computerPrincipal.Dispose();
- }
- else
- {
- WriteEventLog(String.Format("Unable to find a computer object named '{0}'", computerPrincipal.Name), EventLogEntryType.Information);
- }
+ WriteEventLog($"An error occurred while querying for Active Directory domain details. Error message: { ex.Message } ", EventLogEntryType.Error);
}
-
- //' Dispose objects
- currentDomain.Dispose();
- principalContext.Dispose();
}
MethodEnd(method);
- return returnValue;
+ return domain;
}
- [WebMethod(Description = "Get the domain details for current domain")]
- public ADDomain GetADDomain(string secret)
+ [WebMethod(Description = "Get the domain details for the specified domain")]
+ public ADDomain GetADDomainByName(string secret, string domainName)
{
MethodBase method = MethodBase.GetCurrentMethod();
MethodBegin(method);
//' Instatiate return value variable
- ADDomain domain = new ADDomain();
+ ADDomain domain = null;
//' Validate secret key
if (secret == secretKey)
@@ -3430,8 +3019,8 @@ public ADDomain GetADDomain(string secret)
try
{
- domain.DefaultNamingContext = GetADDefaultNamingContext();
- domain.DomainName = GetADDomainName();
+ DirectoryContext ctx = new DirectoryContext(DirectoryContextType.Domain, domainName);
+ domain = Domain.GetDomain(ctx);
}
catch (Exception ex)
{
@@ -3467,42 +3056,13 @@ public List GetADOrganizationalUnits(string secret, string
}
//' Get the base OU directory entry and start a one level search
- using (DirectorySearcher directorySearcher = new DirectorySearcher(new DirectoryEntry(distinguishedName)))
+ using (DirectorySearcher directorySearcher = new DirectorySearcher(new DirectoryEntry(distinguishedName),
+ "(objectCategory=organizationalUnit)", ORG_UNIT_PROPERTIES, SearchScope.Subtree))
{
- //' Define filter options for searcher
- directorySearcher.Filter = "(objectCategory=organizationalUnit)";
- directorySearcher.SearchScope = SearchScope.OneLevel;
- directorySearcher.PropertiesToLoad.Add("name");
- directorySearcher.PropertiesToLoad.Add("path");
- //' Enumerate top level containers
foreach (SearchResult container in directorySearcher.FindAll())
{
- //' Search for children
- SearchResult childResult = null;
- using (DirectorySearcher childDirectorySearcher = new DirectorySearcher(new DirectoryEntry(container.Path)))
- {
- //' Define filter options for searcher
- childDirectorySearcher.Filter = "(objectCategory=organizationalUnit)";
- childDirectorySearcher.SearchScope = SearchScope.OneLevel;
- childDirectorySearcher.PropertiesToLoad.Add("name");
- childResult = childDirectorySearcher.FindOne();
- }
-
- //' Determine if child exist
- bool childPresence = false;
- if (childResult != null)
- {
- childPresence = true;
- }
-
- //' Construct a new object to hold container information
- ADOrganizationalUnit orgUnit = new ADOrganizationalUnit()
- {
- HasChildren = childPresence,
- Name = container.Properties["name"][0].ToString(),
- DistinguishedName = container.Path
- };
+ ADOrganizationalUnit orgUnit = new ADOrganizationalUnit(container.GetDirectoryEntry());
containers.Add(orgUnit);
}
}
@@ -5662,70 +5222,7 @@ private string GetADDomainName()
return Domain.GetComputerDomain().Name;
}
- private string GetADObject(string name, ADObjectClass objectClass, ADObjectType objectType)
- {
- //' Set empty value for return object and search result
- string returnValue = string.Empty;
- SearchResult searchResult = null;
-
- //' Get default naming context of current domain
- string defaultNamingContext = GetADDefaultNamingContext();
- string currentDomain = String.Format("LDAP://{0}", defaultNamingContext);
-
- //' Construct directory entry for directory searcher
- DirectoryEntry domain = new DirectoryEntry(currentDomain);
- DirectorySearcher directorySearcher = new DirectorySearcher(domain);
- directorySearcher.PropertiesToLoad.Add("distinguishedName");
-
- switch (objectClass)
- {
- case ADObjectClass.DomainController:
- directorySearcher.Filter = String.Format("(&(objectClass=computer)((dNSHostName={0})))", name);
- break;
- case ADObjectClass.Computer:
- directorySearcher.Filter = String.Format("(&(objectClass=computer)((sAMAccountName={0}$)))", name);
- break;
- case ADObjectClass.Group:
- directorySearcher.Filter = String.Format("(&(objectClass=group)((sAMAccountName={0})))", name);
- break;
- case ADObjectClass.User:
- directorySearcher.Filter = String.Format("(&(objectClass=user)((sAMAccountName={0})))", name);
- break;
- }
-
- //' Invoke directory searcher
- try
- {
- searchResult = directorySearcher.FindOne();
- }
- catch (Exception ex)
- {
- WriteEventLog(String.Format("An error occured when attempting to locate Active Directory object. Error message: {0}", ex.Message), EventLogEntryType.Error);
- return returnValue;
- }
-
- //' Return selected object type value
- if (searchResult != null)
- {
- DirectoryEntry directoryObject = searchResult.GetDirectoryEntry();
-
- if (objectType.Equals(ADObjectType.objectGuid))
- {
- returnValue = directoryObject.Guid.ToString();
- }
-
- if (objectType.Equals(ADObjectType.distinguishedName))
- {
- returnValue = String.Format("LDAP://{0}", directoryObject.Properties["distinguishedName"].Value);
- }
- }
-
- //' Dispose objects
- directorySearcher.Dispose();
- domain.Dispose();
-
- return returnValue;
- }
+
///
/// Code adjusted from: https://itq.nl/get-more-than-1500-members-from-an-active-directory-group/
@@ -5791,13 +5288,18 @@ private List GetADGroupMemberList(DirectoryEntry groupEntry)
///
/// Check if user if member of a group including nested group - https://stackoverflow.com/questions/5312744/how-to-determine-all-the-groups-a-user-belongs-to-including-nested-groups-in-a/31725157#31725157
///
- private bool GetADGroupNestedMemberOf(Principal principal, GroupPrincipal group)
+ private bool GetADGroupNestedMemberOf(Principal principal, GroupPrincipal group, string domainController = null)
{
//' LDAP query for memberOf including nested
string filter = String.Format("(&(sAMAccountName={0})(memberOf:1.2.840.113556.1.4.1941:={1}))", principal.SamAccountName, group.DistinguishedName);
WriteEventLog(String.Format("Using LDAP filter for user validation: {0}", filter), EventLogEntryType.Information);
DirectorySearcher searcher = new DirectorySearcher(filter);
+ string ldapString = string.IsNullOrEmpty(domainController)
+ ? string.Format("LDAP://{0}", this.GetADDefaultNamingContext())
+ : string.Format("LDAP://{0}/{1}", domainController, this.GetADDefaultNamingContext());
+
+ searcher.SearchRoot = new DirectoryEntry(ldapString);
SearchResult result = searcher.FindOne();
return result != null;
@@ -5879,6 +5381,72 @@ public static Dictionary GetADSubnets(string forestName)
return subnetList;
}
+ private ComputerPrincipal FindComputerObject(string name, string dc, out string respondingDC)
+ {
+ ComputerPrincipal returnValue = null;
+ string realDC = null;
+ using (Domain domain = Domain.GetComputerDomain())
+ {
+ realDC = GetRespondingDomainController(domain, dc);
+ PrincipalContext prinCtx = new PrincipalContext(ContextType.Domain, realDC, null, ContextOptions.Negotiate);
+ WriteEventLog(string.Format("Using the following domain controller for the computer lookup: {0}", realDC), EventLogEntryType.Information);
+
+ returnValue = ComputerPrincipal.FindByIdentity(prinCtx, name);
+ }
+ respondingDC = realDC;
+ return returnValue;
+ }
+
+ private Domain GetDomainFromDN(string ouPath)
+ {
+ string[] dcStrings = ouPath.Split(
+ new string[1] { "," }, StringSplitOptions.RemoveEmptyEntries).Where(
+ x => x.StartsWith("DC=", StringComparison.CurrentCultureIgnoreCase)).ToArray();
+
+ string[] cutOut = new string[dcStrings.Length];
+ for (int i = 0; i < dcStrings.Length; i++)
+ {
+ cutOut[i] = Regex.Match(dcStrings[i], @"^[D|d][C|c]\=(\S{1,})").Groups[1].Value;
+ }
+ string fqdn = string.Join(".", cutOut);
+ return GetDomainFromString(fqdn);
+ }
+
+ private Domain GetDomainFromString(string domainName)
+ {
+ DirectoryContext ctx = string.IsNullOrEmpty(domainName)
+ ? new DirectoryContext(DirectoryContextType.Domain)
+ : new DirectoryContext(DirectoryContextType.Domain, domainName);
+
+ Domain retDomain = Domain.GetDomain(ctx);
+ return retDomain;
+ }
+
+ private string GetLDAPString(ADDomain domain, string dc, out string respondingDC)
+ {
+ string format = "LDAP://{0}/{1}";
+ respondingDC = GetRespondingDomainController(domain, dc);
+ string ldapStr = string.Format(format, respondingDC, domain.DefaultNamingContext);
+ return ldapStr;
+ }
+
+ private string GetRespondingDomainController(Domain domain, string dc)
+ {
+ string retName = null;
+ if (string.IsNullOrEmpty(dc))
+ {
+ using (DomainController domCon = domain.FindDomainController())
+ {
+ retName = domCon.Name;
+ }
+ }
+ else retName = !dc.Contains(domain.Name)
+ ? string.Format("{0}.{1}", dc, domain.Name)
+ : dc;
+
+ return retName;
+ }
+
private static int FindMissingNumber(List list)
{
//' Missing number return value
diff --git a/ConfigMgrWebService/ConfigMgrWebService.csproj b/ConfigMgrWebService/ConfigMgrWebService.csproj
index e5a83af..ad4991a 100644
--- a/ConfigMgrWebService/ConfigMgrWebService.csproj
+++ b/ConfigMgrWebService/ConfigMgrWebService.csproj
@@ -10,7 +10,6 @@
2.0
{9A0DC841-CDB0-4B6D-B1B4-42E307A7675C}
- {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
Library
Properties
ConfigMgrWebService
@@ -44,17 +43,15 @@
4
-
- False
- ..\References\AdminUI.WqlQueryEngine.dll
+
+ Assemblies\AdminUI.WqlQueryEngine.dll
..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll
True
-
- False
- ..\References\Microsoft.ConfigurationManagement.ManagementProvider.dll
+
+ Assemblies\Microsoft.ConfigurationManagement.ManagementProvider.dll
@@ -93,9 +90,24 @@
+
+
+
+
+ Component
+
+
+
+
+ Component
+
+
+
+
+
@@ -103,6 +115,9 @@
+
+ Component
+
@@ -116,6 +131,9 @@
ConfigMgrWebService.asmx
+
+
+
10.0
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
@@ -126,24 +144,7 @@
-
-
-
-
- True
- True
- 60167
- /
- http://localhost:60167/
- False
- False
-
-
- False
-
-
-
-
+
This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
diff --git a/ConfigMgrWebService/Constants.cs b/ConfigMgrWebService/Constants.cs
new file mode 100644
index 0000000..7c82caa
--- /dev/null
+++ b/ConfigMgrWebService/Constants.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace ConfigMgrWebService
+{
+ public partial class ConfigMgrWebService
+ {
+ internal const string COMMON_NAME = "cn";
+ internal const string COMPUTER = "computer";
+ internal const string DISTINGUISHED_NAME = "distinguishedName";
+ internal const string DNS_HOST_NAME = "dNSHostName";
+ internal const string NAME = "name";
+ internal const string ORG_UNIT = "organizationalUnit";
+ internal const string PATH = "path";
+ internal const string SAM_ACCOUNT_NAME = "sAMAccountName";
+
+ private static string[] COMPUTER_PROPERTIES => new string[4]
+ {
+ COMMON_NAME, DISTINGUISHED_NAME, DNS_HOST_NAME, SAM_ACCOUNT_NAME
+ };
+
+ private static string[] GROUP_PROPERTIES => new string[2]
+ {
+ DISTINGUISHED_NAME, SAM_ACCOUNT_NAME
+ };
+
+ private static string[] ORG_UNIT_PROPERTIES => new string[3]
+ {
+ DISTINGUISHED_NAME, NAME, PATH
+ };
+ }
+}
\ No newline at end of file