Powershell : obtention des liens des GPO

Si la console gpmc.msc permet de parcourir toutes les GPO ainsi que leurs liens, cela n’est pas directement possible avec Powershell et la commande Get-GPO qui ne retournera que les informations de base de la GPO.

Afin de pouvoir obtenir les liens dans Powershell, il faut ruser un peu ; dans les deux scripts Powershell suivants, j’ai donc utilisé une technique de sioux consistant à réaliser un rapport au format XML de la GPO (grâce à Get-GPOReport) et à parcourir ledit fichier XML pour y identifier les liens grâce aux balises <LinksTo>.

Ce premier script liste toutes les GPO qui n’ont aucun lien, activé ou non :

Write-Host "Unlinked GPO listing script"
 Write-Host "==========================="
 Write-Host "Working… Please wait.`r`n"
 $GPOlist = Get-GPO -all
 foreach($GPO in $GPOList){
     [xml]$xmlreport = Get-GPOReport -Guid $GPO.Id -Report xml
     if($xmlreport.GPO.LinksTo.Count -eq 0){ Write-Host $GPO.DisplayName ; $count+=1}
 }
 Write-Host "`r`nUnlinked GPO count:"$count
 Write-Host "GPO parsed:"$gpolist.Length
 Write-Host "Done."

Ce deuxième script attend en paramètre le nom d’une GPO et retourne dans la console Powershell les objets auxquels cette GPO est liée. Par exemple, on appellera le script ainsi : .\win_gpolinks.ps1 -gpo « SRV-2016-Security-V3 »

Param([string]$gpoinput)
 $gpo = Get-GPO $gpoinput
 [xml]$report = Get-GPOReport -Guid $gpo.Id -Report xml
 foreach($link in $report.GPO.LinksTo){
     Write-Host $link.SOMPath
 }

A noter qu’il est nécessaire d’avoir les RSAT d’installés sur la station (si ce n’est pas un DC) depuis laquelle le script est exécuté ; il peut également être nécessaire d’appeler Import-Module GroupPolicy pour exécuter les cmdlets Get-GPO et Get-GPOReport.

Exchange et Powershell : usage des databases

Ce script renvoie le nombre de boîtes aux lettres stockées dans une database Exchange ainsi que sa taille.

Le script peut s’appeler avec le nom de la database en paramètre ; si aucun paramètre n’est spécifié, alors le script parcourt toutes les databases.

Par exemple, pour récupérer les informations sur la database DBEXCHFR1, il suffira d’appeler le script de cette manière :

.\exch_dbusage.ps1 -db dbexchfr1

Le script est téléchargeable dans une version commentée.

Param([string]$db)
if($db -eq $null) { $mbxdbs = Get-MailboxDatabase -status | select Name,DatabaseSize }
else { $mbxdbs = Get-MailboxDatabase -status | select Name,DatabaseSize | Where-Object { $_.Name -eq $db } }
foreach($mbxdb in $mbxdbs){
$mbxindb = Get-Mailbox | Where-Object { $_.Database -eq $mbxdb.Name }
Write-Host "Database"$mbxdb.Name
Write-Host "Number of mailboxes on that database:"$mbxindb.Count
Write-Host "Size:"$mbxdb.DatabaseSize`r`n
}

Powershell : extraction des mots de passe BitLocker

Comme j’en avais parlé il y a presque un an déjà dans ce billet, il est possible de configurer BitLocker pour qu’il stocke les mots de passe des volumes chiffrés dans l’ActiveDirectory, en lien avec l’objet Ordinateur correspondant.

BitLocker stocke dans l’ActiveDirectory un objet de type msFVE-RecoveryInformation ; l’objet Ordinateur est donc le père. On peut retrouver toutes les informations en ouvrant un ADSI Edit et en allant sur l’objet Ordinateur :

Les différents mots de passe ont pour canonical name une concaténation de leur date de création et de différentes propriétés.

