Amministrazione di Windows

Semplificare l'amministrazione dei Criteri di gruppo con Windows PowerShell

Thorbjörn Sjövold

 

Panoramica:

  • Che cos'è Windows PowerShell?
  • Come venivano gestiti in precedenza gli oggetti Criteri di gruppo
  • Migrazione di script a Windows PowerShell

La tecnologia dei Criteri di gruppo di Microsoft non si è diffusa in quattro e quattr'otto: è stato alquanto difficile comprenderla e ha richiesto l'adozione di Active Directory, un nuovo servizio del tutto sconosciuto, per nulla simile ai domini account/risorsa che all'epoca costituivano lo standard. Attualmente Criteri di gruppo

costituisce la struttura portante della gestione di quasi tutte le organizzazioni che impiegano un'infrastruttura Windows®. Secondo me succederà la stessa cosa con Windows PowerShell™, la più recente tecnologia di gestione messa a punto da Microsoft. È infatti molto probabile che con Windows PowerShell il lavoro degli amministratori di Criteri di gruppo venga notevolmente semplificato.

In questo articolo illustrerò come sia possibile utilizzare le API della console Gestione Criteri di gruppo (GPMC) Microsoft®, scritte per i linguaggi di Windows Scripting Host, come VBScript e, in generale, per i linguaggi di script basati su COM, per semplificare la gestione di Criteri di gruppo nell'ambiente.

Attività di script di Criteri di gruppo

Con il rilascio della console Gestione Criteri di gruppo qualche anno fa, Microsoft ha messo a disposizione degli amministratori di Criteri di gruppo molte funzionalità utili. In particolare, lo snap-in MMC per Criteri di gruppo ha rappresentato un notevole passo avanti per la gestione di Criteri di gruppo, soprattutto rispetto a Utenti e computer di Active Directory®. Era inoltre inclusa una nuova API che consentiva agli amministratori di utilizzare i linguaggi basati su COM, come VBScript, per eseguire attività di amministrazione di Criteri di gruppo, quali il backup e il ripristino di oggetti Criteri di gruppo, la migrazione di oggetti Criteri di gruppo fra domini, la configurazione delle impostazioni di protezione di oggetti Criteri di gruppo e collegamenti, nonché la generazione di report.

Purtroppo nella console Gestione Criteri di gruppo non è stata fornita la capacità di modificare le impostazioni effettivamente configurate negli oggetti Criteri di gruppo. In altre parole è possibile eseguire operazioni sul contenitore Oggetti Criteri di gruppo, quali leggere le versioni degli Oggetti Criteri di gruppo o le date di modifica, creare nuovi Oggetti Criteri di gruppo, eseguire il backup e il ripristino o l'impostazione di Oggetti Criteri di gruppo da domini diversi e così via, ma non è possibile aggiungere o modificare a livello di programmazione il contenuto dell'Oggetto Criteri di gruppo, ad esempio aggiungendo una nuova cartella reindirizzata o una nuova installazione software. In genere, si procedeva invece creando l'Oggetto Criteri di gruppo e configurando manualmente tutte le impostazioni tramite l'Editor oggetti Criteri di gruppo, quindi si eseguiva il backup dell'oggetto e lo si importava in un ambiente di prova. Dopo avere verificato che tutto funzionasse correttamente, lo si importava nell'ambiente di utilizzo. Malgrado l'assenza di funzionalità, l'utilizzo di script in luogo dell'interazione manuale con l'API GPMC consente un enorme risparmio di tempo e di sforzi, nonché riduce gli errori commessi durante le attività quotidiane di amministrazione di Criteri di gruppo.

Il livello successivo

In che cosa Windows PowerShell differisce dai linguaggi di script come VBScript? Per i principianti, Windows PowerShell è una shell e, almeno ai fini qui contemplati, una shell può essere considerata come un interprete della riga di comando. Nonostante sia possibile eseguire VBScript dalla riga di comando, non è possibile eseguire riga per riga un file VBScript. Al contrario, è possibile creare in tempo reale uno script di Windows PowerShell come una serie di comandi singoli. In Windows PowerShell sono disponibili funzioni operanti come subroutine di VBScript che è possibile creare in tempo reale dal prompt dei comandi di Windows PowerShell.

