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.

The account is not authorized to login from this station

J'ai obtenu cette erreur en tentant de monter un partage réseau d'une machine en Windows XP sur un Server 2016, suite à une migration d'un Server 2003 sur lequel tout fonctionnait bien.

Après comparaison de multiples clefs de registre sur des machines Windows XP similaires pour lesquelles la connexion du partage réseau était possible, j'ai fait chou blanc ; jusqu'à tomber sur ce réglage de GPO locale (les machines sont toutes en standalone, je n'ai donc pas de politique de domaine) :

Situé dans Configuration Ordinateur > Paramètres Windows > Paramètres de sécurité > Stratégies locales > Options de sécurité > Accès réseau : modèle de partage et de sécurité pour les comptes locaux, ce paramètre était réglé sur Classique pour la machine incriminée et sur Guest (invité) sur toutes les autres. Une fois le paramètre passé sur Guest, j'ai pu monter ce partage SMB.

Il semblerait donc que les versions suivantes de SMB présentes avec 2016 (3.1+) aient logiquement des politiques de sécurité renforcées par rapport au SMB 1.x livré avec 2003. Ce billet d'un blog TechNet offre plus d'informations concernant les évolutions de Server Message Block.

Powershell : harmonisation de la configuration DNS

Afin d'harmoniser la configuration DNS sur des serveurs situés sur différents sites géographiques, j'ai développé un script Powershell lié à une GPO qui l'exécute au démarrage.

Ce script récupère grâce au nom du serveur son emplacement et applique en fonction de ce dernier les bonnes adresses IP. Naturellement, il faudra adapter l'extraction de l'emplacement dans le nom de la machine en fonction de l'environnement sur lequel le script sera déployé ; de plus, le domaine sur lequel la carte est connectée sert d'identification de la carte réseau employée pour la résolution DNS.

$location = (hostname).Substring(2,3)
switch($location){
"PAR" { $dnslist = '("192.168.1.1","192.168.1.2","192.168.2.1")' }
"BXL" { $dnslist = '("192.168.2.1","192.168.2.2","192.168.1.1")' }
"BER" { $dnslist = '("192.168.3.1","192.168.3.2","192.168.2.1")' }
"LDN" { $dnslist = '("192.168.4.1","192.168.4.2","192.168.3.1")' }
"NYC" { $dnslist = '("192.168.5.1","192.168.1.1","192.168.4.1")' }
}
$cards = Get-NetIPConfiguration
foreach($card in $cards){
if($card.NetProfile.Name -eq "dundermifflin.local") { $index = $card.InterfaceIndex }
}

$query = "Set-DnsClientServerAddress -InterfaceIndex $index -ServerAddresses $dnslist"
Invoke-Expression $query

Ce snippet fonctionne si par exemple mes serveurs ont une nomenclature de nommage comme celle-ci : <OS><Environnement><Emplacement><Rôle><ID>, qui pourrait donner par exemple pour un contrôleur de domaine de production WPLDNDC01 ou un serveur PostgreSQL de recette LRBXLPG03.

Ce script est disponible dans une version commentée sur le miroir de téléchargement.

Powershell : GPO Remote Updater

Si vous avez suivi mes derniers articles, vous n'êtes pas sans savoir que j'ai travaillé sur le Windows Update Delivery Optimization et sur des GPO en lien avec ce composant.

J'ai développé un script Powershell à interface graphique permettant d'exécuter à distance un gpupdate, soit sur un ordinateur unique, soit sur chaque ordinateur d'un groupe ActiveDirectory.

Il est possible de choisir les paramètres à mettre à jour et de mettre un timer sur l'exécution du gpupdate ; dans ce dernier cas, le traitement se termine lorsque la commande est reçue par l'ordinateur distant étant donné que c'est ce dernier qui effectue le décompte jusqu'au lancement d'un gpupdate.

A noter que la commande Invoke-GPUpdate ne réalise pour autant pas une mise à jour silencieuse des éléments de GPO sur les ordinateurs, il convient donc de communiquer avant d'exécuter le script sur tout un groupe d'ordinateurs en cours d'utilisation. Je vous renvoie à la documentation de la commande pour plus d'informations sur les versions de Windows supportés et sur les ports qui doivent être ouverts dans les firewall afin que la communication puisse être établie.

Vous pouvez télécharger le script en cliquant sur ce lien.

Restriction du Windows Update Delivery Optimization par groupe ActiveDirectory

Le WUDO ou Windows Update Delivery Optimization est un composant Windows présent sous Windows 10 qui permet d'optimiser la bande passante réseau consommée lors de la distribution de mises à jour système via WSUS par exemple. En imaginant un réseau d'une dizaine de stations, une seule d'entre elles pourrait utiliser le WAN pour récupérer les mises à jour depuis un serveur WSUS situé en central et les autres utilisent le LAN pour les télécharger à partir de celle les ayant obtenues via le WAN afin d'éviter une saturation de ce dernier. Ce qui peut être un gain de bande passante peut avoir des effets de bord notables ; c'est pourquoi il est possible de contrôler finement le comportement du WUDO via GPO. Un moyen de mieux centrer son action est de passer par la création de groupes ActiveDirectory pour regrouper des stations ; c'est ce que je vais présenter dans cet article.

La problématique est la suivante : des stations du site fictif de Paris utilisent le WAN pour télécharger des mises à jour WSUS sur des stations à Londres. Afin d'éviter de saturer ce lien, on souhaite donc limiter le WUDO à récupérer des données depuis des stations d'un même site uniquement.

Voici la composition de cette maquette de test :

  • OU computers, comprenant 3 OU paris, bxl et london, comprenant les stations propres à chaque site.
  • OU wudo-grp, qui contiendra les groupes AD wudo_paris, wudo_bxl et wudo_ldn dans lesquels seront placées les stations de chaque site.

Il est nécessaire de créer une GPO par groupe AD, d'où l'importance de bien définir ses besoins et surtout, l'organisation qui va être adoptée pour bien séparer les flux de communication WUDO. Une séparation trop granulaire demandera beaucoup de travail d'administration et l'inverse n'aura probablement aucun effet de correction des effets de bord ! Cette GPO va prendre en paramètre unique le GUID du groupe, il faut donc le récupérer et surtout, le stocker quelque part pour toujours avoir une association facile entre GUID et GPO associée.

En Powershell, l'instruction suivante nous permettra de récuprer le GUID du groupe.

(Get-AdGroup wudo_paris).ObjectGuid.Guid

Bien entendu, une boucle foreach dans un script récupérant tous les groupes d'une OU permettra de tous les obtenir facilement.

Désormais, il faut s'occuper de la création des GPO. Les réglages qui nous intéressent sont dans Computer Configuration > Policies > Administrative Templates > Windows Components > Delivery Optimization.

La première option est le Download Mode, qu'il faut passer à 2. La description du paramètre explique bien les différentes options possibles. Il est important de noter que ce qui est désigné comme "LAN" ici n'est pas un LAN au sens physique du terme mais un réseau interne ActiveDirectory. Par exemple, si votre domaine s'appelle schmitouille.net, alors le LAN englobera toutes les stations dans schmitouille.net. Si vous avez des sous-domaines, alors le LAN considèrera les stations du sous-domaine, par exemple fr.schmitouille.net.

Ensuite, l'autre paramètre est Group ID. C'est ici que devra être renseigné le GUID du groupe correspondant. Ici, je vais placer le GUID du groupe wudo_bxl car c'est la GPO qui va régir le WUDO des stations du site fictif de Bruxelles.

Il ne me reste plus qu'à lier cette GPO sur l'OU contenant les stations, et non celle contenant les groupes. Toujours en restant dans le cadre du site de Bruxelles :

... et à répéter l'opération autant de fois que nécessaire. En fonction de l'architecture de l'ActiveDirectory, il peut être nécessaire d'appliquer un Security Filtering sur le groupe d'ordinateurs concerné afin d'être sûr que la GPO ne s'applique que sur les stations désirées.

Afin de faire en sorte que les paramètres soient pris en compte le plus rapidement possible, il est possible de forcer un gpupdate à distance via Powershell. Voici un snippet que j'ai réalisé permettant de passer sur toutes les stations désormais régies par ces politiques de groupe pour mettre à jour ces dernières (à noter qu'en fonction de la disponibilité des stations, des paramètres firewall ou des droits du compte l'exécutant, il peut y avoir des erreurs) :

$grouplist = Get-ADGroup -Filter 'Name -like "wudo_*"'
foreach ($group in $grouplist){
    $complist = Get-AdGroupMember $group
    foreach ($comp in $complist){
        Write-Host "Processing:"$comp.Name
        Invoke-GPUpdate -Computer $comp.Name -RandomDelayInMinutes 0
    }
}

Enfin, pour vérifier que la GPO est bien redescendue, il est possible d'utiliser la fonctionnalité Group Policy Result et d'avoir un rapport indiquant si oui ou non la GPO a bien été appliquée. Si oui, le WUDO de la station concernée ne pourra donc interroger que les membres du groupe AD dont le GUID correspond à la GPO appliquée.