Dans les propriétés de l’objet, on retrouve donc l’attribut msFVE-RecoveryPassword que je vais récupérer dans le script Powershell ci-dessous ; ce script génère la liste de tous les objets Ordinateur et leurs objets msFVE-RecoveryInformation associés pour ensuite écrire le contenu dans un fichier CSV. Ainsi, ce script permet de réaliser une copie de sauvegarde des mots de passe et de ce qui est nécessaire pour déverrouiller les disques chiffrés des stations jointes au domaine. Naturellement, on prendra soin de bien protéger ce fichier et son accès. Le script est téléchargeable dans une version commentée à la fin de l’article.

Requires -RunAsAdministrator
 Add-Type -AssemblyName System.Windows.Forms
 $fileExpl = New-Object System.Windows.Forms.SaveFileDialog
 $fileExpl.ValidateNames = $true
 $fileExpl.CreatePrompt = $false
 $fileExpl.OverwritePrompt = $true
 $fileExpl.RestoreDirectory = $false
 $fileExpl.InitialDirectory = "$env:userprofile"
 Write-Host "WARNING : This script will extract from your ActiveDirectory all the BitLocker recovery keys and passwords. This is CRITICAL DATA as you would not want unauthorized users to be able to unlock the protected drives. Please ensure the exported data is stored somewhere safe." -Foreground "Red"
 Write-Host "Please press ENTER to start."
 Read-Host
 $global:tempfile = "$env:temp\temp-bl.csv"
 if(Test-Path $tempfile){ Remove-Item $tempfile }
 $dump = "ComputerName,DistinguishedName,msFVE-RecoveryPassword"
 Add-Content -Value $dump -path $tempfile
 $complist = Get-AdComputer -Filter *
 foreach($comp in $complist){
     $BLInfo = Get-AdObject -Filter 'objectClass -eq "msFVE-RecoveryInformation"' -SearchBase $comp.DistinguishedName -Properties 'msFVE-RecoveryPassword'
     foreach($BL in $BLInfo){
         $dn =$BL.DistinguishedName
         $dump = $comp.Name+","+"'"+$dn+"'"+","+$BL.'msFVE-RecoveryPassword'
         Add-Content -Value $dump -Path $tempfile
     }
 }
 $fileExpl.DefaultExt = "csv"
 $fileExpl.Filter = "Comma-separated values file (.csv)|.csv"
 $fileExpl.Title = "Export data to CSV file"
 $fileExpl.Filename = ""
 $fileExpl.ShowDialog() | out-null
 if ($fileExpl.Filename -ne "") {
     Copy-Item $global:tempfile -Destination $fileExpl.Filename
     if ($?){ Remove-Item $global:tempfile ; Write-Host "Data exported to"$fileExpl.Filename }
     else { Write-Host "Couldn't save the CSV file to the specified location." ; Remove-Item $global:tempfile }
 }
 else { Remove-Item $global:tempfile ; Write-Host "Data export aborted." }

Ce fichier CSV peut ensuite être importé dans Excel par exemple, en le convertissant :

Disque virtuel de taille nulle sur vSphere 6.5

Alerte de sauvegarde sur une machine virtuelle en exécution, snapshot impossible pour cause de disque inaccessible : celui-ci affiche une taille de 0 Ko.

Pourtant, en allant parcourir le datastore, on voit bien les fichiers VMDK aux côtés des fichiers de configuration et de mémoire vive.

Afin de résoudre le problème, j’ai essayé les manipulations suivantes :

  • Storage vMotion vers un autre datastore, machine éteinte : KO
  • vMotion vers un autre hôte, machine éteinte : KO

Il a finalement fallu que je supprime la machine de l’inventaire avant de la réinscrire sur le datastore d’origine. J’imagine que la réinscription dans l’inventaire et la lecture du fichier .vmx a permis à vSphere de rafraîchir les informations.

Enfin, le démarrage de la machine s’est déroulé sans accroc et j’ai pu créer un snapshot de test pour vérifier le bon fonctionnement d’une interaction avec le fichier VMDK. Mon flux de sauvegarde pourra reprendre son cours.