LDAP per Amministratori Active Directory – LDAP for Active Directory Administrators

In questo articolo vi introdurrò all'uso di LDAP, un protocollo di accesso alla directory, scoprirete come sia possibile interrogare e manipolare gli oggetti e le informazioni contenute nel database di Active Directory al fine di automatizzare determinate procedure amministrative o semplicemente estrapolare da esso utili informazioni.

Ad_Tree_bw.jpg

Lo Schema di Active Directory

Gli oggetti con i quali lavoriamo quotidianamente in Active Directory vengono creati seguendo le regole dettate da uno schema, banalizzando potremmo affermare che esso costituisce la struttura del database della directory.

Per fare un esempio molto banale provate a pensare che un utente sia un oggetto al quale vengono associate una serie di proprietà: il suo nome, il suo cognome, il suo indirizzo email, il suo username e così via, queste proprietà vengono dette attributi e lo Schema di Active Directory si occupa di definirli stabilendo anche quali di essi possano essere associati ad un oggetto piuttosto che ad un altro; un gruppo utenti o una stampante avranno delle proprietà sicuramente differenti da un semplice utente.

Lo Schema inoltre è modificabile, in particolari condizioni potrebbe essere necessario creare nuovi attributi al fine di garantire una perfetta integrazione tra gli oggetti di Active Directory e le applicazioni esterne ad esso. Un esempio di quanto ho appena affermato è dato dalla procedura di installazione di Microsoft Exchange Server, un prodotto che fornisce servizi legati alla posta elettronica ed ideato per il Groupware. Per far sì che i servizi di Exchange Server possano integrarsi nella directory occorrerà, in fase di installazione, eseguire alcuni comandi che si occuperanno di estendere lo Schema al fine di aggiungere ad esso una nuova serie di attributi (perché estendere lo schema? basti pensare alla necessità di collegare agli oggetti utente tutti i dettagli relativi alla casella email assegnatagli).

Per visualizzare lo schema su di un qualsiasi Domain Controller dobbiamo registrare la snap-in amministrativa Schema Management, questa fa parte del pacchetto amministrativo di Windows Server ed è già installata nel sistema ma per motivi di sicurezza non viene registrata automaticamente.

N.B.: E' necessario prestare particolare attenzione alle azioni che si compiono utilizzando lo Schema Management, modificare in maniera errata anche soltanto una singola voce all'interno di esso può portare a conseguenze disastrose.

Dal menu Start->Run (o da un prompt dei comandi) digitate il seguente comando

regsvr32.exe schmmgmt.dll

Se tutto procede correttamente dovreste ottenere un messaggio che vi avvisa dell'avvenuta registrazione del componente e dovrebbe ora essere possibile utilizzare la snap-in di gestione dello Schema.

Per chi non sapesse come caricare una snap-in amministrativa, ecco cosa dovete fare

  • Dal menu Start->Run (o da un prompt dei comandi) digitate il comando mmc.exe, questo farà in modo che venga aperta l'interfaccia del motore Microsoft Management Console (MMC).
  • Attivate il menu File->Add/Remove Snap-in, questa azione farà apparire una finestra che vi permetterà di caricare una alla volta tutte le snap-in delle quali avrete bisogno; noi ne attiveremo una soltanto, quella chiamata Active Directory Schema.
  • Premete il pulsante Add, trovate e selezionate la voce Active Directory Schema, premete il tasto Add di questa nuova finestra e poi Close.
  • Noterete che ora la snap-in "Active Directory Schema" risulta in lista e perciò caricata. Premete OK per confermare chiudendo così tutte le finestre di dialogo.

Qualche screenshot che illustra i passaggi sopra descritti...

ldap1.PNG
ldap2.PNG
ldap3.PNG


ldap4.PNG
ldap5.PNG


Espandere ed esplorare le voci contenute nell'interfaccia amministrativa che avete appena caricato vi renderà subito l'idea di come è organizzato questo schema, in realtà non è particolarmente complesso: come vi ho accennato in precedenza esistono diverse classi di oggetti che possono essere creati all'interno del database e ad ognuno di essi vengono associati degli attributi.

Prendiamo come esempio la classe user, se fate scorrere rapidamente la lista degli attributi ad essa associati noterete l'esistenza di voci che potrebbero risultarvi familiari come: mail, HomeDirectory, HomeDrive, displayName, info, userPrincipalName o le più interessanti memberOf, LastLogon, LastLogoff.

ldap6.PNG


Sull'MSDN potete trovare una lista completa di tutte le classi e gli attributi che trovate in questo Schema.

Alla luce di tutto ciò viene naturale chiedersi come sia possibile interrogare e manipolare a piacere tutte queste informazioni, ed è proprio ciò che andremo a vedere tra poco.