Per di più, Windows PowerShell è basato su Microsoft .NET Framework, mentre VBScript è basato su una tecnologia COM precedente. Pertanto, la grande quantità di codice .NET che oggi viene prodotta potrà essere utilizzata direttamente da Windows PowerShell.

Se ne deduce che Windows PowerShell offre un supporto completo per gli script e una modalità interattiva, il tutto in un pacchetto. Gli esempi riportati di seguito sono tutti costituiti da input della riga di comando da digitare così come li si legge, ma tuttavia funzioneranno altrettanto bene se vengono inseriti ed eseguiti in un file script di Windows PowerShell.

Ricreare i vecchi script utilizzando Windows PowerShell

L'ultima cosa da fare quando si adotta una nuova tecnologia è non considerare tutto il lavoro precedente. Per accedere agli oggetti COM dall'API GPMC o fondamentalmente riutilizzare qualsiasi codice VBScript già disponibile, è possibile scegliere uno dei tre approcci qui indicati:

  • Creare un cmdlet di Windows PowerShell utilizzando un linguaggio di programmazione come C# o C++ gestito.
  • Utilizzare Windows PowerShell per accedere all'oggetto ScriptControl contenuto in MSScript.ocx per inserire gli script esistenti.
  • Inserire le chiamate COM in funzioni riutilizzabili di Windows PowerShell o, in alternativa, chiamare direttamente gli oggetti COM.

Adotterò soprattutto il terzo approccio, ma vediamo prima rapidamente in che cosa consistono gli altri.

Creazione di un cmdlet in Windows PowerShell

Microsoft ha incluso molti cmdlet Windows PowerShell per consentire la copia dei file, la formattazione dell'output, il recupero di data e ora, e così via, ma è anche possibile creare i cmdlet autonomamente. La procedura è descritta in maniera dettagliata nell'articolo riportato alla pagina msdn2.microsoft.com/ms714598.aspx. Riassumo brevemente i passaggi:

  • Creare una DLL contenente una libreria di classi in uno dei linguaggi di programmazione di .NET, ad esempio C#.
  • Creare una nuova classe ed ereditare dal cmdlet della classe di base.
  • Impostare gli attributi che determinano il nome, l'utilizzo, i parametri di input, e così via, quindi aggiungere il codice.

Considerato che Windows PowerShell si basa su .NET Framework, i tipi presenti nel codice, quali stringa, oggetto e così via, restituiti o inviati come parametri sono identici a quelli di Windows PowerShell, non è pertanto necessaria alcuna conversione tipo speciale.

Il punto di forza di questa soluzione è che si ha a disposizione un linguaggio di programmazione completo.

Inserimento di script esistenti tramite l'oggetto ScriptControl contenuto in MSSCRIPT.ocx

Ovviamente per eseguire un file VBScript è necessario il motore VBScript. Non altrettanto ovvio è che questo motore è un oggetto COM e, visto che è possibile utilizzare oggetti COM da Windows PowerShell, è possibile richiamare il motore VBScript. Ecco un esempio di come potrebbe presentarsi il codice:

$scriptControl = New-Object -ComObject ScriptControl
$scriptControl.Language = ‘VBScript’
$scriptControl.AddCode(
    ‘Function ShowMessage(messageToDisplay)
    MsgBox messageToDisplay
    End Function’)
$scriptControl.ExecuteStatement(‘ShowMessage
    “Hello World”’)

Se il codice viene inserito nell'interfaccia della riga di comando di Windows PowerShell, la funzione ShowMessage di VBScript verrà richiamata ed eseguita con un parametro e come risultato verrà visualizzata una finestra di messaggio contenente il testo Hello World.

Alcuni lettori potrebbero pensare: "Fantastico! Ho già capito come utilizzare COM con Windows PowerShell e quindi posso smettere di leggere l'articolo e cominciare a riempire l'oggetto ScriptControl con la mia raccolta di script GPMC esistenti". Purtroppo non è così. Questa tecnica diventa rapidamente molto complessa e quando gli script aumentano di dimensioni eseguire il debug è tutt'altro che semplice.

Disposizione di oggetti COM

