From 68dfc365ee99f2a516d2397ae6c4f14fc4f7b689 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 8 Nov 2019 14:52:15 +0100 Subject: [PATCH] add surname and guid to users, filter users and groups --- GUIs.Test.ADSyncTest/Form1.vb | 4 +- .../ActiveDirectoryInterface.vb | 69 +++++++++++++++---- Modules.Jobs/EDMI/ADSync/ADSyncArgs.vb | 7 ++ Modules.Jobs/EDMI/ADSync/ADSyncJob.vb | 6 +- Service.JobRunner/Jobs/ADJob.vb | 8 +++ 5 files changed, 75 insertions(+), 19 deletions(-) diff --git a/GUIs.Test.ADSyncTest/Form1.vb b/GUIs.Test.ADSyncTest/Form1.vb index 79686b2f..a5c6a936 100644 --- a/GUIs.Test.ADSyncTest/Form1.vb +++ b/GUIs.Test.ADSyncTest/Form1.vb @@ -19,14 +19,14 @@ Public Class Form1 _firebird = New Firebird(_logConfig, "172.24.12.41", "172.24.12.41:E:\DB\Firebird\Databases\DD_ICM.fdb", "sysdba", "dd") _sql = New MSSQLServer(_logConfig, "Server=172.24.12.41\tests;Database=DD_ECM_TEST;User Id=sa; Password=dd") - _sync = New ActiveDirectoryInterface(_logConfig, Nothing, _sql) + _sync = New ActiveDirectoryInterface(_logConfig) _sync.Authenticate() End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim oGroup As String = ListBox1.SelectedItem Dim oAttributeMappings = GetAttributeMappings() - _sync.SyncUsersForGroup(oGroup, oAttributeMappings) + _sync.SyncUsersForGroup(oGroup, oAttributeMappings, _firebird, _sql) End Sub Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click diff --git a/Modules.Interfaces/ActiveDirectoryInterface.vb b/Modules.Interfaces/ActiveDirectoryInterface.vb index 12a24afa..69a0b868 100644 --- a/Modules.Interfaces/ActiveDirectoryInterface.vb +++ b/Modules.Interfaces/ActiveDirectoryInterface.vb @@ -1,5 +1,6 @@ Imports System.DirectoryServices Imports System.DirectoryServices.AccountManagement +Imports System.Text.RegularExpressions Imports DigitalData.Modules.Database Imports DigitalData.Modules.Logging @@ -11,6 +12,7 @@ Public Class ActiveDirectoryInterface Private ReadOnly _mssql As MSSQLServer Private ReadOnly _rootPath As String + Private _rootNode As DirectoryEntry Private Const SEARCH_LIMIT = 50000 @@ -23,31 +25,31 @@ Public Class ActiveDirectoryInterface Private Const NAME = "name" Private Const OBJECTCATEGORY = "objectCategory" - Public Sub New(LogConfig As LogConfig, Firebird As Firebird, MSSQL As MSSQLServer, Optional RootPath As String = Nothing) + Public Const DEFAULT_USER_FILTER = "(&(objectClass=user)(samAccountName=@SAMACCOUNTNAME)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))" + Public Const DEFAULT_GROUP_FILTER = "(&(objectClass=group) (samAccountName=*))" + + Public Sub New(LogConfig As LogConfig, Optional RootPath As String = Nothing) _logConfig = LogConfig _logger = _logConfig.GetLogger() - _firebird = Firebird - _mssql = MSSQL If RootPath Is Nothing Then _rootPath = $"LDAP://{Environment.UserDomainName}" Else _rootPath = RootPath End If - _logger.Info("Using RootPath {0}", _rootPath) End Sub - Public Function SyncUsersForGroup(GroupName As String) As List(Of ADUser) + Public Function SyncUsersForGroup(GroupName As String, Firebird As Firebird, MSSQL As MSSQLServer) As List(Of ADUser) Try - Return SyncUsersForGroup(GroupName, New List(Of AttributeMapping)) + Return SyncUsersForGroup(GroupName, New List(Of AttributeMapping), Firebird, MSSQL) Catch ex As Exception _logger.Error(ex) Return Nothing End Try End Function - Public Function SyncUsersForGroup(GroupName As String, AttributeMappings As List(Of AttributeMapping)) As List(Of ADUser) + Public Function SyncUsersForGroup(GroupName As String, AttributeMappings As List(Of AttributeMapping), Firebird As Firebird, MSSQL As MSSQLServer, Optional Filter As String = DEFAULT_USER_FILTER) As List(Of ADUser) Dim oUsers As New List(Of ADUser) Dim oSyncedUsers As New List(Of ADUser) Dim oGroupId As Int64 = Nothing @@ -58,7 +60,7 @@ Public Class ActiveDirectoryInterface Try _logger.Debug("Fetching users from ActiveDirectory") - oUsers = ListUsers(GroupName, AttributeMappings) + oUsers = ListUsers(GroupName, AttributeMappings, Filter) _logger.Debug("Found {0} users", oUsers.Count) Catch ex As Exception _logger.Error(ex) @@ -116,10 +118,12 @@ Public Class ActiveDirectoryInterface End Try End Function - Public Function ListGroups(Optional Query As String = "(&(objectClass=group) (samAccountName=*))") As List(Of ADGroup) + Public Function ListGroups(Optional Query As String = DEFAULT_GROUP_FILTER) As List(Of ADGroup) Return ListGroups(_rootNode, Query) End Function - Public Function ListGroups(RootNode As DirectoryEntry, Optional Query As String = "(&(objectClass=group) (samAccountName=*))") As List(Of ADGroup) + + + Public Function ListGroups(RootNode As DirectoryEntry, Optional Query As String = DEFAULT_GROUP_FILTER) As List(Of ADGroup) Dim oGroups As New List(Of ADGroup) Try @@ -139,11 +143,11 @@ Public Class ActiveDirectoryInterface End Try End Function - Public Function ListUsers(GroupName As String) As List(Of ADUser) - Return ListUsers(GroupName, New List(Of AttributeMapping)) + Public Function ListUsers(GroupName As String, Optional Filter As String = DEFAULT_USER_FILTER) As List(Of ADUser) + Return ListUsers(GroupName, New List(Of AttributeMapping), Filter) End Function - Public Function ListUsers(GroupName As String, AttributeMappings As List(Of AttributeMapping)) As List(Of ADUser) + Public Function ListUsers(GroupName As String, AttributeMappings As List(Of AttributeMapping), Optional Filter As String = DEFAULT_USER_FILTER) As List(Of ADUser) Dim oUsers As New List(Of ADUser) Try @@ -161,9 +165,14 @@ Public Class ActiveDirectoryInterface Try If TypeOf oMember Is UserPrincipal Then Dim oUser As UserPrincipal = DirectCast(oMember, UserPrincipal) - Dim oUserEx As UserPrincipalEx = UserPrincipalEx.FindByIdentity(oContext, oUser.SamAccountName) + Dim oUserEx As UserPrincipalEx = UserPrincipalEx.FindByIdentity(oContext, IdentityType.SamAccountName, oUser.SamAccountName) Dim oCustomAttributes As New List(Of ADUser.CustomAttribute) + If FindUserWithFilter(oUserEx, Filter) = False Then + _logger.Debug("User '{0}' was skipped out due to user filter.", oUserEx.SamAccountName) + Continue For + End If + ' TODO: Figure out why oUserEx can be nothing for certain users If oUserEx IsNot Nothing Then For Each oMap As AttributeMapping In AttributeMappings @@ -191,6 +200,8 @@ Public Class ActiveDirectoryInterface .samAccountName = oUser.SamAccountName, .Middlename = oUser.MiddleName, .GivenName = oUser.GivenName, + .Surname = oUser.Surname, + .GUID = oUser.Guid, .Email = oUser.EmailAddress, .CustomAttributes = oCustomAttributes } @@ -213,6 +224,36 @@ Public Class ActiveDirectoryInterface End Try End Function + Public Function FindUserWithFilter(User As UserPrincipalEx, Filter As String) As Boolean + Dim oRootPath = String.Join(","c, User.DistinguishedName.Split(","c).Skip(1)) + Dim oPlaceholder = "@SAMACCOUNTNAME" + Dim oEntry As New DirectoryEntry("LDAP://" & oRootPath) With { + .Username = Nothing, + .Password = Nothing, + .AuthenticationType = AuthenticationTypes.Secure + } + + If Filter = String.Empty Then + _logger.Warn("FindUserWithFilter: Filter was empty, returning True for User {0}", User.SamAccountName) + Return True + End If + + If Filter.Contains(oPlaceholder) Then + Filter = Filter.Replace(oPlaceholder, User.SamAccountName) + Else + _logger.Warn("FindUserWithFilter: Placeholder '{0}' was not found in filter. Results may not be correct.") + End If + + Dim oSearcher As New DirectorySearcher(oEntry, Filter) + Dim oResult = oSearcher.FindOne() + + If oResult Is Nothing Then + Return False + Else + Return True + End If + End Function + Private Function GetRootNode() As DirectoryEntry Dim oEntry As New DirectoryEntry(_rootPath) With { .AuthenticationType = AuthenticationTypes.Secure, diff --git a/Modules.Jobs/EDMI/ADSync/ADSyncArgs.vb b/Modules.Jobs/EDMI/ADSync/ADSyncArgs.vb index 86458756..d98716de 100644 --- a/Modules.Jobs/EDMI/ADSync/ADSyncArgs.vb +++ b/Modules.Jobs/EDMI/ADSync/ADSyncArgs.vb @@ -1,7 +1,14 @@ Public Class ADSyncArgs Inherits JobArgs + ''' + ''' LDAP URI that acts as the root node of searches, ex: LDAP://DIGITALDATA + ''' Public RootPath As String + + Public UserFilter As String + Public GroupFilter As String + Public DisableFirebird As String Public DisableMSSQL As String End Class diff --git a/Modules.Jobs/EDMI/ADSync/ADSyncJob.vb b/Modules.Jobs/EDMI/ADSync/ADSyncJob.vb index 5bec43ff..030ede25 100644 --- a/Modules.Jobs/EDMI/ADSync/ADSyncJob.vb +++ b/Modules.Jobs/EDMI/ADSync/ADSyncJob.vb @@ -16,7 +16,7 @@ Public Class ADSyncJob Dim oJobName As String = [GetType]().Name Try - Dim oSync = New ActiveDirectoryInterface(_LogConfig, _Firebird, _MSSQL, Arguments.RootPath) + Dim oSync = New ActiveDirectoryInterface(_LogConfig, Arguments.RootPath) _Logger.Info("Running job {0}", oJobName) @@ -25,13 +25,13 @@ Public Class ADSyncJob Exit Sub End If - Dim oGroups = GetGroups() + Dim oGroups = GetGroups(Arguments.GroupFilter) Dim oAttributeMappings = GetAttributeMappings() _Logger.Debug("Found {0} Groups", oGroups) For Each oGroup In oGroups _Logger.Debug("Syncing Group {0}", oGroup) - Dim oSyncedUsers = oSync.SyncUsersForGroup(oGroup, oAttributeMappings) + Dim oSyncedUsers = oSync.SyncUsersForGroup(oGroup, oAttributeMappings, _Firebird, _MSSQL, Arguments.UserFilter) If oSyncedUsers Is Nothing Then _Logger.Warn("Group {0} could not be synced!", oGroup) diff --git a/Service.JobRunner/Jobs/ADJob.vb b/Service.JobRunner/Jobs/ADJob.vb index 9a94c2e6..f85ca378 100644 --- a/Service.JobRunner/Jobs/ADJob.vb +++ b/Service.JobRunner/Jobs/ADJob.vb @@ -17,6 +17,14 @@ Public Class ADJob oADJobArgs.RootPath = oArgs.Item("RootPath") End If + If oArgs.ContainsKey("UserFilter") Then + oADJobArgs.UserFilter = oArgs.Item("UserFilter") + End If + + If oArgs.ContainsKey("GroupFilter") Then + oADJobArgs.GroupFilter = oArgs.Item("GroupFilter") + End If + If oArgs.ContainsKey("DisableFirebird") AndAlso oArgs.Item("DisableFirebird") = "True" Then oFirebird = Nothing End If