Quello che sappiamo fino ad ora è che Active Directory è organizzato secondo uno schema che stabilisce le tipologie di oggetti che possiamo creare e gli attributi ad essi associati, ma dove vengono posizionati poi questi dati? Come facciamo a raggiungerli? Per dare una risposta a queste due domande occorre fermarsi un attimo e parlare di protocolli di accesso, in particolare parleremo di LDAP.

LDAP

LDAP (Lightweight Directory Access Protocol) è il protocollo che permette di interfacciarsi con Active Directory, ogni Domain Controller infatti esegue un Server LDAP interrogabile tramite sintassi LDAP.

Non vi proporrò ora la storia di LDAP, in questo articolo ci concentreremo soltanto sull'aspetto tecnico-pratico dell'argomento, un buon approfondimento lo potete trovare su Wikipedia.

Innanzitutto, al fine di seguire la mia spiegazione, vi consiglio di installare i Support Tools di Windows Server, per la versione 2003 li potete trovare qui per Service Pack 1 e qui per Service Pack 2, vi ricordo che è possibile installarli anche su Windows XP.

All'interno dei Support Tools sono infatti inclusi alcuni strumenti grafici che permettono di lavorare con LDAP, in particolare ADSI Edit ci permetterà di esplorare la struttura di un Domain Controller ed ldp.exe di connetterci ad un server al fine di eseguire ricerche all'interno di esso.

Iniziamo quindi da ADSI Edit, grazie a questo strumento potrete facilmente capire come vengono identificati gli oggetti tramite la sintassi LDAP, se avete installato i Support Tools lo troverete nel percorso C:\Program Files\Support Tools\adsiedit.msc

All'apertura il programma visualizzerà la seguente schermata

ldap8.PNG


Per fare un minimo di chiarezza occorre innanzitutto dire che le voci Domain, Configuration e Schema rappresentano le tre partizioni che compongono il database di Active Directory, in particolare le partizioni di configurazione e di schema sono comuni per tutta la foresta mentre la partizione di dominio è specifica e ne esiste una per ogni dominio che compone la foresta.

Nel caso in cui la vostra foresta sia composta da più di un unico dominio e che stiate eseguendo lo strumento ADSI Edit connettendovi ad un server che svolge la funzione di Global Catalog è possibile che vengano visualizzate anche altre partizioni; quanto detto succede perché, a differenza di un normale Domain Controller il quale ospita nel proprio database soltanto gli oggetti appartenenti al dominio di cui esso fa parte, il server Global Catalog ha il compito di memorizzare anche ulteriori informazioni che appartengono ai vari domini della foresta.

Ciò che però interessa maggiormente a noi in questo momento è esplorare la sola partizione di Dominio, provate ad espanderne i vari livelli ed osservatene la struttura...

ldap9.PNG


Avete notato come i nomi dei vari oggetti siano preceduti da acronimi? DN, DC, CN, OU... essi sono i componenti di un nome.

Secondo la sintassi LDAP ogni oggetto che potete trovare all'interno dell'albero della directory viene identificato per mezzo di un Distinguished Name (DN), un nome univoco. Il DN viene costruito mettendo in sequenza una serie di componenti specifiche separate per mezzo di una virgola, il compito di tale sequenza è quello di descrivere il percorso assoluto dell'oggetto preso in esame, o meglio la sua posizione, all'interno della struttura di directory.

Le componenti di un DN sono le seguenti

  • L'acronimo DC (Domain Component) indica la componente di dominio, il dominio testdomain.lan in LDAP viene rappresentato come DC=testdomain, DC=lan così come il percorso america.azienda.inet verrebbe rappresentato con DC=america, DC=azienda, DC=inet; possiamo pertanto affermare che in LDAP un nome di dominio viene spezzettato in più Domain Component separate da una virgola, nello specifico una DC per ogni livello del suo nome DNS.
  • L'acronimo OU identifica invece una Organizational Unit, se nel vostro Active Directory avete organizzato gli oggetti per mezzo di esse dovrete ricostruirne la struttura anche nel percorso LDAP.
  • CN invece sta per Common Name ed indica il nome comune di un oggetto, il nome comune dell'oggetto di classe utente Mirko Iodice sarà appunto "CN=Mirko Iodice".

Percui, in base a quanto mostrato dal mio precedente screenshot, il Distinguished Name per il suddetto utente sarà

CN=Mirko Iodice, OU=Domain Users, DC=testdomain, DC=lan
ldap10.PNG


Non è complicato... è sufficiente ricostruire l'intero percorso in senso contrario a come viene sfogliato nella struttura ad albero proposta dagli strumenti amministrativi di Active Directory.

Voglio fare soltanto una precisazione: non dovete confondere il CN (Common Name) di cui abbiamo appena parlato con il Canonical Name che viene invece visualizzato all'interno dello strumento Active Directory Users and Computers, quest'ultimo è come un Distinguished Name privato però di informazioni come DC, OU, CN. Di seguito il Canonical Name dell'oggetto appena preso in esame.

ldap11.PNG


