Contattaci

Gestire dati con PowerShell

powershell
  • Data: 20 Febbraio 2019
  • Autore: Alessio Giusti
  • Categorie

  • Giuneco Tech

    Il nostro settore richiede uno studio continuo e una forte attenzione all’innovazione. Incentiviamo quindi dei programmi formativi annuali per tutti i componenti del team, con ore dedicate (durante l’orario di lavoro) e serate formative sia online che in presenza. Sponsorizziamo eventi, sia come partner che semplicemente come partecipanti, e scriviamo articoli su quello che abbiamo imparato per essere, a nostra volta, dei divulgatori.

    Vai alla sezione Team
  • Può capitare di avere la necessità di dover gestire, allineare o integrare dati dai nostri sistemi interni a sistemi di condivisione documenti, come SharePoint, o a sistemi di gestione di utenti e relativi gruppi come Active Directory.
    Per fare ciò si possono utilizzare diverse tecnologie, tra le quali la generazione di script PowerShell.

    Prima di affrontare come realizzare script di integrazione con Sharepoint e Active Directory, è bene introdurre gli attori che utilizzeremo per la creazione dei nostri script.

    PowerShell

    Powershell è un ambiente di scripting integrato con .NET, gestito tramite CmdLet.
    Per sviluppare gli script possiamo utilizzare svariati editor, dal normale notepad ad editor integrati come Microsoft PowerShell ISE. L’estensione degli script PowerShell è “.ps1”.

    Cosa è un CmdLet

    Un CmdLet o Command-Let è un comando dato dall’utente al sistema, per ottenere una serie di informazioni.
    Se stampato a video, Powershell provvederà alla conversione in testo del risultato del cmdlet, altrimenti si otterrà uno o più oggetti da utilizzare nel proseguimento dello script.

    Per concatenare due o più CmdLet utilizziamo il simbolo “|” .
    Tutto ciò che viene inserito dopo tale simbolo manterrà il tipo restituito dal CmdLet precedente.

    Ad esempio:

    Get-ChildItem -Path "C:\Develop" 

    restituisce in forma testuale tutti gli elementi presenti nella cartella C:\Develop

    CmdLet
    Get-ChildItem -Path "C:\Develop " | %{$($_.Name)} 

    permette, invece, di ottenere la proprietà filename da tutti i file presenti all’interno della cartella C:\Develop

    Adesso scriviamo un nostro CmdLet:

    Potremmo, ad esempio, scrivere un CmdLet che ci restituisca una DataTable passando una connessione OLEDB e una QUERY.

    function LoadDataTable ($ConnString, $SqlQuery) 
    { 
    	$OLEDBConn = New-Object System.Data.OleDb.OleDbConnection($ConnString)            
    	$OLEDBConn.open() 
    	$readcmd = New-Object system.Data.OleDb.OleDbCommand($SqlQuery,$OLEDBConn)            
    	$readcmd.CommandTimeout = '300'            
    	$da = New-Object system.Data.OleDb.OleDbDataAdapter($readcmd)            
    	$dt = New-Object system.Data.datatable    
    	[void]$da.fill($dt) 
    	$OLEDBConn.close()   
    	return ,$dt
    }

    Note per la scrittura di un CmdLet:

    • Tutte le variabili nel contesto di PowerShell vengono precedute dal simbolo “$”.
    • Il CmdLet New-Object crea un’istanza di un oggetto .NET o COM
    • [void] serve a rendere l’output dell’operazione a null (poteva essere scritto anche <<operazione>> | Out-Null).
    • Il simbolo “,” inserito nella line “return ,$dt” serve a far restituire un oggetto di tipo DataTable; nel caso in cui tale simbolo non sia presente, PowerShell lo considererà come Object generico.

    Cosa si intende per “Moduli”

    I moduli (estensione .psm1) sono, di fatto, contenitori di CmdLet. La creazione, gestione e importazione dei moduli ci permette di scrivere solo una volta il contenuto dei nostri CmdLet e utilizzarli in più script.
    I moduli possono essere “installati” all’interno dell’ambiente PowerShell o importati di volta in volta all’interno degli script.

    Una volta definita la funzione che vogliamo introdurre nel nostro modulo, per renderla disponibile all’ambiente esterno dobbiamo utilizzare il comando Export-ModuleMember -function FunctionToExport.

    SharePoint

    Piccola definizione e introduzione di “SharePoint On Premises” ed “SharePoint OnLine”

    Si parla di SharePoint on Premises quando all’interno della nostra server farm è presente un server dedicato esclusivamente a SharePoint.

    Si parla invece di SharePoint OnLine quando si ottiene SharePoint attraverso i servizi rilasciati con Office365.

    Per la generazione dei nostri script di integrazione con PowerShell, nel caso in cui abbiamo un ambiente “On Premises” i moduli che ci permettono di interagire con SharePoint sono già integrati nel nostro server.

    Viceversa, nel caso OnLine, bisognerà provvedere all’installazione dei moduli SharePointPnP (rimandiamo al sito Microsoft per le istruzioni di installazione) o delle librerie CSOM (Client-Side Object Model)

    CSOM (Client-Side Object Model)

    É una libreria scaricabile dal sito di Microsoft, che fornisce l’accesso al modello a oggetti di SharePoint (on Premises/OnLine). I comandi PowerShell per la connessione e gestione dei siti SharePoint sono in gran parte wrapper di comandi CSOM.

    La libreria CSOM si può usare durante lo sviluppo di applicativi .NET o, come già accennato, all’interno di PowerShell.

    La programmazione in CSOM prevede la creazione di un oggetto di contesto (Microsoft.SharePoint.Client.ClientContext) passando nel costruttore la nostra Url del sito di SharePoint, un’operazione di Load delle risorse che vorremmo gestire e un’operazione di esecuzione “ExecuteQuery” per ottenere tali risorse.

    Ad esempio:

    $Url = “SharePoint web Url"
    $context = New-Object Microsoft.SharePoint.Client.ClientContext($Url) 
    $web = $context.Web
    $context.Load($web)
    $context.ExecuteQuery()

    SharePoint PnP

    È un modulo PowerShell che contiene tutti i CmdLet per poter connettere e gestire SharePoint OnLine.

    Sulle pagine PowerShell e Sharepoint di Microsoft è presente, oltre alle istruzioni per l’installazione e l’aggiornamento, la lista di tutti i  cmdlet presenti all’interno del modulo e il loro utilizzo.

    Proviamo a realizzare lo stesso script interamente scritto CSOM e utilizzando i CmdLet del modulo SharePointPnP per recuperare gli utenti e i gruppi che hanno accesso ad una particolare cartella (e relativi contenuti) del nostro sito SharePoint.

    Con Modulo SharePointPnP Con Modulo CSOM Uso
      Add-Type Importa le DLL all’interno dello script
    $context =  Connect-PnPOnline -Url $SharePointUrl -Credentials $Credential  $context = New-Object Microsoft.SharePoint.Client.ClientContext($SharePointUrl)
    $context.Credentials = $Credential
    $web = $context.Web
    $context.Load($web)
    $context.ExecuteQuery()
    Crea il contesto collegato al sito SharePoint
    $roleDefs = Get-PnPRoleDefinition -Connection
    $context
    $roleDefs | %{ Write-Host $_.RoleTypeKind }
    $roledefs = $web.RoleDefinitions
    $context.Load($roledefs)
    $context.ExecuteQuery()
    $roleDefs | %{ Write-Host $_.RoleTypeKind }
    Recupera tutti i possibili ruoli utente associati al sito SharePoint a cui ci siamo collegati
    $folder = Get-PnPFolder -Connection $context -Url $SharePointFolderUrl   $folder = $web.GetFolderByServerRelativeUrl($ServerRelativeUrl)
    $context.Load($folder)
    $context.ExecuteQuery()
    Ci colleghiamo alla cartella di interesse e ne recuperiamo l’oggetto.  In questo caso, oltre alla differenza in linee di codice, bisogna notare che nel caso di utilizzo del modulo SharePointPnP è necessario passare l’indirizzo assoluto della cartella, mentre nel caso di CSOM dobbiamo passare l’indirizzo relativo
    $folder.Context.Load($folder.ListItemAllFields.RoleAssignments)
    $folder.Context.ExecuteQuery()
    $roles = $folder.ListItemAllFields.RoleAssignments  
    $context.Load($folder.ListItemAllFields.RoleAssignments)
    $context.ExecuteQuery()
    $roles = $folder.ListItemAllFields.RoleAssignments  
    Recuperiamo ruoli assegnati alle cartelle
    foreach($role in $roles)
    {    
    $role.Context.Load($role.Member)    
    $role.Context.ExecuteQuery()    
    $userRole = $role.Member    
    if ($userRole.PrincipalType.ToString() -eq “User”)    
    {        
    Write-Host
    $userRole.LoginName.Split(‘|’)[2].toLower().Trim()    
    }    
    else    
    {        
    Write-Host
    $userRole.LoginName.ToString()    
    }
    }
    foreach($role in $roles)
    {    
    $role.Context.Load($role.Member)    
    $role.Context.ExecuteQuery()    
    $userRole = $role.Member    
    if ($userRole.PrincipalType.ToString() -eq “User”)    
    {        
    Write-Host $userRole.LoginName.Split(‘|’)[2].toLower().Trim()    
    }    
    else    
    {        
    Write-Host
    $userRole.LoginName.ToString()
    }
    }
    Codice uguale per entrambi gli script. Viene eseguito un ciclo sugli oggetti recuperati al passo precedente, e in base alla tipologia di userRole viene o stampata la mail collegata all’utente o il nome del gruppo.    
    Disconnect-PnPOnline   Disconnessione

    Utente per la connessione:

    Attenzione: per potersi connettere al sito di SharePoint OnLine bisogna ottenere tramite CSOM e SharePointPnP, purtroppo, un utente amministratore di Office 365; in caso contrario la connessione viene rifiutata e non è possibile effettuare nessuna modifica attraverso l’utilizzo dei moduli sopra indicati.

    Active Directory

    Installare il modulo Active Directory per PowerShell

    Per poter procedere nell’utilizzo di PowerShell per sincronizzare dati con Active Directory, dobbiamo innanzitutto abilitare il modulo Active Directory per PowerShell da linea di comando ed eseguire Import-Module ActiveDirectory.

    Installato il modulo, abbiamo adesso tutto una suite di CmdLet che ci permetterà di interagire con Active Directory.

    Sul sito di Microsoft trovate la lista completa di tutti i CmdLet per ActiveDirectory.

    Proviamo a scrivere uno script per il recupero di un utente Active Directory, la modifica di alcune proprietà e l’aggiunta/rimozione da uno specifico gruppo Active Directory

    Codice Descrizione
    Import-Module ActiveDirectory Importazione Modulo Active Directory
    $ADGroup = Get-ADGroup -Identity $ourADGroup Recupero oggetto “Active Directory Group”, passando l’identificativo del gruppo
    $ADUser = Get-ADUser -Identity $UserLogin -Properties * Recupero oggetto “Active Directory User” passando l’identità dell’utente (SamAccountName property) e recuperando tutte le proprietà (-Properties *)
    Write-Host $ADUser.SamAccountName Stampa a video la proprietà SamAccountName
    Write-Host  $ADUser.CanonicalName Stampa a video la proprietà CanonicalName (utente con relativa OU)
    Write-Host  $ADUser.ipPhone Stampa a video la proprietà ipPhone  (Tab Telephones campo IPPhone)
    Write-Host  $ADUser.Office Stampa a video la proprietà Office (Tab General campo Office)
    Write-Host $ADUser.OfficePhone Stampa a video la proprietà OfficePhone (Tab General campo Telephone Number)
    Write-Host $ADUser.Pager Stampa a video la proprietà Pager (Tab Telephones campo Pager)
    Set-ADUser -Identity  $ADUser.SamAccountName -Replace @{‘ipPhone’=”XXX”} -Office “yyyy” -Credential $credential Comando per modificare i campi ipPhone e Office per l’utente AD. Da notare che per il campo ipPhone abbiamo dovuto utilizzare un Dictionary (chiave valore). Nel caso si voglia rimuove il valore del campo l’istruzione sarà –Remove @{‘ipPhone’=’ipPhone’}. Per il campo Office, raggiungibile come parametro del CmdLet, in caso di rimozione basterà impostarlo al valore $null. Questa operazione necessiterà delle credenziali.
    $ADUser.MemberOf.Contains($ADGroup.DistinguishedName) Controlla se l’utente ha tra i suoi gruppi il gruppo AD prevalentemente ottenuto con il commad-let Get-ADGroup. Attenzione: non restituisce l’appartenza a Gruppi di Gruppi. In tal caso è necessario effettuare query LDAP
    Remove-ADGroupMember -Identity $ADGroup.Name -Members $AD_Login  -Confirm:$false -Credential $credential Rimozione dell’utente dal Gruppo AD. Da notare il comando  -Confirm:$false, che indica la non necessarietà di una conferma da parte dell’utente con il quale lo script viene eseguito. Questa operazione necessiterà delle credenziali.
    Add-ADGroupMember -Identity $ADGroup.Name -Members $AD_Login -Credential $credential Aggiunta dell’utente ad un gruppo AD. Questa operazione necessiterà delle credenziali.

    Problematiche utente Amministratore

    Attenzione: a meno che non venga utilizzato un utente amministratore di Active Directory per l’esecuzione dello script (scelta a mio avviso sconsigliata), l’utente di “servizio” che verrà utilizzato dovrà necessariamente essere abilitato alla lettura/scrittura dei campi Active Directory che vogliamo modificare.

    Tuttavia non esiste una naming-convention per quanto riguarda i campi Active Directory gestiti dagli script e abilitati dalla console di gestione di Active Directory.