AD objektumok kezelése LDAP osztályokkal

Ebben a 2.21 -es fejezetben az előzőekben az ADSI interfészt használtuk az AD adatok kezelésére. Ezt viszonylag könnyű használni, sok minden a háttérben automatikusan lezajlik, mint például a kapcsolódás a tartományvezérlőhöz és az autentikáció. Néha jól jöhet, ha ezeket is kézben tudjuk tartani és mi magunk kezelhetjük. A másik eset, amikor „kinőjük” az ADSI-t, amikor nem egyszerű adattípust tároló attribútumokat szeretnénk kezelni. Nézzünk erre egy példát, a felhasználómnak van egy maxStorage nevű attribútuma:

$o = [ADSI] "LDAP://CN=Vegetári János,OU=Test,DC=ps,DC=local"

$o.Properties | ft -Property propertyname, value

 Ennek eredménye:

PropertyName          Value                                             

------------          -----                                             

objectClass           {top, person, organizationalPerson, user}         

cn                    Vegetári János                                    

sn                    Vegetári                                          

givenName             János                                             

distinguishedName     CN=Vegetári János,OU=Test,DC=ps,DC=local          

instanceType          4                                                 

whenCreated           2018. 10. 21. 20:52:56                            

whenChanged           2018. 10. 21. 21:12:56                            

displayName           Vegetári János                                    

uSNCreated            System.__ComObject                                

uSNChanged            System.__ComObject                                

nTSecurityDescriptor  System.__ComObject                                

name                  Vegetári János                                    

objectGUID            {237, 100, 82, 153...}                            

userAccountControl    512                                                

badPwdCount           0                                                 

codePage              0                                                 

countryCode           0                                                 

badPasswordTime       System.__ComObject                                

lastLogoff            System.__ComObject                                

lastLogon             System.__ComObject                                

maxStorage            System.__ComObject                                 

pwdLastSet            System.__ComObject                                

primaryGroupID        513                                               

objectSid             {1, 5, 0, 0...}                                   

accountExpires        System.__ComObject                                

logonCount            0                                                 

sAMAccountName        vj                                                

sAMAccountType        805306368                                          

userPrincipalName     vj@ps.local                                       

objectCategory        CN=Person,CN=Schema,CN=Configuration,DC=ps,DC=local

dSCorePropagationData 1601. 01. 01. 0:00:00                             

Látható, hogy jónéhány esetben csak annyit látunk, hogy System.__ComObject. És nem csak kiolvasni nem tudjuk, hanem beállítani sem ezeket az értékeket:

PS C:\Users\Administrator> $o.maxStorage = 1234

 

PS C:\Users\Administrator> $o.maxStorage

1234

 

PS C:\Users\Administrator> $o.put()

Exception calling "put" with "0" argument(s): "Number of parameters specified does not match the expected number."

At line:1 char:1

+ $o.put()

+ ~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI

Ez a maxStorage attribútum Large Integer típusú, ahogy ezt a Schema Management eszközben is látjuk:

130 . ábra A maxStorage attribútum a Schema Manager-ben

Próbáltam felderíteni, hogy pontosan itt mit is kellene betölteni az attribútumba, olyasmit találtam, hogy magas bájt és alacsony bájt tömbjét, de nem nagyon jutottam dűlőre. Viszont az LDAP osztállyal viszonylag egyszerűen tudjuk ezt is kezelni.

Elsőként építsük fel a kapcsolatot:

try{

    [void] [System.DirectoryServices.Protocols.LdapConnection]

}

catch{

    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols")

}

 

$c = New-Object -TypeName System.DirectoryServices.Protocols.LdapConnection -ArgumentList "ps.local:389"

$c.SessionOptions.SecureSocketLayer = $false

$c.SessionOptions.ProtocolVersion = 3

$c.AuthType = [System.DirectoryServices.Protocols.AuthType]::Kerberos

 

try{

    $c.Bind()

}