Dalla teoria alla pratica - l'uso di ldp.exe

Chiudete pure ADSI Edit ed aprite ora lo strumento ldp.exe che trovate sempre sotto a C:\Program Files\Support Tools.

ldp.exe ci permetterà di sperimentare quanto abbiamo detto fin'ora, per mezzo di esso eseguiremo infatti una connessione al server LDAP ed una query, il nostro fine sarà quello di ottenere come risultato una lista dei gruppi di cui fanno parte gli oggetti di classe utente contenuti in una specifica Unità Organizzativa (Domain Users). Credetemi... si fa più fatica a descriverlo che a farlo.

Dopo aver aperto ldp.exe Andate sul menu Connection e selezionate la voce Connect, vi verrà ora richiesto di specificare alcuni dati, in condizioni normali occorre soltanto inserire l'indirizzo di un Domain Controller. Nel mio caso inserirò localhost poiché sto lavorando sul Domain Controller stesso.

ldap12.PNG


Appariranno a video alcuni messaggi di log e vi renderete subito conto se la connessione ha avuto esito positivo.

La sola connessione al server LDAP per fortuna non basta per ottenere informazioni, sarà necessario ora stabilire un binding completo utilizzando un account utente di dominio autorizzato. Dal menu Connection selezionate la voce Bind, inserite i dati richiesti e poi premete il tasto OK.

ldap13.PNG


Di nuovo alcuni messaggi di log confermeranno l'esito positivo dell'operazione

ldap14.PNG


Una volta eseguita l'operazione di binding avrete la possibilità di utilizzare tutti i comandi disponibili sotto al menu Browse, per questo esempio utilizzeremo soltanto la funzione Search... selezionatela.

ldap15.PNG


Compiliamo i dati richiesti dalla finestra di dialogo Search, in particolare

  • Base Dn deve corrispondere alla posizione di base dalla quale vorrete far partire la vostra ricerca, nel mio caso non voglio eseguirla all'interno dell'intero dominio ma soltanto tra gli oggetti contenuti nella unità organizzativa Domain Users, per questo motivo specificherò come Base dn soltanto il percorso LDAP di questa OU.
  • Filter è un filtro di ricerca, praticamente costituisce la nostra chiave di ricerca vera e propria; il carattere asterisco funziona da wildcard (non è però supportato per tutti i tipi di attributo) ed utilizzato da solo permette di non specificare nessun filtro. Come filtro è possibile utilizzare sia valori riferiti a classi di oggetti che attributi (vi ricordate la struttura dello Schema di AD spiegata poco fa?). Per il momento mi limiterò a ricercare i soli oggetti di classe user perché la mia intenzione è quella di ottenere la lista dei gruppi di cui fa parte ciascun utente contenuto nella suddetta organizzativa.
  • Il parametro Scope permette di specificare la profondità della ricerca, cioè il numero di sottolivelli a partire dal Base Dn nei quali verrà effettuata la ricerca; vogliamo forse che essa si limiti ad analizzare i soli oggetti contenuti in questa specifica unità organizzativa? Oppure ci farebbe comodo analizzare anche il livello immediatamente successivo o addirittura l'intero albero? Nel mio caso la scelta non farà nessuna differenza poiché non ci sono altre unità organizzative all'interno del Base Dn "Domain Users", lascerò quindi selezionata la voce subtree.
ldap16.PNG


Non ho però ancora espresso in nessun modo la volontà di visualizzare i gruppi di cui fanno parte gli eventuali utenti contenuti nel Base Dn, per questa operazione utilizzerò il pulsante Options che vedete evidenziato nella precedente immagine.

ldap17.PNG


La stringa Attributes permette di specificare una lista di tutti gli attributi che verranno restituiti in output qualora vengano trovati oggetti che soddisfino il filtro di ricerca prestabilito. Procedo quindi aggiungendo memberOf infondo alla lista degli attributi ed apponendo un carattere punto e virgola per terminare la stringa. A quanto punto è sufficiente premere il pulsante OK per accettare le modifiche e poi Run per eseguire la query. Un piccolo consiglio: in un secondo momento, a scopo puramente didattico, provate a visualizzare anche l'attributo "pwdLastSet" e godetevi i risultati della ricerca... vi verrà visualizzata la data esatta dell'ultimo cambio password eseguito dall'utente.

ldap18.PNG


L'output generato dall'operazione di ricerca non risulta certamente facile da leggere, in ogni caso si nota che sono stati trovati due utenti all'interno del Base Dn preso in esame e che soltanto uno di essi fa parte di qualche gruppo, per la precisione l'utente Mirko Iodice fa parte di due gruppi: Italy Admins ed IT Department.