L'opzione migliore è dunque la terza: disporre le chiamate COM in funzioni di Windows PowerShell riutilizzabili che consentono di utilizzare gli oggetti COM nell'API GPMC. Nella riga seguente viene illustrato come creare un oggetto .NET direttamente in Windows PowerShell. In questo caso, si tratta di un oggetto FileInfo che può essere utilizzato per ottenere la dimensione del file:

$netObject = New-Object System.IO.FileInfo(
“C:\boot.ini”) # Create an instance of FileInfo 
               # representing c:\boot.ini

Si noti che per i commenti in linea in Windows PowerShell viene utilizzato il simbolo del cancelletto (#). Servendosi di questo oggetto FileInfo del quale è appena stata creata una nuova istanza, è possibile ottenere con facilità la dimensione del file boot.ini semplicemente digitando il codice seguente:

$netObject.Length # Display the size in bytes of the
                  # file in the command line interface

Un attimo, non dovevamo parlare degli oggetti COM e della conversione in VBScript? Ebbene sì, ma diamo un'occhiata al comando seguente:

$comFileSystemObject = New-Object –ComObject Scripting.FileSystemObject

È possibile osservare che la sintassi è sostanzialmente identica a quella utilizzata in precedenza per creare oggetti nativi da .NET Framework, con due differenze. Innanzitutto, ho aggiunto l'opzione -ComObject la quale fa sì che Windows PowerShell punti al mondo COM anziché al mondo .NET. Secondariamente, utilizzo un ProgID COM anziché un costruttore .NET, in questo caso Scripting.FileSystemObject. ProgID è lo stesso nome che viene sempre utilizzato. L'equivalente in VBScript sarebbe:

Set comFileSystemObject = CreateObject(
    “Scripting.FileSystemObject”)

Per ottenere la dimensione del file utilizzando VBScript aggiungere in un file la riga sopra riportata, unitamente al codice seguente:

Set comFileObject = comFileSystemObject.GetFile(
    “C:\Boot.ini”)
WScript.Echo comFileObject.Size

Quindi eseguirlo utilizzando ad esempio Cscript.exe. In Windows PowerShell, la procedura dovrebbe essere come illustrato di seguito, anche eseguendo il codice direttamente dalla riga di comando, se lo si desidera:

$comFileObject = $comFileSystemObject.GetFile(
    “C:\boot.ini”)
$comFileObject.Size

Certo, per convertire uno script VBScript in grado di leggere la dimensione di un file avrei potuto utilizzare il cmdlet di Windows PowerShell che gestisce gli oggetti nelle unità, ma ho preferito dimostrare quanto è facile accedere a COM da Windows PowerShell. Si osservi che nonostante venga fornita a Windows PowerShell l'istruzione di creare un oggetto COM, l'oggetto creato, $il comFileSystemObject, in realtà è un oggetto .NET che inserisce l'oggetto COM e ne espone l'interfaccia. Ai fini di quest'articolo, tuttavia, non è un dettaglio molto rilevante.

Windows PowerShell in azione

Dopo aver visto come accedere a COM da Windows PowerShell, concentriamoci su Criteri di gruppo. Negli esempi qui riportati sono illustrati frammenti di codice che forniscono un'idea di come utilizzare l'API GPMC da Windows PowerShell, ma nel download correlato a questo articolo, in linea all'indirizzo technetmagazine.com/code07.aspx, è disponibile una serie completa di funzioni Windows PowerShell per la gestione di Criteri di gruppo. Nella Figura 1 sono elencate le funzioni incluse nel download.

Figure 1 Funzioni personalizzate disponibili nel download

Nome funzione Descrizione
BackupAllGpos Esegue il backup di tutti gli oggetti Criteri di gruppo compresi in un dominio
BackupGpo Esegue il backup di un solo oggetto Criteri di gruppo
RestoreAllGpos Ripristina tutti gli oggetti Criteri di gruppo in un dominio da un backup
RestoreGpo Ripristina un solo oggetto Criteri di gruppo da un backup
GetAllBackedUpGpos Recupera la versione più recente dei backup di oggetti Criteri di gruppo da un determinato percorso
CopyGpo Copia le impostazioni di un oggetto Criteri di gruppo in un altro oggetto Criteri di gruppo
CreateGpo Crea un nuovo oggetto Criteri di gruppo vuoto
DeleteGpo Elimina un oggetto Criteri di gruppo
FindDisabledGpos Restituisce tutti gli oggetti Criteri di gruppo in cui sia la parte utente sia la parte computer sono disattivate
FindUnlinkedGpos Restituisce tutti gli oggetti Criteri di gruppo privi di collegamenti
CreateReportForGpo Crea un report XML per un solo oggetto Criteri di gruppo di un dominio
CreateReportForAllGpos Crea un report XML separato per ogni oggetto Criteri di gruppo di un dominio
GetGpoByNameOrID Trova un oggetto Criteri di gruppo in base al relativo nome visualizzato o ID
GetBackupByNameOrId Trova il backup di un oggetto Criteri di gruppo in base al relativo nome visualizzato o ID
GetAllGposInDomain Restituisce tutti gli oggetti Criteri di gruppo di un dominio

È possibile avviare la riga di comando di Windows PowerShell e digitare i comandi mentre si legge questa sezione. Tenere presente tuttavia che alcuni comandi dipendono dai precedenti. Vale a dire che alcuni degli oggetti creati inizialmente verranno utilizzati in seguito, quindi è bene restare nella stessa sessione di Windows PowerShell. Se la si chiude, sarà necessario ricominciare da capo e ridigitare tutti i comandi.

Creiamo quindi un nuovo oggetto Criteri di gruppo utilizzando Windows PowerShell. Il team di Microsoft che si è occupato di Criteri di gruppo ha incluso nella console Gestione Criteri di gruppo vari esempi VBScript completamente funzionanti dei quali è possibile avvalersi per velocizzare le operazioni. Sono contenuti nella directory %Programmi%\GPMC\Scripts, nella quale è presente anche un file, denominato gpmc.chm, contenente la documentazione dell'API GPMC. Esaminiamo ora lo script CreateGPO.wsf e scomponiamolo in sezioni per capire come funziona.

Nella parte iniziale è presente la riga seguente:

Dim GPM
Set GPM = CreateObject(“GPMgmt.GPM”)

In pratica questa riga costituisce il punto di partenza di tutte le sessioni o script di gestione di Criteri di gruppo in quanto crea un'istanza della classe GPMgmt.GPM che consente l'accesso a gran parte della funzionalità della console Gestione Criteri di gruppo. Proseguiamo svolgendo invece le seguenti operazioni in Windows PowerShell:

$gpm = New-Object -ComObject GPMgmt.GPM

Ora che conosciamo il punto di partenza per la gestione di Criteri di gruppo, proviamo a immaginare come possiamo utilizzarla. In genere per questo tipo di informazioni ci si affida alla documentazione, ma Windows PowerShell dispone di una funzionalità davvero comoda. Digitando la riga seguente, si ottiene l'output illustrato nella Figura2:

Figura 2 Output di Get-Member

Figura 2** Output di Get-Member **(Fare clic sull'immagine per ingrandirla)

$gpm | gm

Niente male, secondo me. Si noti come il cmdlet Get-Member (o gm) consente di vedere le proprietà e i metodi supportati dall'oggetto dalla riga di comando. Certo, non è come leggere la documentazione, ma agevola l'utilizzo di oggetti già noti quando non si ricorda il numero esatto dei parametri, il nome preciso e così via. Un punto importante da sottolineare è che l'elenco dei nodi contenuto nella documentazione della console Gestione Criteri di gruppo è simile all'oggetto GPM e tutte le altre classi dispongono della lettera I come prefisso. Ciò è dovuto al funzionamento intrinseco di COM e in questa sede non è importante. Questo sistema è rivolto ai programmatori che utilizzano C++ per scrivere il codice COM nativo e denota la differenza tra un'interfaccia e la classe che la implementa. Inoltre, tenere presente che quando si utilizzano le API GPMC è necessario creare in questo modo soltanto un oggetto, ossia GPMgmt.GPM. Tutti gli altri oggetti vengono creati utilizzando metodi che partono da quest'oggetto GPM.

Continuiamo con la creazione di un nuovo oggetto Criteri di gruppo.

Nella Figura 3 è illustrato quanto sia semplice creare un oggetto Criteri di gruppo. Confesso di avere tralasciato parte del codice, compreso quella relativa alla gestione degli errori (ovvero ciò che succederebbe, ad esempio, se non si fosse autorizzati a creare oggetti Criteri di gruppo) e di avere specificato a livello di codice un nome di dominio, ma dovrebbe comunque rendere l'idea.

Figure 3 Creazione di un oggetto Criteri di gruppo

$gpmConstants = $gpm.GetConstants() 
# This is the GPMC way to retrieve all 
# constants
$gpmDomain =$gpm.GetDomain(“Mydomain.local”, “”, $gpmConstants.UseAnyDC)
# Connects to the domain where the GPO should 
# be created, replace Mydomain.local with the 
# name of the domain to connect to.
$gpmNewGpo = $gpmDomain.CreateGPO() 
# Create the GPO
$gpmNewGpo.DisplayName = “My New Windows PowerShell GPO” 
# Set the name of the GPO

Dopo aver descritto come creare un oggetto Criteri di gruppo, apriamone invece uno esistente. Il riferimento al dominio $il gpmDomain è tutt'ora valido, quindi digitiamo quanto segue:

$gpmExistingGpo = $gpmDomain.GetGPO(
  “{31B2F340-016D-11D2-945F-00C04FB984F9}”) 
# Open an existing GPO based on its GUID, 
# in this case the Default Domain Policy.
$gpmExistingGpo.DisplayName 
# Show the display name of the GPO, it 
# should say Default Domain Policy
$gpmExistingGpo.GenerateReportToFile($gpmConstants.ReportHTML, “.\DefaultDomainPolicyReport.html”

Viene generato un report HTML delle impostazioni contenute nel Criterio dominio predefinito, ma è naturalmente possibile utilizzare qualunque metodo e proprietà, come ModificationTime, che fornisce informazioni relative all'ultima volta in cui l'oggetto Criteri di gruppo è stato modificato, per scoprire quando sono state modificate le impostazioni dell'oggetto Criteri di gruppo.

Si tratta di una funzionalità estremamente utile. Probabilmente il telefono non la smetta più di suonare per tutte le chiamate degli utenti che si lamentano dello strano funzionamento dei loro computer. In tal caso, al programmatore viene il sospetto che il problema sia legato a un'impostazione dell'oggetto Criteri di gruppo modificata, aggiunta o eliminata, ma senza uno straccio di indizio su quale sia l'oggetto incriminato. Aiuto, Windows PowerShell! Immettendo nella riga di comando di Windows PowerShell lo script illustrato nella Figura 4, vengono visualizzati tutti gli oggetti Criteri di gruppo modificati durante le ultime 24 ore.

Figure 4 Individuazione degli oggetti Criteri di gruppo modificati

$gpmSearchCriteria = $gpm.CreateSearchCriteria() 
# We want all GPOs so no search criteria will be specified
$gpmAllGpos = $gpmDomain.SearchGPOs($gpmSearchCriteria) 
# Find all GPOs in the domain
foreach ($gpmGpo in $gpmAllGpos)
{
if ($gpmGpo.ModificationTime -ge (get-date).AddDays(-1)) {$gpmGpo.DisplayName}
# Check if the GPO has been modified less than 24 hours from now 
}

Si osservi l'operatore -ge, equivalente a maggiore di o uguale a. Potrebbe sembrare strano se si è abituati agli operatori < e > di altri linguaggi di script o di programmazione, ma tali operatori vengono utilizzati per il reindirizzamento, ad esempio per reindirizzare l'output al file, quindi non possono essere utilizzati come operatori di confronto in Windows PowerShell.

Disposizione testo

Nel codice illustrato nella Figura 5 è contenuto l'intero script per la copia delle impostazioni di un oggetto Criteri di gruppo in un altro oggetto Criteri di gruppo. A questo punto dovrebbe essere più chiaro come utilizzare questa nuova tecnologia con i Criteri di gruppo e come riutilizzare gli oggetti COM o il codice VBScript che utilizza un oggetto COM.

Figure 5 Copia delle impostazioni di un oggetto Criteri di gruppo in un altro oggetto Criteri di gruppo

###########################################################################
# Function  : CopyGpo
# Description: Copies the settings in a GPO to another GPO
# Parameters : $sourceGpo     - The GPO name or GPO ID of the GPO to copy
#           : $sourceDomain   - The dns name, such as microsoft.com, of the domain where the original GPO is located
#           : $targetGpo      - The GPO name of the GPO to add
#           : $targetDomain   - The dns name, such as microsoft.com, of the domain where the copy should be put
#           : $migrationTable - The path to an optional Migration table to use when copying the GPO
# Returns   : N/A
# Dependencies: Uses GetGpoByNameOrID, found in article download
###########################################################################
function CopyGpo(
 [string] $sourceGpo=$(throw ‘$sourceGpo is required’),
 [string] $sourceDomain=$(throw ‘$sourceDomain is required’),
 [string] $targetGpo=$(throw ‘$targetGpo is required’),
 [string] $targetDomain=$(throw ‘$targetDomain is required’),
 [string] $migrationTable=$(“”),
 [switch] $copyAcl)
{
 
 $gpm = New-Object -ComObject GPMgmt.GPM # Create the GPMC Main object
 $gpmConstants = $gpm.GetConstants() # Load the GPMC constants
 $gpmSourceDomain = $gpm.GetDomain($sourceDomain, “”, $gpmConstants.UseAnyDC) # Connect to the domain passed 
                                                                              # using any DC
 $gpmSourceGpo = GetGpoByNameOrID $sourceGpo $gpmSourceDomain
 # Handle situations where no or multiple GPOs was found
 switch ($gpmSourceGpo.Count)
 {
   {$_ -eq 0} {throw ‘No GPO named $gpoName found’; return}
   {$_ -gt 1} {throw ‘More than one GPO named $gpoName found’; return} 
 }
 if ($migrationTable)
 {
   $gpmMigrationTable = $gpm.GetMigrationTable($migrationTable)
 }

 $gpmTargetDomain = $gpm.GetDomain($targetDomain, “”, $gpmConstants.UseAnyDC) # Connect to the domain passed 
                                                                              # using any DC

 $copyFlags = 0
 if ($copyAcl)
 {
   $copyFlags = Constants.ProcessSecurity
 }
 $gpmResult = $gpmSourceGpo.CopyTo($copyFlags, $gpmTargetDomain, $targetGpo)
 [void] $gpmResult.OverallStatus
 
}

Windows PowerShell è destinato a diventare, proprio com'è avvenuto per Criteri di gruppo, parte integrante di tutti gli ambienti di gestione Windows. Ma nel mondo esistono milioni di righe di codice VBScript di cui eseguire la migrazione o la manutenzione e speriamo che questa esercitazione possa essere d'aiuto.

È disponibile molto materiale di consultazione utilizzabile per migliorare l'amministrazione di Criteri di gruppo e altri settori in cui è stato utilizzato precedentemente VBScript, comprese le funzioni Windows PowerShell disponibili nell'area download, unitamente a una guida utile per la conversione da VBScript a Windows PowerShell, disponibile sul sito Web di TechNet, che include suggerimenti su come svolgere attività comuni in Windows PowerShell quando si conosce l'equivalente in VBScript. L'indirizzo è il seguente: microsoft.com/technet/scriptcenter/topics/winpsh/convert.

L'API GPMC è inoltre corredata di una documentazione completa. Le informazioni possono essere scaricate dal sito di Criteri di gruppo, all'indirizzo microsoft.com/grouppolicy.

Infine chi non ha ancora installato Windows PowerShell, si affretti, potrà scaricarlo da microsoft.com/powershell. Buon divertimento.

Thorbjörn Sjövold è il fondatore e responsabile delle tecnologie di Special Operations Software (www.specopssoft.com), una società che fornisce prodotti per la gestione dei sistemi basata sui Criteri di gruppo e l'estensione della protezione. È possibile contattarlo inviando un messaggio all'indirizzo thorbjorn.sjovold@specopssoft.com.

© 2008 Microsoft Corporation e CMP Media, LLC. Tutti i diritti riservati. È vietata la riproduzione completa o parziale senza autorizzazione.