ADSI: Snel, Safe en Simpel

Dit artikel verscheen eerder in Windows en Netwerken

Wim Verveen , e-mail: wim@win2kwereld.nl

Inleiding

ADSI is de afkorting van 'Active Directory Services Interfaces'. In tegenstelling tot wat de naam suggereert gaat ADSI verder dan de Active Directory alleen. ADSI is een interface waarmee we vanuit scripts contact kunnen maken met diverse Directory gebaseerde systemen. Door het gebruik van één interface wordt het makkelijk om scripts schrijven die ons kunnen helpen administratieve taken te verlichten. Taken waar scripting en ADSI samenkomen zijn bijvoorbeeld het in batches creëren van gebruikers, mogelijk als output van bijvoorbeeld een personeelsdatabase.

In elke organisatie zijn er, meestal meerdere, plekken waar gegevens over gebruikers en resources worden opgeslagen. Dit zijn onder meer gebruikersdatabases in een wat eenvoudiger vorm (NT 4.0 SAM of Novell Netware Bindery) maar ook LDAP gebaseerde directories zoals Active Directory of NDS. Daarnaast zijn er vele applicaties die hun eigen gegevens bijhouden zoals bijvoorbeeld Lotus Notes.

ADSI is ontstaan uit het besef dat er in elke organisatie meerdere directories aanwezig zijn waardoor het niet eenvoudig is om allerlei soorten informatie zoals gebruikers, printers en documenten te lokaliseren. Door al die verschillende directories nemen de supportkosten onevenredig toe. Door het gebruik van een consistente uniforme interface wordt beheer eenvoudiger en goedkoper. ADSI is die consistente interface en in staat die rol te vervullen die bijvoorbeeld ODBC in de database wereld heeft. Doordat er een standaard manier beschikbaar is om gegevens te benaderen wordt het makkelijker om toepassingen te ontwikkelen die breder inzetbaar zijn.

Voordelen ADSI

ADSI is net als het in eerdere artikelen besproken WMI en ADO  gebaseerd op het component object model, ook wel bekend als COM. Hierdoor is het mogelijk om ADSI te benaderen vanuit allerlei applicaties en (script-) talen. ADSI bestaat uit een consistente interface die relatief eenvoudig is te leren maar toch krachtige aspecten heeft. Doordat ADSI in een eenduidige interface voorziet kunnen we onze code hergebruiken tussen de verschillende directorie systemen.

Figuur 1 : ADSI object model

De volgende providers zijn (out of the box) standaard aanwezig:  WinNT, IIS, AD/Exchange (LDAP), NDS, en Netware Bindery. Het is echter voor fabrikanten mogelijk om nieuwe providers te ontwikkelen die voldoen aan de ADSI standaard.

Naast deze providers is er ook nog een koppeling mogelijk tussen ADSI en WMI. WMI is een interessante interface voor systemmanagement (zie ook: Management Informatie voor elke applicatie, W&N april 2001 ). Veel toepassingen van WMI komen neer op het monitoren of inventariseren van grote aantallen machines. Onder meer de Active Directory is natuurlijk uitermate geschikt als bron van machines die benaderd moeten worden. Om nu te voorkomen dat er allerlei vertaalslagen gedaan moeten worden, voorziet WMI in een extensie die deze vertaling verricht. Hierdoor wordt het simpeler om ADSI en WMI te combineren.

In het kader van beheerwerkzaamheden zal vooral gewerkt worden met de providers WinNT en LDAP om domein objecten te manipuleren. De WinNT provider is de meest simpele van de twee, en is gebaseerd op NT4. Wanneer de WinNT provider gebruikt wordt op een Active Directory domein dan zal deze zich als een NT4 domein presenteren, zover als dat mogelijk is. Dit is analoog aan de wijze waarop AD zich aan NT4 clients presenteert als een NT4 domein door middel van emulatie. De WinNT objecten die zich lenen voor ADSI zijn natuurlijk gebruikers en groepen, maar ook shares en printer objecten. De LDAP provider is veel breder inzetbaar, en kan in feite alle Active Directory objecten aansturen.

Het gebruik van ADSI in een Visual Basic script met de WinNT provider gaat als volgt. Allereerst moeten we een object verbinden aan een computer, user of ander object met een syntax zoals deze:

    Set myObj = GetObject("WinNT://Domain/Machine/Object,Class")

