Nem bírunk nyugton ülni a fenekünkön, még mindig felhasználói adatokat akarunk módosítani az Active Directoryban. Csakhogy mostanra begörcsölt a jobb csuklónk, így szomorúan lökjük félre az egeret. Innentől csak a billentyűzetre fogunk támaszkodni.
Lássuk a parancssoros AD editáló segédprogramokat.

5. DS parancsok
A Windows szerverek esetén maga az operációs rendszer is tartalmaz egy csomó címtárpiszkálgatásra alkalmas segédprogramot. Ilyenek például a Windows2003 szerverben megtalálható DS* kezdetű parancsok.

  • DSAdd
    Segítségével különböző típusú objektumokat (computer, contact, group, ou, user, quota) adhatunk a címtárhoz.
    Részletes ismertetése megtalálható itt.

    Példa:
    Új felhasználó hozzáadása a címtárhoz:
    dsadd user „cn=Vaszilij Kubaszov, cn=users, dc=test, dc=net”

  • DSGet
    Segítségével különböző típusú objektumok (computer, contact, group, ou, user, quota, server, subnet, site, partition) egyes tulajdonságait tudjuk lekérdezni.
    Részletes ismertetése megtalálható itt.
    Elég sűrűn szokták a DSQuery parancs kiegészítéseként használni. (Lásd később.)

    Példa:
    Egy felhasználó csoporttagságainak kilistázása, beleértve az egymásbaágyazott csoportokat is:
    dsget user „CN=Magyari Béla,CN=Users,DC=test,DC=net” -memberof -expand

  • DSMod
    Segítségével különböző típusú objektumok (computer, contact, group, ou, server, user, quota, partition) egyes tulajdonságait tudjuk módosítani.
    Részletes ismertetése megtalálható itt.

    Példa:
    Felhasználó jelszavának megváltoztatása, belépéskor jelszóváltás kikényszerítése.
    dsmod user „CN=Farkas Bertalan,CN=Users,DC=test,DC=net” -pwd ujjelszo -mustchpwd yes

  • DSMove
    Egy objektum átmozgatására, illetve átnevezésére szolgál.
    Részletes ismertetése megtalálható itt.

    Példa:
    Felhasználó átrakása egy másik OU-ba.
    dsmove „CN=Valerij Kubaszov,CN=Users,DC=test,DC=net” -newparent OU=CCCP,CN=Users,DC=test,DC=net

  • DSQuery
    A megadott feltételek segítségével lekérdezi a címtárat. Lehet szűkíteni egyes objektumokra (computer, contact, group, ou, site, server, user, quota, partition), de lehet szűkítés nélkül (dsquery *) is használni.
    Részletes ismertetése megtalálható itt.

    Példa:
    Lekérjük az összes olyan felhasználót, akinek az előneve a ‘Farkas’ szóval kezdődik, plusz lekérdezzük hozzá a felhasználó néhány adatát (dn, description) is.
    dsquery user -name Farkas* | dsget user -dn -desc

  • DSRm
    Objektum törlése a címtárból.
    Részletes ismertetése megtalálható itt.

    Példa:
    Egy OU és összes elemének törlése.
    dsrm -subtree -noprompt -c OU=CCCP,CN=Users,DC=test,DC=net

Link szekció:

6. ADFind, ADMod

Joe Richards mindig reszelget valamit a műhelyében. Joe – aki egyébként Directory MVP – nem csak a neve miatt szimpatikus, hanem azért is, mert a segédprogramjait ingyen bocsátja a nagyérdemű részére. Mindegyik program kizárólag csak parancssori verzióban létezik. Joe szemmel láthatóan nem kedveli a GUI-kat.