Getting 2 entries:
>> Dn: CN=Mirko Iodice,OU=Domain Users,DC=testdomain,DC=lan
	4> objectClass: top; person; organizationalPerson; user; 
	1> cn: Mirko Iodice; 
	1> distinguishedName: CN=Mirko Iodice,OU=Domain Users,DC=testdomain,DC=lan; 
	2> memberOf: CN=Italy Admins,OU=Domain Groups,DC=testdomain,DC=lan;
                            CN=IT Department,OU=Domain Groups,DC=testdomain,DC=lan; 
	1> name: Mirko Iodice; 
	1> canonicalName: testdomain.lan/Domain Users/Mirko Iodice; 
>> Dn: CN=Mario Rossi,OU=Domain Users,DC=testdomain,DC=lan
	4> objectClass: top; person; organizationalPerson; user; 
	1> cn: Mario Rossi; 
	1> distinguishedName: CN=Mario Rossi,OU=Domain Users,DC=testdomain,DC=lan; 
	1> name: Mario Rossi; 
	1> canonicalName: testdomain.lan/Domain Users/Mario Rossi;

Se ritoccassi le opzioni di ricerca eliminando la visualizzazione di tutti gli attributi eccetto memberOf potrei migliorare sensibilmente la leggibilità di quanto sopra riportato ottenendo il seguente risultato

Getting 2 entries:
>> Dn: CN=Mirko Iodice,OU=Domain Users,DC=testdomain,DC=lan
	2> memberOf: CN=Italy Admins,OU=Domain Groups,DC=testdomain,DC=lan;
                            CN=IT Department,OU=Domain Groups,DC=testdomain,DC=lan;
>> Dn: CN=Mario Rossi,OU=Domain Users,DC=testdomain,DC=lan

Vi voglio far notare che anche i gruppi di cui il mio utente fa parte vengono identificati per mezzo di un Distinguished Name e che il loro nome è anch'esso un CN.

AdFind

Purtroppo l'output offerto dallo strumento ldp.exe non risulta particolarmente ordinato e riutilizzabile. Per venire incontro alle esigenze di tutti vi segnalo l'esistenza di AdFind scaricabile da qui. Si tratta di un programma molto versatile ma ad un primo impatto risulterà altrettanto complicato da utilizzare, in questa pagina potete trovare il suo manuale completo.

Innanzitutto occorre dire che con AdFind avrei potuto digitare la seguente stringa per avere lo stesso risultato ottenuto con ldp.exe

AdFind.exe -h localhost -p 389 -u TESTDOMAIN\Administrator -up P@ssw0rd -s Subtree -b "OU=Domain Users,DC=testdomain,DC=lan" -f "objectclass=user" memberOf
ldap19.PNG


AdFind mette però a disposizione alcune funzionalità avanzate che permettono di reindirizzare l'output in un file di testo o csv, nonché di migliorare, ordinare e filtrare i risultati. Il comando di cui sopra potrebbe in realtà essere nettamente semplificato: poiché il computer dal quale l'ho eseguito fa parte di un dominio non dovrebbe essere necessario specificare i dati di connessione al server LDAP, quest'ultimo verrà selezionato automaticamente sfruttando le funzionalità di Active Directory e per il binding verranno utilizzate le credenziali fornite da una autenticazione Windows integrata.

Osservate il risultato, nettamente più pulito del precedente, che ottengo utilizzando la seguente stringa di ricerca semplificata

AdFind.exe -s Subtree -b "OU=Domain Users,DC=testdomain,DC=lan" -f -nodn -noctl -list "objectclass=user" cn memberOf
ldap20.PNG


Mirko Iodice
CN=Italy Admins,OU=Domain Groups,DC=testdomain,DC=lan
CN=IT Department,OU=Domain Groups,DC=testdomain,DC=lan
Mario Rossi

I filtri di ricerca nel dettaglio

Abbiamo visto che sia ldp.exe che AdFind permettono di estrapolare informazioni mediante l'applicazione di un filtro di ricerca (mi riferisco al campo Filter di ldp.exe o allo switch -f di Adfind), precedentemente non sono sceso nel dettaglio e mi sono limitato ad utilizzare un semplice (objectclass=user) per ricercare tutti gli oggetti di classe utente, ora però voglio mostrarvi qualche altra possibilità...

(memberOf=CN=IT Department,OU=Domain Groups,DC=testdomain,DC=lan)

Mi permetterebbe di visualizzare gli attributi di tutti gli oggetti che fanno parte del gruppo IT Department. memberOf è un attributo di tipo Distinguished Name quindi quando viene utilizzato come filtro non supporta wildcard e va obbligatoriamente specificato per intero.

(&(objectcategory=user)(memberOf=CN=IT Department,OU=Domain Groups,DC=testdomain,DC=lan))

Un esempio di filtro multiplo, visualizzerà gli attributi dei soli oggetti di classe user che fanno parte del gruppo IT Department

(&(objectcategory=user)(!(memberOf=CN=IT Department,OU=Domain Groups,DC=testdomain,DC=lan)))

Quest'altro filtro invece è di esclusione e visualizzerà gli attributi di tutti gli oggetti di classe user che NON fanno parte del gruppo IT Department

