Powershell : clôture d'une sélection de processus

Certaines applications appelées par un ordonnanceur ou des scripts peuvent laisser un processus ouvert sur le système lorsqu'elles ne sont plus utilisées. Ayant été confronté à ce cas d'une application gardant son driver ODBC en processus zombie lorsque la transaction est terminée, j'ai développé un script Powershell qui est appelé en tâche planifiée qui récupère la liste des processus ayant le nom correspondant et qui les tue automatiquement.

$process = Get-Process | Where-Object { $_.ProcessName -like "iexplore" }
foreach($proc in $process){
Stop-Process $proc.Id
}

Il suffit simplement de mettre le nom du processus récalcitrant ou bien de retravailler le script pour éventuellement faire passer un nom en paramètre pour une exécution interactive.

Powershell : automatisation de la création d'un répertoire partagé DFS

J'ai développé un script Powershell permettant d'automatiser tout le process de création d'un répertoire partagé et son ajout à un namespace DFS.

Ce script, prenant en paramètre le nom du partage, va réaliser les opérations suivantes :

  • Création d'un répertoire sur le disque et création d'un partage SMB sur ce même répertoire ;
  • Création et peuplement de groupes AD qui permettront de définir les droits en lecture et écriture ;
  • Ajout des ACL sur le partage ;
  • Ajout du répertoire dans le namespace DFS.

Il sera nécessaire, avant exécution du script, d'éventuellement modifier les variables déclarées en début de code afin de les adapter à l'environnement d'exécution ou au process habituellement suivi.

param([Parameter(Mandatory=$true)][string]$ShareName)
$path = "D:\DFS"
$dfspath = "\\dundermifflin.com\DFS"
$srvname = "PWFILE01"
$ou = "OU=DFS,OU=Access_Groups,DC=dundermifflin,DC=com"
$readarray = @()
$writearray = @()
$readgroup = "DFS-$ShareName-RX"
$writegroup = "DFS-$ShareName-W"
New-Item -path $path -name $ShareName -ItemType "Directory" -ErrorAction Stop | Out-Null
New-ADGroup -Name $readgroup -GroupCategory Security -GroupScope DomainLocal -Path $ou -Description "\\dundermifflin.com\DFS\$ShareName - Read Only" -ErrorAction Stop
New-ADGroup -Name $writegroup -GroupCategory Security -GroupScope DomainLocal -Path $ou -Description "\\dundermifflin.com\DFS\$ShareName - Write" -ErrorAction Stop
New-SmbShare -Name $ShareName -Path "$path\$ShareName" -FullAccess "BUILTIN\Administrators" -ReadAccess $readgroup -ChangeAccess $writegroup -ErrorAction Stop
Write-Host "You will be prompted the usernames to add to the read-only access group. Please input only one user at a time. When you are done, leave the field empty and press enter."
do {
$readacc = Read-Host "Account name to add to the READ group"
if($readacc -ne "") {$readarray+=$readacc}
}
while($readacc -ne "")
Write-Host "Now you will be prompted the usernames to add to the modification group. Please input only one user at a time. When you are done, leave the field empty and press enter."
do {
$writeacc = Read-Host "Account name to add to the WRITE group"
if($writeacc -ne "") {$writearray+=$writeacc}
}
while($writeacc -ne "")
if($readarray -ne $null) { Add-ADGroupMember -Identity $readgroup -Members $readarray }
if($writearray -ne $null) { Add-ADGroupMember -Identity $writegroup -Members $writearray }
$acl = Get-Acl "$path\$ShareName"
$acl.SetAccessRuleProtection($true,$false)
$readacl = New-Object Security.AccessControl.FileSystemAccessRule("DUNDERMIFFLIN\$readgroup","ReadAndExecute, Synchronize",3,0,"Allow")
$acl.SetAccessRule($readacl)
$writeacl = New-Object Security.AccessControl.FileSystemAccessRule("DUNDERMIFFLIN\$writegroup","Modify, Synchronize",3,0,"Allow")
$acl.SetAccessRule($writeacl)
$sysacl = New-Object Security.AccessControl.FileSystemAccessRule("NT AUTHORITY\System","FullControl",3,0,"Allow")
$acl.SetAccessRule($sysacl)
$admacl = New-Object Security.AccessControl.FileSystemAccessRule("BUILTIN\Administrators","FullControl",3,0,"Allow")
$acl.SetAccessRule($admacl)
$acl | Set-Acl
New-DfsnFolder -path "$dfspath\$ShareName" -Target "\\$srvname\$ShareName"

Une version commentée du script est disponible en téléchargement.

Powershell : suppression d'enregistrements DNS depuis un import CSV

Ce snippet permet de supprimer les enregistrements DNS à partir d'une liste au format CSV passée en paramètre.

Le script sera appelé de cette manière :

.\win_dns-deletion.ps1 -zone superdomaine.local -csv exportdns.csv

Seuls les enregistrements de type A sont supprimés par ce code ; le paramètre peut se modifier pour cibler un autre type. Par défaut, la commande demande confirmation avant suppression ; le paramètre -Force permet de passer outre cette confirmation. Attention au moment d'exécuter le script.

param([string]$zone, [string]$csv)
$records = Import-CSV $csv
foreach($record in $records){
Remove-DnsServerResourceRecord -ZoneName $zone -RRType "A" -Name $record.Name -Force
}

Powershell : ActiveDirectory Recycle Bin Explorer

La corbeille ActiveDirectory est une fonctionnalité disponible sur les forêts en niveau fonctionnel 2008 R2. Comme son nom l'indique, elle permet de restaurer des objets qui ont été supprimés, durant un laps de temps qui dépend de la configuration de la forêt.

Cette corbeille n'apparaît pas en tant que telle dans la console ActiveDirectory Users and Computers ou encore dans ADSI Edit, et pourtant elle existe bien dans l'AD en tant que "Deleted Objects".

Si il est possible de parcourir le contenu de la corbeille via la console ActiveDirectory Administrative Center disponible dans le Server Manager à partir de Windows Server 2012, cela implique d'avoir l'environnement graphique d'installé sur les contrôleurs de domaine et cela est surtout incompatible dans un environnement où l'on travaille avec les RSAT.

C'est pourquoi j'ai développé un script Powershell avec une interface graphique simpliste permettant d'afficher le contenu de la corbeille ActiveDirectory et permettant de restaurer en un clic un objet préalablement supprimé.

Les informations sont affichées dans un DataGridView ; il est possible de trier ou de rechercher / filtrer par nom ou type, de réaliser un export CSV de la liste complète des objets étant dans la corbeille.


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.