A sok közül kettőt emelnék most ki. Ennek a kettőnek története van. Korábban Joe elég sokat macerálta az Active Directoryt, hol ldapsearch-csel, hol egy bizonyos search.vbs szkripttel, illetve ha ezekkel megakadt, akkor nekiállt saját visual basic szkripteket írni. Tudjuk, hogy vbsciptben nem lehet minden AD műveletet végrehajtani, vannak olyan értékek, főleg a binárisok, melyek elég nehezen adják meg magukat. Aztán amikor már teljesen elege lett ebből a kínlódásból, Joe megírta az ADFind segédprogramot. C++-ban.
Nem sokkal később a Microsoft is kijött a DS* családdal, de Joe állítja, hogy az ő programjai sokkal flexibilisek, léteznek hozzá add-on-ok (pl. egy perl szkript, mely a végeredményt csv formátumba konvertálja) – és nem utolsó sorban, működnek Windows 2000 szervereken is.

  • ADFind
    Ez egy query segédprogram, az AD-n belül hajt végre megadott lekérdezéseket. Ahogy Joe fogalmazott: ez egyfajta speciális keveréke az ldapsearch, search.vbs, ldp, dsquery, dsget programoknak, egyéb dögös opciókkal feltupírozva.
    A program részletes leírása itt található, maga a program is innen tölthető le.

    Példák:
    Egy felhasználó objektum összes értékkel bíró tulajdonságának és azok értékeinek kilistázása, úgy, hogy az idő jellegű adatok emberi módon jelennek meg:
    adfind -b dc=test,dc=net -f name=”Farkas Bertalan” -tdc

    Kitiltott felhasználók kilistázása az egész AD erdőből:
    adfind -gc -b -bit -f „&(objectcategory=person)(samaccountname=*)(useraccountcontrol:AND:=2)” -dn

    Séma dump:
    adfind -sc sdump

  • ADMod
    Ez a program már egyértelműen a DS* programok megjelenése után íródott. Joe-nak ugyanis azokból is elege lett: a dsmod, dsmove, dsrm programok nem igazán akartak úgy működni, ahogy ő szerette volna, pontosabban nem igazán akartak úgy működni, ahogy az expert adminok szerették volna – ezért írt egy olyan segédprogramot, mely az ő ízlése szerint viselkedik. Elméletileg ugyanazokat a dolgokat tudja, mint a fenti hármas, csak máshogy – kiegészítve azzal, hogy van benne undelete funkció, igaz ez csak Windows 2003 szerveren működik. (Az összes többi funkció elérhető Windows 2000 szervereken is.)
    A program részletes leírása itt található, maga a program is innen tölthető le.

    Példák:
    Egy felhasználói tulajdonság értékének módosítása:
    admod -b „CN=Valerij Kubaszov,OU=CCCP,CN=User,DC=test,DC=net” „ipPhone::bal3″

    Felhasználó létrehozása:
    admod -b ou=CCCP,cn=users,dc=test,dc=net objectclass::user samaccountname::leonyidb -add

    Módosítja az összes beépített adminisztrátor leírás mezőjének az értékét. (Nagyon szép összecsövezése az adfind és admod programoknak.)
    adfind -gc -b -f „&(objectcategory=person)(objectclass=user)(name=administrator)” -dsq |admod „description::Rendszergarázda”

Link szekció:

7. Ldifde, csvde
A Windows szerverekben megtalálható másik kupac címtárkezelő parancs a *DE végű parancsokból áll. (DE: Directory Export) Ezek a programok azon filozófia mentén működnek, hogy képesek fájlba exportálni a címtár részeit, illetve képesek fájlból adatokat importálni a címtárba. (A DS* parancsoktól eltérően mindkettő létezik már Windows2000 szerveren is.)
A csvde inkább nagytömegű módosításokra alkalmas, az ldifde viszont a fifikásabb változtatások lezongorázására.

  • CSVDE Mint a nevéből is kikövetkeztethető, az átmeneti tárolóként használt fájl jelen esetben csv típusú – azaz akár szövegszerkesztőből, akár Excelből remekül szerkeszthető.
    Tipikus menet, hogy a címtár egy részét kiexportáljuk, akármilyen módszerrel módosítjuk a csv fájlt, majd a fájlt tartalmát visszaimportáljuk. Szintén tipikus, hogy ez elsőre nem szokott sikerülni. A full export során ugyanis a bináris értékek (SID, GUID és egyéb blobok) is kikerülnek a fájlokba, ezeket viszont nem lehet importálni. Persze a világ nem dől össze, exportálás során egyszerűen meg kell adni a -m -n kapcsolókat és ekkor binárisék békén maradnak.
    A parancs részletes leírása itt található.
  • LDIFDE
    Ennek a nevéből már közvetlenül nem következik a fájl típusa. Márcsak azért sem, mivel ez egy kevert fájlból dolgozik. Kevert, mert a fájlban – szabvány szerinti szintaxisban (LDIF) – egyaránt megtalálhatók az adatok és a parancsok is. Értelemszerűen használatához ismerni kell ezt a szintaxist – és emellett magát az LDAP protokollt is. Nem egyszerű, de megéri elmélyedni benne. Aki Active Directory hegesztésekkel foglalkozik, annak meg úgyis kötelező, mivel a szintaxis elemei vissza-visszaköszönnek a mindennapi munka területein. (Az LDIF egyáltalán nem mellesleg az AD replikáció nyelve.)
    Apró nehezítés, hogy magának a parancsnak is van néhány kapcsolója. A részletes leírást itt találhatjuk. Röviden az LDIF fájl felépítéséről:

    dn: ldap útvonal
    changetype: parancs
    adatok
    >üres sor<
    dn: ldap útvonal
    changetype: parancs
    adatok
    >üres sor<
    … stb …

    A changetype után a következő parancsok állhatnak: add, delete, modify [, modrdn, moddn]. (A kapcsos zárójelben szereplő parancsok – rdn/dn módosítása – részei az LDIF RFC-nek, de tudtommal a Windows LDIFDE nem ismeri ezeket. Kipróbálni még nem próbáltam.)
    Amennyiben az adatok több adatblokkot is tartalmaznak, a blokkokat a ‘-’ karakterrel választjuk el.

    Példák.
    A szöveges fájl beimportálása mindegyik esetben így fog kinézni: ldifde -i -f puffer.txt

    OU létrehozása
    puffer.txt tartalma:
    dn: ou=CCCP,cn=Users,DC=test,DC=net
    changetype: add
    objectclass: organizationalUnit
    ou: CCCP

    Adminisztrátor leírás mezőjének módosítása
    puffer.txt tartalma:
    dn: cn=Administrator,cn=Users,DC=test,DC=net
    changetype: modify
    replace: description
    description: Rendszergarázda

    Ámokfutás – módosítjuk egy felhasználó leírás mezőjét, értéket adunk az IP telefon tulajdonságának és töröljük a munkahelyi azonosítóját.
    puffer.txt tartalma:
    dn: cn=Valerij Kubaszov,ou=CCCP,cn=Users,DC=test,DC=net
    changetype: modify
    replace: description
    description: Beépített ember

    add: ipPhone
    ipPhone: bal3

    delete: employeeID