Qualche altra idea? ...

(physicalDeliveryOfficeName=*Verona*)
(badPwdCount=1)

LDAP nella vita quotidiana di un amministratore

Oltre all'attività di ricerca informazioni all'interno del database della directory voglio darvi almeno altri due motivi per i quali una conoscenza basilare di LDAP può tornarvi utile in qualsiasi momento: WSH Scripting con ADSI ed Active Directory Authoritative Restore.

Gli script "Find And Move Specified Users To A New OU" e "List All Computers And Users Within An OU And SubOUs" che potete trovare nella mia sezione scripts sono soltanto un piccolo assaggio di come sia possibile creare procedure amministrative per Active Directory, un esempio ancora più interessante è costituito dal seguente script che è in grado di resettare la password (rendendone obbligatoria la modifica al prossimo logon) di tutti gli utenti contenuti in una specifica OU.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
' StudentPwd.vbs
' Source http://www.computerperformance.co.uk/ezine/ezine83.htm
' Example VBScript to change a user's password
' Version 2.0 - August 2005
' ---------------------------------------------------------'
Option Explicit
Dim objOU, objUser, objRootDSE
Dim strContainer, strDNSDomain, strPassword
Dim intCounter, intAccValue, intPwdValue
 
' --------------------------------------------------------'
' Note: Please change OU=nowhere, to reflect your domain
' --------------------------------------------------------'
strContainer = "OU=nowhere, "
strPassword = "H0l1d@y$"
intAccValue = 544
intPwdValue = 0
intCounter = 0
' -------------------------------------------------------'
' Makes the user change H0l1d@y$ password at first logon
' -------------------------------------------------------'
 
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
strContainer = strContainer & strDNSDomain
set objOU =GetObject("LDAP://" & strContainer )
 
For each objUser in objOU
	If objUser.class="user" then
		objUser.SetPassword strPassword
		objUser.SetInfo
		objUser.Put "pwdLastSet", intPwdValue
		objUser.SetInfo
		objUser.Put "userAccountControl", intAccValue
		objUser.SetInfo
		intCounter = intCounter +1
	End if
next
 
WScript.Echo strPassword & " is Password. UserAccountValue = " _
& intAccValue & vbCr & intCounter & " accounts changed"
WScript.Quit
 
' End of change password example VBScript

Una interessante introduzione all'utilizzo di LDAP in VBScript la potete leggere nell'articolo Walking the AD Tree riportato da computerperfomance.co.uk.

Autore

Mirko Iodice
mirko -at- notageek (.dot) it

Suggeriti dall'autore

Print This Email this Twit This! Add to del.icio.us Share on Facebook Digg This! Stumble It! AddThis! Share on Segnalo Alice Share on OKNotizie

Post Metadata

Data
9 Gennaio 2008

Autore
Mirko

Categorie