catch{

    Write-Host "Kapcsolódási hiba!" -ForegroundColor Red

    Write-Host $_

    return

}

 Az első sorokban megnézem, hogy be van-e töltve a System.DirectoryServices.Protocols.LDAPConnection  típus. Ha nincs, akkor a catch ágban betöltöm. Ezután a $c változóba létrehozom az LDAP kapcsolati objektumot, ennek paramétereként a tartományom DNS nevét és a 389-es portot adom át. Ezután még finomhangolom a kapcsolatot, nem kérek titkosítást, 3-as verziójú LDAP-ot használok és Kerberosszal autentikálok. Ezután kapcsolódok a Bind() metódussal. Hiba esetén kiírom, hogy hiba van és a hiba szövegét.

Nézzük, hogyan lehet egy objektumot lekérdezni:

$sr = new-object -TypeName System.DirectoryServices.Protocols.SearchRequest

$sr.DistinguishedName = "DC=ps,DC=local"

$sr.Filter = "(&(objectclass=user)(samaccountname=vj))"

$re = $c.SendRequest($sr)

 Az $sr változóba létrehozok egy System.DirectoryServices.Protocols.SearchRequest  objektumot, ennek többfajta tulajdonságát ki lehet tölteni. Én most csak az egyszerűség kedvéért a keresés helyét és az LDAP lekérdezést adtam meg, majd a korábban létrehozott $c kapcsolati objektum SendRequest() metódusának adom át, ami ezt a lekérdezést átküldi a kapcsolaton keresztül a tartományvezérlőnek és a választ az $re változóba kapom meg:

PS C:\> $re

 

 

MatchedDN    :

Controls     : {}

ResultCode   : Success

ErrorMessage :

Referral     : {}

References   : {}

Entries      : {CN=Vegetári János,OU=Test,DC=ps,DC=local}

RequestId    :

A ResultCode mutatja, hogy sikeres volt-e a lekérdezés, ha igen, akkor az Entries-be kapom vissza a tényleges választ. Ez mindenképpen gyűjtemény lesz, még akkor is, ha csak 1 találatot kaptam vissza:

PS C:\> $re.Entries

 

DistinguishedName                        Attributes

-----------------                        ----------