Link szekció:

8. Excel

Végére hagytam a kedvencemet. Én gyakorlatilag csak ezt használom a tömeges AD módosítások lezongorázására.
Nem, nem zakkantam meg. Legalábbis nem teljesen.
Tudjuk, hogy az Active Directory-t ADSI-n keresztül különböző módokon érhetjük el: .net/vbs/jscript… és egyebek. Az Excel makrók pedig akárhogy is nézzük, teljesen szabályos vbscript-ből állnak, kiegészítve Excel specifikus parancsokkal, változókkal.
Ideális.
Eleinte mondjuk kicsit macerás, de ahogy elkészülnek a tipikus részfeladatok építőkövei, onnan már csak sima falazás az egész. (Építőkockákat a netről is letölthetünk, sőt…)
Első pillantásra jogos lehet a kérdés, hogy miben különbözik ez a módszer a CSVDE használatától. Mindkettőben ki lehet exportálni bizonyos tulajdonságokat egy Excel kompatibilis táblázatba, lehet kézzel módosítani, majd vissza lehet tölteni azokat a címtárba.
A nagy különbség az on-fly vbscript használati lehetőség. Ha valaki látta már, hogyan néz CSVDE esetében a proxaddresses multivalue változó, akkor sejtheti, hogy miről beszélek. Ember legyen a talpán, aki ezt – akár Excelben is – könnyedén szerkesztgeti. Ellenben a makró futása során már a szépen szétválogatott címek kerülnek ki táblázat mezőibe. Ha nem is egyszerűen, de lehetőségünk van lekezelni a bináris mezőket.
Ugyanez a röptében feldolgozás teszi lehetővé, hogy bizonyos feltételektől függően formázhassam a kiírást (szöveg kövérítés, szöveg/háttérszín változtatás), kontrollértékek kiírásával nyomon követhessem a folyamatot. Nem elhanyagolható például, hogy egyszerre több worksheet-et tudok kezelni (mondjuk egyikben tárolva a folyamatban érintett OU-k nevét; így csak azok az OU-k kerülnek feldolgozásra, amelyekkel foglalkozni akarok) – és természetesen rendelkezésre állnak az Excel függvényei a különböző feldolgozásokhoz.

A nagy ujjongásban meg kell említenem a módszer legnagyobb hátrányát is: csak akkor működik, ha van a közelben Excel. Ez a szerverszobákban, a szervereken nem igazán szokott lenni. Akkor értelemszerűen marad a többi megoldás – de ha kényelmesen, usermódban is ráérünk megoldani egy feladatot, akkor a munkaállomásunkról már simán használhatjuk az Excel makrókat.

Végül két építőkocka:

Felhasználó információk legyűjtése:

Sub Macro1()
Attribute Macro1.VB_Description = „Macro recorded 2006.09.03 by JoeP”
Attribute Macro1.VB_ProcData.VB_Invoke_Func = „a\n14″

‘ Macro1 Macro
‘ Macro recorded 2006.09.03 by JoeP

‘ Keyboard Shortcut: Ctrl+a

‘ Adatok lekérdezése a címtárból

‘——————————————————————–
‘ Deklarációk