24 commenti a “LDAP per Amministratori Active Directory – LDAP for Active Directory Administrators”




  1. Search:
    Base Dn: Ou = Domain Users, Dc=notageek.it, Dc=it
    Filter: (objectclass=Author)
    Attributes: VotoArticolo

    go....

    Getting One Entries...
    >> Dn: Cn=Mirko Iodice.Ou=Domain Users.Dc=notageek.Dc=it
    >>Name: Mirko Iodice
    >>Rank: Author
    >>VotoArticolo= 10...Come Sempre....;)

    Ciao

    Rispondi



  2. @ 5og7i@n0
    ahah! Commento originale, veramente... ;-)

    Rispondi



  3. Ciao,
    Ti faccio una domanda di una cosa che non mi è chiara:

    Se voglio ottenere una lista di utenti da una OU contenuta in un altra OU come devo fare?
    "OU=nomeOu"
    oppure
    "OU=PrimaOu, Ou=SecondaOu" ? ed eventualmente quale si mette prima?

    Per il resto mi sembra di aver capito(speriamo).
    L'articolo era molto interessante.
    Ciao e alla prossima

    Giacomo

    Rispondi



  4. @ Giacomo
    Ciao,
    per creare il Base Dn iniziale devi partire dal livello più basso, ovvero la OU che contiene gli oggetti stessi, e risalire nella struttura ad albero fino ad arrivare alle componenti di dominio. Ad esempio: per operare sugli utenti che si trovano all'interno dell'unità organizzativa "IT" che a sua volta è contenuta nell'unità organizzativa "Utenti" del dominio "test.lan", dovrai settare il seguente Base Dn - OU=IT,OU=Utenti,DC=test,DC=lan

    Rispondi



  5. @Mirko
    Ciao se volessi operare contemporaneamente su due OU di pari livello lo posso fare? Che base dn dovrei specificare? Quella di libello superiore? Grazie

    Rispondi



  6. @Andrea
    Se ti riferisci al vbscripting sì, il basedn sarà il livello superiore e poi ti sposterai nelle sottounità, ad esempio, per mezzo di ricorsione.

    Rispondi



  7. ciao,
    e se volessi inserire questi script in un'interfaccia web, avresti qualche idea di come dovrei fare ??
    bell'articolo,
    grazie
    ciao

    Rispondi



  8. @Jean
    Sinceramente non lo so, non ho mai fatto nulla del genere. Penso però che con ASP tu possa eseguire scripts WSH per poi leggerne il risultato... più o meno nello stesso modo in cui con WSH si possono eseguire dei comandi shell. Alternativamente potresti creare una HTA: http://msdn.microsoft.com/en-us/library/ms536496.aspx ... un esempio: http://www.vbshf.com/vbshf/forum/forums/thread-view.asp?tid=309&posts=5&start=1

    Rispondi



  9. Ciao,
    avrei bisogno di una info..se ho necessità di togliere il logon script presente sul profile di più utenti come posso fare per evitare di entrare su ogni utente e cancellarlo a mano?c'è un modo per automatizzarlo?

    Rispondi



  10. @Silvia
    Ciao,
    il codice adatto a risolvere la tua problematica lo trovi qui: http://www.microsoft.com/technet/scriptcenter/resources/qanda/sept05/hey0908.mspx
    Per adattarlo alla tua rete dovrai modificarne la stringa di connessione ed il parametro "ADS_SCOPE_SUBTREE"
    Tale script utilizza la stessa logica di quello che ho presentato nel mio articolo WSH ADSI - Estrarre da Active Directory informazioni sugli account computer, ti invito perciò a leggerne la sezione "Impostare lo scope per la ricerca degli oggetti computer" per avere maggiori informazioni su come effettuare le due modifiche alle quali ti ho accennato.

    Rispondi



  11. Finalmente un po' di chiarezza su legame tra ldap e ad. Grazie per la guida, ben scritta, chiara, ed esaustiva.

    Complimenti e Saluti
    Armando

    Rispondi



  12. Ciao Mirko, avrei bisogno di modificare la descrizione di un migliaio di utenti nell'AD dell'azienda dove lavoro. Mi potresti indirizzare verso uno script che possa farlo in automatico magari leggendo la lista utenti sui quali effettuare la modifica da un file di testo ? gli utenti si trovano in differenti OU e sono mischiati con altri ai quali la descrizione non va invece modificata, praticamente ne devo modificare circa 1000 su un totale di 2500 e la descrizione sara' la stessa per tutti. La ricerca dei vari utenti dovrebbe essere fatta a livello di dominio senza specificare le differenti OU per velocizzare tutto il processo, che dici c'e' un qualche script che possa fare al mio caso?
    grazie

    Rispondi



    • @Andrea
      per una cosa così semplice non utilizzerei vbscript ma Powershell.

      Se utilizzi un Domain Controller Widnows 2008 R2 hai già tutto quello che ti serve.

      Se utilizzi un Domain Controller Windows 2003/2008 devi installare Powershell e ActiveRoles Management Shell for Active Directory di QuestSoftware.

      Di seguito un banale script utilizzabile su Windows 2003/2008 con ActiveRoles Management Shell for Active Directory:

      $inputFile = Get-Content users.txt
      
      foreach($line in $inputFile)
      {
          Set-QADUser -Identity $line -Description "Descrizione di prova"
      }
      

      Lo stesso script può essere rapidamente adattato anche per l'uso su Windows 2008 R2 con Active Directory Module for Windows Powershell:

      $inputFile = Get-Content users.txt
      
      foreach($line in $inputFile)
      {
          Set-ADUser -Identity $line -Description "Descrizione di prova"
      }
      

      Il file users.txt deve contenere un singolo nome utente per riga.

      L'unica vera differenza tra i due script è che nel primo caso (2003/2008) la lista degli utenti può contenere sia il semplice Username che il DisplayName, mentre nel secondo caso (2008 R2) la lista deve contenere obbligatoriamente lo Username.
      Se preferisci utilizzare il DisplayName anche nel secondo caso allora lo script ha bisogno di qualche modifica:

      $inputFile = Get-Content users.txt
      
      foreach($line in $inputFile)
      {
          Get-AdUser -filter 'Name -like $line' | Set-ADUser -Description "Descrizione di prova"
      }
      

      P.S: esiste la possibilità di installare ActiveRoles Management Shell for Active Directory di QuestSoftware anche su Windows 2008 R2, a questo punto potresti utilizzare il primo degli script che ti ho indicato senza ulteriori complicazioni.

      Rispondi



      • Ciao Mirko, ti ringrazio per l'aiuto! Qui in azienda utilizzano Windows 2008 R2 e il file users che ho contiene i display name (in questo caso COGNOME NOME) e quindi provero' ad utlizzare l'ultimo degli script ch mi hai indicato.
        Avrei ancora alcune cose da chiederti..
        Potrebbe verificarsi il caso che il file utenti.txt non sia accurato al 100% ed alcuni utenti siano stati cancellati dall'AD e quindi vorrei evitare che si blocchi l'esecuzione dello script nel caso in cui un utente non venga trovato e far si quindi che si passi al successivo utente automaticamente.

        Sarebbe inoltre possibile spostare ogni utente in una determinata OU oltre all'aggiunta della descrizione ? Praticamente ho piu files utenti.txt divisi per ufficio ma nell'AD invece sono messi tutti mischiati tra di loro. Mi andrei a creare le OU necessarie nell'AD e quindi sarebbe utile se potessi spostare automaticamente l'utente specificando il percorso dell'OU direttamente nello script.

        Ultimo chiarimento... avro' necessita in seguito di fare la stessa cosa per i computers presenti in AD, va bene lo stesso script sostituendo Get-ADComputer al posto di Get-ADUser o serve qualcos'altro ?
        Grazie.

        Rispondi



        • @Andrea
          l'esecuzione dello script non si blocca se un oggetto non viene trovato.

          Per spostare gli oggetti si utilizza il comando Move-ADObject, di seguito un esempio di script completo:

          $inputFile = Get-Content users.txt
          
          foreach($line in $inputFile)
          {
          	$User = Get-AdUser -filter 'Name -like $line'
          	Set-ADUser -Identity $User -Description "Descrizione di prova"
          	Move-ADObject -Identity $User -TargetPath 'OU=Test,DC=dominio,DC=lan'
          }
          

          Tieni presente che con una piccolissima modifica lo script di cui sopra potrebbe accettare in input anche un CSV, a quel punto saresti in grado di gestire in un unico file utenti con descrizioni e posizioni diverse:

          $inputFile = Import-CSV users.txt
          
          foreach($line in $inputFile)
          {
          	$strUserName = $line.UserName
          	$strDescription = $line.Description
          	$strTargetPath = $line.TargetPath
          	$User = Get-AdUser -filter 'Name -like $strUserName'
          	Set-ADUser -Identity $User -Description $strDescription
          	Move-ADObject -Identity $User -TargetPath $strTargetPath
          }
          

          La prima riga del CSV deve contenere le intestazioni delle colonne, esempio:

          UserName,Description,TargetPath
          Utente 1,Descrizione di Utente 1,"OU=Test1,DC=dominio,DC=lan"
          Utente 2,Descrizione di Utente 2,"OU=Test2,DC=dominio,DC=lan"
          

          Riguardo agli account computer: sì, sarà sufficiente sostituire "Get-ADUser" e "Set-ADUser" con "Get-ADComputer" e "Set-ADComputer". "Move-ADObject" rimane invece invariato.

          Rispondi



  13. Grazie per il tuo aiuto, ho provato lo script e funziona benissimo.. fa tutto quello che deve fare solo che mi restituisce una serie di errori:

    Set-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null. Supply a non-null argument and try
    the command again.
    At line:7 char:25
    + Set-ADUser -Identity <<<< $User -Description $strDescription
    + CategoryInfo : InvalidData: (:) [Set-ADUser], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.SetADUser

    Move-ADObject : Cannot validate argument on parameter 'Identity'. The argument is null. Supply a non-null argument and
    try the command again.
    At line:8 char:28
    + Move-ADObject -Identity <<<< $User -TargetPath $strTargetPath
    + CategoryInfo : InvalidData: (:) [Move-ADObject], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.MoveADObj
    ect

    Praticamente mi da questi 2 errori su tutte le linee (qui ne ho riportate solo 2) ma nonostante questo come ti ho gia detto funziona bene, mi aggiunge la descrizione e mi fa anche il move.
    Sembra che l'argomento fornito per -Identity non sia valido perche vuoto ma poi pero' viene modificato lo stesso in AD; ho bisogno di cambiare qualcosa o sono errori normali ?

    Grazie

    Rispondi



    • @Andrea
      dagli errori posso dedurre che stai utilizzando la versione con CSV.

      Questo errore è normale per tutti gli utenti che non vengono trovati in Active Directory, questo perché come argomento -Identity (obbligatorio) viene fornita la variabile $User e tale variabile equivale all'oggetto utente ottenuto tramite il comando Get-ADUser:

      Get-AdUser -filter 'Name -like $strUserName'

      L'unico caso in cui la variabile $User può risultare "null" è quando il comando Get-ADUser non da nessun risultato.

      Puoi mettere in evidenza tutti gli utenti non trovati in questo modo:

      $inputFile = Import-CSV users.txt
      
      foreach($line in $inputFile)
      {
      	$strUserName = $line.UserName
      	$User = Get-AdUser -filter 'Name -like $strUserName'
      	If ($User -eq $null) {
      		Write-Output "$strUserName non trovato"
      	}	
      }
      

      Sfruttando il sistema di cui sopra si potrebbe scrivere uno script più completo e quindi comprensivo di un semplice sistema di error handling:

      $inputFile = Import-CSV users.txt
      
      foreach($line in $inputFile)
      {
      	$strUserName = $line.UserName
      	$strDescription = $line.Description
      	$strTargetPath = $line.TargetPath
      	$User = Get-AdUser -filter 'Name -like $strUserName'
      	If ($User -eq $null) {
      		Write-Output "$strUserName -> Utente non trovato"
      	}
      	Else {
      		Try {
      			Set-ADUser -Identity $User -Description $strDescription
      		}
      		Catch {
      			Write-Output "$strUserName -> Errore Set-ADUser"
      		}
      		Try {
      			Move-ADObject -Identity $User -TargetPath $strTargetPath
      		}
      		Catch {
      			Write-Output "$strUserName -> Errore Move-ADObject"
      		}
      	}
      }
      

      Così facendo ti verranno riportate a video (in maniera controllata) tutte quelle operazioni che non sono andate a buon fine.

      Rispondi



  14. Si sto usando la versione con CSV che e' perfetta per quello che mi serve.. mi era venuto il dubbio che l'errore fosse relativo agli oggetti non trovati, ora comunque provero anche questa versione con error-handling poiche una lista di oggetti mancanti puo essere sempre utile.
    Ti chiedererei l'ultima cosa.. nel caso volessi applicare lo script solamente ad una determinata OU (ed eventuali sotto-OU) piuttosto che all'intero dominio cosa bisogna aggiungere ?
    grazie

    Rispondi



    • @Andrea
      Devi aggiungere delle opzioni al comando Get-ADUser:

      $User = Get-AdUser -SearchScope Subtree -SearchBase "OU=Test,DC=dominio,DC=lan" -filter 'Name -like $strUserName'
      

      L'opzione -SearchScope può essere impostata con i seguenti valori:
      - Base
      - OneLevel
      - Subtree

      Rispondi



  15. perfetto, funziona tutto!! grazie mille per l'aiuto, mi hai risolto parecchi problemi!

    Rispondi



  16. Ciao Mirko,
    ti disturbo ancora :) mi puoi indicare se e' possibile e cosa dovrei cambiare nello script nel caso in cui non voglia cambiare tutta la descrizione con una nuova specificata nel file csv ma solamente aggiungere qualcosa (tipo numeri o parole) prima o dopo a quella gia esistente senza quindi cancellarla?
    mi tornerebbe utile per evidenziare subito quali oggetti ho modificato dato che spesso e volentieri i file csv di cui sono in possesso non corrispondono agli oggetti in AD.
    Grazie

    Rispondi



    • Ciao Andrea,

      $inputFile = Import-CSV users.txt
      
      foreach($line in $inputFile)
      {
      	$strUserName = $line.UserName
      	$strTargetPath = $line.TargetPath
      	$strPreDescription = $line.PreDescription
      	$strPostDescription = $line.PostDescription
      	$User = Get-AdUser -filter 'Name -like $strUserName' -Properties Description
      	If ($User -eq $null) {
      		Write-Output "$strUserName -> Utente non trovato"
      	}
      	Else {
      		$strDescription = $User.Description
      		Try {
      			Set-ADUser -Identity $User -Description "$strPreDescription $strDescription $strPostDescription"
      		}
      		Catch {
      			Write-Output "$strUserName -> Errore Set-ADUser"
      		}
      		Try {
      			Move-ADObject -Identity $User -TargetPath $strTargetPath
      		}
      		Catch {
      			Write-Output "$strUserName -> Errore Move-ADObject"
      		}
      	}
      }
      

      Ho preso come base l'ultimo esempio che ti avevo fatto.
      Come vedi la variabile "$strDescription" ora viene ricavata dall'oggetto "$User" e contemporaneamente ho aggiunto due nuove variabili "$strPreDescription" e "$strPostDescription", il loro valore equivale ai campi "PreDescription" e "PostDescription" del file CSV. Di seguito un esempio del file CSV:

      UserName,PreDescription,PostDescription,TargetPath
      Utente A,Pre desc 1,Post desc 1,"OU=Test,DC=dominio,DC=lan"
      Utente B,Pre desc 1,Post desc 1,"OU=Test,DC=dominio,DC=lan"
      

      Rispondi



  17. Ciao Mirco,
    scusami se ti disturbo, ma ho un problemino da risolvere. Spero tu possa aiutarmi. Mi è stato chiesto di risalire dato un indirizzo IP a tutti i nomi, e gli alias associati, nel dns server, ovviamente in una foresta che contiene una cinquantina di zone/domini, tutte integrate in active directory. Tramite query ldap o script, si riesce a risalire a questi dati? Potresti aiutarmi per favore? Grazie.

    Rispondi


2 Trackbacks/Pingbacks

  1. Interrogare un server LDAP con Python « intelligenti pauca 21 07 11
  2. Interrogare un server LDAP « opuntia.biz 28 02 12

Lascia un commento