CN=Vegetári János,OU=Test,DC=ps,DC=local {givenname, codepage, objectcatego...

Ennek Attributes tulajdonságában vannak az AD objektum attribútumai:

PS C:\> $re.Entries[0].Attributes

 

Name                           Value

----                           -----

givenname                      {74 195 161 110 111 115}

codepage                       {48}

objectcategory                 {67 78 61 80 101 114 115 111 110 44 67 78 61...

dscorepropagationdata          {49 54 48 49 48 49 48 49 48 48 48 48 48 48 4...

usnchanged                     {49 54 52 50 51}

instancetype                   {52}

logoncount                     {48}

name                           {86 101 103 101 116 195 161 114 105 32 74 19...

badpasswordtime                {48}

pwdlastset                     {49 51 49 56 52 54 50 56 55 55 54 48 56 55 5...

objectclass                    {116 111 112, 112 101 114 115 111 110, 111 1...

badpwdcount                    {48}

samaccounttype                 {56 48 53 51 48 54 51 54 56}

usncreated                     {49 54 52 49 49}

sn                             {86 101 103 101 116 195 161 114 105}

objectguid                     {237 100 82 153 105 171 32 73 143 139 82 82 ...

whencreated                    {50 48 49 56 49 48 50 49 50 48 53 50 53 54 4...

maxstorage                     {49 50 51 52 53 54 55 56}

useraccountcontrol             {53 49 50}

cn                             {86 101 103 101 116 195 161 114 105 32 74 19...

countrycode                    {48}

primarygroupid                 {53 49 51}

whenchanged                    {50 48 49 56 49 48 50 49 50 49 49 50 53 54 4...

lastlogon                      {48}

distinguishedname              {67 78 61 86 101 103 101 116 195 161 114 105...

samaccountname                 {118 106}

objectsid                      {1 5 0 0 0 0 0 5 21 0 0 0 237 21 168 170 134...

lastlogoff                     {48}

displayname                    {86 101 103 101 116 195 161 114 105 32 74 19...

accountexpires                 {57 50 50 51 51 55 50 48 51 54 56 53 52 55 5...

userprincipalname              {118 106 64 112 115 46 108 111 99 97 108}

Elsőre nem tűnik túl szimpatikusnak, amit látunk. A legtöbb érték valójában egy szöveg karakterkódjainak tömbje, például a DistinguishedName értékét így lehet visszafejteni:

PS C:\> [char[]] $re.Entries[0].Attributes.distinguishedname[0] -join ""

CN=Vegetári János,OU=Test,DC=ps,DC=local

Itt megint kellett a [0] indexet használnom, hiszen itt is minden attribútum tömbként van kezelve, jobban mondva tömbök tömbjeként. A példánkban szereplő maxStorage attribútumot is ugyanígy tudjuk dekódolni, de ha számként kell kezeljük, akkor még egy típuskonverziót is hozzáadhatunk:

PS C:\> [int64] ([char[]] $re.Entries[0].Attributes.maxstorage[0] -join "")

12345678

Ha át akarjuk írni ennek az attribútumnak az értékét, akkor a következőket kell tenni:

$r = new-object -TypeName System.DirectoryServices.Protocols.ModifyRequest

$r.DistinguishedName = "CN=Vegetári János,OU=Test,DC=ps,DC=local"

 

$a = New-Object -TypeName System.DirectoryServices.Protocols.DirectoryAttributeModification

$a.Name = "MaxStorage"

$a.Operation = [System.DirectoryServices.Protocols.DirectoryAttributeOperation]::Replace

[void] $a.Add(11223344)

 

[void] $r.Modifications.Add($a)

 

$re = $c.SendRequest($r)

 

if ($re.ResultCode -ne [System.directoryServices.Protocols.ResultCode]::Success){

    write-host "Hiba!" -ForegroundColor Red

    write-host "Hibakód: $($re.ResultCode)"

    write-host "Üzenet : $($re.ErrorMessage)"

}

else{

    $re.ResultCode

}

 Elsőként most egy System.DirectoryServices.Protocols.ModifyRequest  objektumot hoztam létre az $r változóba. Ennek tulajdonságaként a módosítandó objektum DistinguishedName nevét adom meg. Majd egy újabb objektum, egy System.DirectoryServices.Protocols.DirectoryAttributeModification  jön, amiben összerakom, hogy mit is akarok módosítani. Ennek Name tulajdonságába kerül az attribútum neve, az Operation tulajdonságba kerül a változtatás típusa, ami itt Replace, majd meghívom az Add() metódust, amivel az attribútum új értékét töltöm bele. Mindezt berakom a ModifyRequest objektum Modifications tulajdonságába, majd a kapcsolaton keresztül átküldöm a tartományvezérlőhöz. Ezután már csak a választ kell értékelni, ami jó esetben Success a válasz ResultCode tulajdonságában.

Látható, hogy a $r.Modifications-be akár több különböző változtatást is berakhatunk és mindezt egy menetben küldhetjük át feldolgozásra. Az attribútumokkal természetesen nem csak felülírást (Replace) végezhetünk, hanem törlést és hozzáadást is:

PS C:\> [System.DirectoryServices.Protocols.DirectoryAttributeOperation] | gm -

Static -MemberType Property

 

 

   TypeName: System.DirectoryServices.Protocols.DirectoryAttributeOperation

 

Name    MemberType Definition

----    ---------- ----------

Add     Property   static System.DirectoryServices.Protocols.DirectoryAttri...

Delete  Property   static System.DirectoryServices.Protocols.DirectoryAttri...

Replace Property   static System.DirectoryServices.Protocols.DirectoryAttri...

Mindezt tehát egy kis ízelítőül szántam arra, hogy az ADSI-n kívül milyen egyéb módszer áll rendelkezésünkre AD objektumok lekérdezésére, módosítására.

 

 

 

 



Word To HTML Converter