Dim oActUsers
Dim child, sor
‘——————————————–
‘ Inicializálás

On Error Resume Next

Worksheets(”Munka”).Activate
Cells.Select
Selection.Clear
Range(”A1″).Select

Cells(1, 1).Value = „Username”
Cells(1, 2).Value = „Employee ID”
Cells(1, 3).Value = „Display name”
Cells(1, 4).Value = „Description”
Cells(1, 5).Value = „Phone”
Cells(1, 6).Value = „Mobile”
Cells(1, 7).Value = „Office”
Cells(1, 8).Value = „Title”
Cells(1, 9).Value = „Department”
Cells(1, 10).Value = „Object”
sor = 3
‘——————————————–
‘ Bind

Set oActUsers = GetObject(”LDAP://cn=users, dc=test, dc=net”)
oActUsers.Filter = Array(”user”)
‘——————————————-
‘ Legyüjtés indul

For Each child In oActUsers
Cells(sor, 1).Value = child.samaccountname
Cells(sor, 2).Value = child.employeeid
Cells(sor, 3).Value = child.displayname
Cells(sor, 4).Value = child.Description
Cells(sor, 5).Value = child.telephonenumber
Cells(sor, 6).Value = child.mobile
Cells(sor, 7).Value = child.physicaldeliveryofficename
Cells(sor, 8).Value = child.Title
Cells(sor, 9).Value = child.department
Cells(sor, 10).Value = child.distinguishedname
sor = sor + 1
Next
‘———————————–
‘ Dekoráció
‘ Itt lehet cifrázni a táblázatot

Range(”C1″).Select

End Sub

——————————————————————————

Módosított információk visszaírása:

Sub Macro2()
Attribute Macro2.VB_Description = „Macro recorded 2006.09.03 by JoeP”
Attribute Macro2.VB_ProcData.VB_Invoke_Func = „b\n14″

‘ Macro2 Macro
‘ Macro recorded 2006.09.03 by JoeP

‘ Keyboard Shortcut: Ctrl+b

‘ Adatok visszaírása a címtárba

Dim sor, eszterlanc, oActUser

On Error Resume Next

sor = 3

Do While Cells(sor, 1).Value <> „”
eszterlanc = „LDAP://” & Trim(Cells(sor, 10).Value)
Set oActUser = GetObject(eszterlanc)

If Not IsEmpty(Cells(sor, 2).Value) Then
oActUser.putex 2, „employeeid”, Array(Trim(CStr(Cells(sor, 2).Value)))
Else
oActUser.putex 1, „employeeid”, „”
End If
oActUser.setinfo
Err.Clear

If Not IsEmpty(Cells(sor, 3).Value) Then
oActUser.putex 2, „displayname”, Array(Trim(CStr(Cells(sor, 3).Value)))
Else
oActUser.putex 1, „displayname”, „”
End If
oActUser.setinfo
Err.Clear

If Not IsEmpty(Cells(sor, 4).Value) Then
oActUser.putex 2, „description”, Array(Trim(CStr(Cells(sor, 4).Value)))
Else
oActUser.putex 1, „description”, „”
End If
oActUser.setinfo
Err.Clear

If Not IsEmpty(Cells(sor, 5).Value) Then
oActUser.putex 2, „telephonenumber”, Array(Trim(CStr(Cells(sor, 5).Value)))
Else
oActUser.putex 1, „telephonenumber”, „”
End If
oActUser.setinfo
Err.Clear

If Not IsEmpty(Cells(sor, 6).Value) Then
oActUser.putex 2, „mobile”, Array(Trim(CStr(Cells(sor, 6).Value)))
Else
oActUser.putex 1, „mobile”, „”
End If
oActUser.setinfo
Err.Clear

If Not IsEmpty(Cells(sor, 7).Value) Then
oActUser.putex 2, „physicaldeliveryofficename”, Array(Trim(CStr(Cells(sor, 7).Value)))
Else
oActUser.putex 1, „physicaldeliveryofficename”, „”
End If
oActUser.setinfo
Err.Clear

If Not IsEmpty(Cells(sor, 8).Value) Then
oActUser.putex 2, „title”, Array(Trim(CStr(Cells(sor, 8).Value)))
Else
oActUser.putex 1, „title”, „”
End If
oActUser.setinfo
Err.Clear

Set oActUser = GetObject(eszterlanc)
If Not IsEmpty(Cells(sor, 9).Value) Then
oActUser.putex 2, „department”, Array(Trim(CStr(Cells(sor, 9).Value)))
Else
oActUser.putex 2, „department”, „n/a”
End If
oActUser.setinfo
Err.Clear

sor = sor + 1
Loop

End Sub