Powershell : création d'un batch de users AD sur import CSV

Ce script permet de créer en masse des utilisateurs dans un AD sur base d'un fichier CSV.

$userlist = Import-CSV usertocreate.csv
foreach($user in $userlist){
	New-AdUser -Name $user.Name -GivenName $user.FirstName -Surname $user.LastName -Path $user.OrgUnit -StreetAddress $user.Address -City $user.City -PostalCode $user.PostalCode -Country FR -HomeDrive "U:" -HomeDirectory $user.HomeDir -AccountPassword (ConvertTo-SecureString -AsPlainText $user.MatriculeID -Force) -UserPrincipalName $user.UPN
    Enable-ADAccount $user.Name
	Set-ADUser -Identity $user.Name -ChangePasswordAtLogon $true
	$GrpList = $user.Groups
	while($GrpList.IndexOf(",") -ne -1) {
		$commaindex = $GrpList.IndexOf(",")
		Add-AdGroupMember -Identity $GrpList.SubString(0,$commaindex) -Members $user.Name
		$GrpList = $GrpList.SubString($commaindex+1,$GrpList.Length-($commaindex+1))
	}
	Add-AdGroupMember -Identity $GrpList -Members $user.Name
} 

Le script (une version commentée est disponible en fin d'article, comme toujours) prend quelques propriétés pour la création du compte en sus des usuelles. Il pourra donc être nécessaire d'en retirer, en rajouter ou de modifier les noms attribués dans le script pour s'adapter au fichier d'entrée qui pourra être généré à partir d'une application RH par exemple.

Le script ajoute également l'utilisateur fraîchement créé aux groupes AD spécifiés, en découpant la liste située entre guillemets (afin qu'elle soit interprétée comme une chaîne de caractères unique) en fractions séparées par une virgule.

Le mot de passe est basé sur un numéro matricule fictif que seul l'utilisateur final connaît ; cependant pour des raisons de sécurité, ce mot de passe sera à modifier à la première connexion.

Crashs fréquents de WSUS 4.0

Depuis quelques jours, un serveur WSUS plantait au bout de quelques minutes de fonctionnement, sans dysfonctionnement notable côté système. Les logs de WSUS ne donnaient rien de particulier : toutes les requêtes y étaient journalisées, jusqu'au plantage sans code d'erreur particulier. Il suffisait d'un iisreset pour redonner l'accès au service, mais hors de question de créer un tâche planifiée pour effectuer un iisreset toutes les 5 minutes pour palier au dysfonctionnement.

Message d'erreur apparaissant sur la console WSUS peu de temps après le redémarrage du service.

J'avais cependant dans le journal d'événements Windows, deux entrées récurrentes, avec pour code d'erreur 5013 et 5138, et source "WAS". Ces erreurs indiquent qu'une application utilisée dans le pool applicatif WsusPool n'a pas communiqué et ne s'est pas terminée dans le temps imparti.

J'ai procédé à quelques changements de variables concernant le pool applicatif WsusPool :

  • Queue Length : passage à 25000 au lieu de 5000 (il s'agit du nombre maximal de requêtes HTTP qui peuvent être en attente) ;
  • Augmentation de la Virtual Memory Limit à 5 Go (pour 8 installés physiquement sur le serveur) ;
  • Passage du "Service Unavailable" Response Type de HttpLevel vers TcpLevel : ceci permet d'éviter de renvoyer une erreur HTTP 503 Service Unavailable lorsque le serveur ne peut traiter la requête. Le serveur va à la place remettre en file d'attente la requête HTTP.

J'ai procédé ensuite à un redémarrage complet du serveur, WSUS fonctionne désormais depuis plus de 2 heures consécutives et aucun dysfonctionnement n'est à déplorer.

Powershell : vérification de masse d'existence de comptes AD

Ce script prend un fichier CSV en entrée comprenant des noms de comptes AD afin de vérifier pour chacun s'il existe vraiment grâce à dsquery et réalise un export CSV de la liste générée.

$userlist = Import-CSV userlist.csv
$i = 0
$userexport = @()
foreach($user in $userlist){
	if ((dsquery user -samid $user.Name) -eq $null) { 
		$user.name
		$i++
		$name=@{Name = $user.name}
		$export = New-Object PSObject -Property $name
		$userexport+=$export
	}
}
Write-Host "Number of accounts not present in AD"$i" out of"($userlist.length)
$userexport | Export-CSV user-noexist.csv -NoTypeInformation

Pourquoi dsquery et non pas Get-AdUser ? Car ce dernier renvoie un message d'erreur si l'utilisateur n'existe pas et que le but du script est simplement de lister les users qui ne sont pas présents dans l'AD.

A noter qu'en fonction du titre de la "colonne" comportant les noms dans le fichier CSV, il sera nécessaire de modifier la requête -samid $user.Name en -samid $user.NomColonne.

Octroi de droits à un compte sur un service grâce à subinacl

En recherchant un moyen d'accorder les droits de démarrage / arrêt sur un service particulier pour un compte d'utilisateur standard, je suis tombé sur cet article sur Serverfault. Le but était d'éviter d'accorder des privilèges d'administration à l'utilisateur en question.

Il existe donc un outil nommé SubInACL, qui fait partie du Windows Resource Kit (aux côtés de nombreux autres outils que je connaissais comme LockOutStatus). Cet outil qui s'exécute en ligne de commande permet de choisir précisément quels privilèges accorder sur un service pour un utilisateur, qu'il soit local ou du domaine.

J'ai testé cet outil sur un serveur de test en 2008 R2 et appliqué le fonctionnement sur un 2016 ; son exécution est très simple. Microsoft explique toute la syntaxe disponible à ce lien. Si je souhaite accorder à l'utilisateur dschrute le droit de voir l'état et de relancer le service NTP, je vais devoir envoyer cette instruction :

subinacl.exe /service w32time /GRANT=DUNDERMIFFLIN\dschrute=STO

Voici sur un Server 2016, le résultat de la commande pour le service Windows Update :

Si SubInACL n'est plus disponible sur le site de Microsoft, il est disponible en téléchargement sur le miroir du blog à ce lien.