Wat we in de syntax herkennen is het aanroepen van de juiste provider (WinNT://) en daarna het pad naar het object dat we willen gebruiken. Let goed op, de gegevens van de provider moeten in precies deze syntax worden opgeschreven, hoofd- en kleine letters zijn erg belangrijk in ADSI. Met 'class' geven we het type object aan wat verwarring helpt voorkomen. Als we 'Janssen' zoeken willen we waarschijnlijk het user object 'Janssen' en niet de computer die toevallig zo heet.

Soms hebben we niet direct het juiste object en moeten we wat meer zoeken voordat we het hebben gevonden, de voorbeelden in dit artikel zullen dit duidelijker maken. Hebben we eenmaal het juiste object te pakken dan kunnen we hier eigenschappen van opvragen of deze bewerken met de methods en objecten die het object aanbiedt.

Na deze droge kost is het natuurlijk interessant om te zien hoe het in de praktijk nu eigenlijk werkt. Allereerst een simpel voorbeeld waarbij we in een NT 4 of Windows 2000 omgeving het profiel van een gebruiker aanpassen. Met de 'getobject' method wordt een verbinding gezocht met een domaincontroller of (member-)server. Vervolgens filteren we op alle user objecten. Daarna gaan we alle objecten af, laten bij elk object het userID en huidige profilepath zien en passen het daarna aan. Handig bij een verhuizing!

WINNT

Voorbeeld1

    Set UsersObj = GetObject("WinNT://MijnDomein")
    Usersobj.Filter = Array("User")
    for each oUser in UsersObj
      wscript.echo oUser.Name & " Profile : " & oUser.Profile
      oUser.Profile="\\server\profiles$\" & oUser.Name
      oUser.Setinfo
    next

Een ander voorbeeld is het aanmaken van een share. Daar zijn andere commando's voor, zoals het bekende net.exe commando en het rmtshare.exe commando uit de NT4 resource kit (dat overigens uitstekend werkt op Windows 2000), maar deze methode heeft het voordeel dat er geen externe programma's voor aangeroepen worden. In dit geval wordt via de WinNT provider expliciet gebonden aan een bepaalde server, en niet aan het domein; het domein kent immers geen shares.

SHARES

Voorbeeld2

    Const sSharename = "GroupData"
    Const sDirname      = "D:\AllData\TrashCan"
    Const sServer         = "MIJNSERVER"

    Set oServer = GetObject ("WinNT://" & sServer &  "/lanmanserver")
    Set oShare = oServer.Create("FileShare", sSharename)
    oShare.Path = sDirname
    oShare.Description = "Group Data"
    oShare.SetInfo

Het zou mooi zijn om via deze methode ook permissies toe te kennen aan de nieuwe share. Dit blijkt helaas niet mogelijk te zijn, en illustreert meteen een tekortkoming van standaard ADSI. Het permissiemodel van NT4 of Windows 2000 is niet, of slechts moeizaam toegankelijk. De ADSI SDK kit (gratis te downloaden bij Microsoft) heeft een gedeeltelijke oplossing in de vorm van een extra COM component -- AdsSecurity.dll – waarmee wel Access Control Entries bewerkt kunnen worden.

Het contact met de Active Directory via de LDAP provider is een stuk gecompliceerder omdat ook de AD niet zo doorzichtig is als een SAM database uit het vorige voorbeeld, waar de Active Directory database via de WinNT proveder werd benaderd.
Voorbeeld 3 maakt middels LDAP contact met de AD, selecteert de juiste Organisational Unit (OU) en filtert dan op gebruikersaccounts die één voor één worden opgevraagd.

AD

Lees gebruikersinformatie uit de AD
'Laat alle user accounts zien in de gewenste OU

Voorbeeld 3:

      Const sOrg="ou=testOU"
      Dim strInfo,oDir,oDomain,oOrg,oUser

      'Maak verbinding met de AD
      Set oDir=Getobject("LDAP://RootDSE")
      set oDomain=Getobject("LDAP://" & oDir.Get("defaultNamingContext"))
      set oOrg = oDomain.Getobject("organizationalUnit",sOrg)
      'Selecteer de user accounts
      oOrg.Filter = Array( "User" )
      For Each oUser in oOrg
       strInfo=strinfo & "Account : " & oUser.samAccountname & vbcrlf & _
          "Naam    : " & oUser.Givenname & vbcrlf & _
          "Lastname: " & oUser.sn & vbcrlf
       Next
      wscript.echo strinfo

In het voorbeeld 4 gaan we een stapje verder. Op dezelfde manier wordt nu contact gezocht met de Active Directory. Echter daarna gebruiken we het commando oOrg.Create om een gebruikersaccount aan te maken. In dit script maken we niet één gebruiker aan maar een instelbaar aantal gebruikers. Dit ten bate van een performance test bijvoorbeeld.

Aanmaken van een x-aantal gebruikers

Dit voorbeeld laat tevens een aantal van de te definiëren opties zien. Er vindt een rudimentaire vorm van foutencontrole plaats door na te gaan of er een foutmelding wordt gegeven bij het aanmaken van de gebruiker. In een productieomgeving moet dit natuurlijk worden uitgebreid.

Voorbeeld 4: 'Creer een groot aantal(100)  users

    Const sOrg="ou=testOU"
    Const MaxUsers = 100
    sServer="TestServer"
    Dim strInfo,oDir,oDomain,oOrg,oUser,I

    'Maak verbinding met de AD
    Set oDir=Getobject("LDAP://RootDSE")
    set oDomain=Getobject("LDAP://" & oDir.Get("defaultNamingContext"))
    set oOrg = oDomain.Getobject("organizationalUnit",sOrg)

    For I = 1 to MaxUsers
    sUserID="CountUser" & I
    set oUser=oOrg.Create("user","cn=" & sUserid)

    'wscript.echo sFullName & " " & sPrincName
      oUser.samAccountname=sUserid
      oUser.Userprincipalname=sUserid
      oUser.description="Windows & Netwerken"
      oUser.Givenname=sUserID
      oUser.sn=sUserID
      oUser.displayname=sUserID
      oUser.homedrive="J:"
      oUser.Profile="\\" + sServer + "\profiles$\" + sUserid
      oUser.homedirectory="\\" + sServer + "\" + sUserid + "$"
      on error resume next
      oUser.Setinfo
      if Err.number <> 0 then
        if Err.Number=-2147019886 then
          sDescription="Gebruiker bestond al"
          wscript.quit
        end if
        wscript.echo Err.number
      end if
      on error goto 0
      oUser.Accountdisabled=True
      oUser.Setinfo

    'Object weer vrijgeven
    Next

IIS

Voorbeeld 5

    Dim ComputerObj
    Dim strinfo
    Set ComputerObj = GetObject("IIS://LocalHost")
    strinfo=  "Maximale bandbreedte :" & ComputerObj.MaxBandwidth
    wscript.echo strinfo

ADSI en WMI

Een klein voorbeeld van het koppelen van WMI en ADS.
Eerst vragen we uit de AD een computerobject om deze vervolgens door te sluizen naar WMI en het filesysteem van de C: schijf op te vragen

Voorbeeld 6

    Dim oComputer
    Dim oWMI
    Dim oDevice

    Set oComputer = GetObject("LDAP://CN=badmobile,CN=Computers,DC=wvc,DC=local")
    Set oWMI = oComputer.GetWMIServices
    Set oDevice = oWMI.Get("Win32_LogicalDisk.DeviceID=""C:""")

    wscript.echo "FileSysteem=" + oDevice.FileSystem

Met Windows 2000 is scripting een onlosmakelijk onderdeel geworden van het dagelijks beheer. Ik hoop dat de voorbeelden die aan u zijn voorgesteld u hebben duidelijk gemaakt welke waardevolle bijdrage scripting kan leveren aan het dagelijks werk van een beheerder.
ADSI is met name van belang doordat het essentieel is voor ondermeer gebruikersbeheer. Het blijkt dat zelfs met een eenvoudig script reeds behoorlijk gecompliceerde taken op eenvoudige wijze kunnen worden uitgevoerd. Samen met de voorbeelden uit dit artikel en de onderstaande links zult u binnen korte tijd uw collega's versteld doen staan!

Resources

Creëer een exchange mailbox met ADSI
http://msdn.microsoft.com/library/psdk/adsi/ds2exchgd_0it4.htm

ADSI overview:  http://www.microsoft.com/windows2000/techinfo/howitworks/activedirectory/adsilinks.asp

ADSI reference:  http://msdn.microsoft.com/library/psdk/adsi/adsistartpage_7wrp.htm

De scripts downloaden:  http://www.win2kwereld.nl/downloads/wnadsi.zip

 

W. Verveen is verbonden aan de Ormer groep als Consultant, daarnaast beheert hij Win2K Wereld
E-mail: w.verveen@ormer.nl
Web:
http://www.ormer.nl en http://www.win2kwereld.nl

 


privacy policy