Dlaczego ostatnio tak rozpisywałem się odnośnie zarządzania Active Directory z poziomu PowerShella ? Mianowicie przyszło mi zmierzyć się z drobnym projektem, którego celem było zintegrowanie dwóch niezależnych od siebie systemów. Nie mogę podać za wiele szczegółów, ale sytuacja wyglądała następująco: system A musiał synchronizować dane odnośnie kont użytkowników zawartych w bazie danych opartych o MS SQL, z systemem B opartym o pracę na kontrolerze domeny.
Może się wydawać skomplikowane rozwiązanie niemniej dla PowerShella to żadna przeszkoda. Oczywiście można było tutaj skorzystać z gotowych modułów do zarządzania SQL’em oraz Active Directory, ale odebrało by to całą zabawę związaną ze stworzeniem własnego rozwiązania 🙂
Zatem jak więc można rozwiązać powyższy problem ?? Najpierw tworzymy sobie funkcję pozwalającą nam skorzystać z informacji zawartych w bazie danych. Do tego celu tworzymy sobie connection string w celu nawiązania połączenia z bazą danych:
param( [string] $dataSource = "TESTSERVER", [string] $database = "TESTOWA", [string] $sqlCommand ) $connectionString = "Provider=sqloledb; " + "Data Source=$dataSource; " + "Initial Catalog=$database; " + "Integrated Security=SSPI;"
Następnie tworzymy obiekt połączenia oraz obiekt zapytania do bazy:
$connection = New-Object System.Data.OleDb.OleDbConnection $connectionString $command = New-Object System.Data.OleDb.OleDbCommand $sqlCommand,$connection
Otwieramy połączenie, tworzymy obiekt OleDbDataAdapter oraz DataSet i wysyłamy zapytanie do serwera:
$connection.Open() $adapter = New-Object System.Data.OleDb.OleDbDataAdapter $command $dataset = New-Object System.Data.DataSet [void] $adapter.Fill($dataSet) $connection.Close()
Ostatecznie zwracamy wynik zapytania:
$dataSet.Tables | Select-Object -Expand Rows
Pobieramy informacje za pomocą naszej funkcji:
$Users = Get-SqlData –sqlCommand “Select login, imie, nazwisko From Users”
Gdy pobierzemy już konieczne informacje z bazy danych przystąpmy do synchronzacji ich z kontrolerem domeny.
Tworzymy drugą funckję w której najpierw podłączamy się do kontrolera.
param( $Users ) $LDAP = ([ADSI]'LDAP://rootDSE').defaultNamingContext.value $ADObj = [ADSI]"LDAP://CN=Users,$LDAP"
I dla każdego z użytkowników dokonujemy synchronizacji danych:
ForEach($User in $Users) { if(!([ADSI]"LDAP://CN=$($User.login),CN=Users,$LDAP").distinguishedName) { $NewCN = $ADObj.Create("User", "CN=$($User.login)") $NewCN.put("givenName",$($User.imie)) $NewCN.put("sn",$($User.nazwisko)) #ewentualnie synchronizujemy inne potrzebne atrybuty $NewCN.SetInfo() } else { $CurrentCN = [ADSI]LDAP://CN=$($User.login),CN=Users,$LDAP $CurrentCN.put("givenName",$($User.imie)) $CurrentCN.put("sn",$($User.nazwisko)) $CurrentCN.SetInfo() } }
Jest to tylko i wyłącznie zarys, a wręcz bym powiedział ogólna koncepcja podejścia do problemu. Niemniej jednak powinna być na tyle zrozumiała, aby pomóc w jego rozwiązaniu.
Cały kod powinien wyglądać następująco:
function Get-SqlData { param( [string] $dataSource = "TESTSERVER", [string] $database = "TESTOWA", [string] $sqlCommand ) $connectionString = "Provider=sqloledb; " + "Data Source=$dataSource; " + "Initial Catalog=$database; " + "Integrated Security=SSPI; " $connection = New-Object System.Data.OleDb.OleDbConnection $connectionString $command = New-Object System.Data.OleDb.OleDbCommand $sqlCommand,$connection $connection.Open() $adapter = New-Object System.Data.OleDb.OleDbDataAdapter $command $dataset = New-Object System.Data.DataSet [void] $adapter.Fill($dataSet) $connection.Close() $dataSet.Tables | Select-Object -Expand Rows } function Set-ADSynch { param( $Users ) $LDAP = ([ADSI]'LDAP://rootDSE').defaultNamingContext.value $ADObj = [ADSI]LDAP://CN=Users,$LDAP ForEach($User in $Users) { if(!([ADSI]"LDAP://CN=$($User.login),CN=Users,$LDAP").distinguishedName) { $NewCN = $ADObj.Create("User", "CN=$($User.login)") $NewCN.put("givenName",$($User.imie)) $NewCN.put("sn",$($User.nazwisko)) #ewentualnie synchronizujemy inne potrzebne atrybuty $NewCN.SetInfo() } else { $CurrentCN = [ADSI]LDAP://CN=$($User.login),CN=Users,$LDAP $CurrentCN.put("givenName",$($User.imie)) $CurrentCN.put("sn",$($User.nazwisko)) $CurrentCN.SetInfo() } } } $Users = Get-SqlData –sqlCommand “Select login, imie, nazwisko From Users” Set-ADSynch –Users $Users