Installation de PowerShell V7 et OpenSSH sous Windows Server 2016

Si Microsoft s'ouvre de plus en plus vers le monde GNU/Linux, cet effort se retrouve principalement sur Windows Server 2019. Cependant, il est tout à fait possible d'installer OpenSSH sur Windows Server 2016 et ainsi d'administrer son serveur à distance en utilisant la dernière version de Powershell, ou encore de pouvoir faire du transfert de fichier via SSH comme sur un hôte GNU/Linux.

Bien que Microsoft indique que les binaires OpenSSH ne soient pas suffisamment stables pour un usage en production, je n'ai rencontré aucun dysfonctionnement pénalisant avec dans mon environnement de test et j'ai intégré OpenSSH à ma dernière révision du master. Chaque environnement étant différent, il reste important de tester avant une intégration en production.

Les sources de Powershell V7 se trouvent sur le GitHub de Powershell accessible à ce lien. Les sources d'installation d'OpenSSH pour Windows se trouvent sur ce GitHub.

L'installation de Powershell V7 se fait simplement en exécutant le setup ; cependant, l'implémentation d'OpenSSH sous Windows semble rencontrer des dysfonctionnements lorsqu'elle doit gérer des répertoires avec des espaces. Je vous conseille donc d'installer PS dans un autre répertoire que celui proposé par défaut ; dans cet exemple je l'ai installé directement à la racine du C:\.

L'installation d'OpenSSH se fait également en dézippant l'archive. Pour les mêmes raisons que précédemment, je vous conseille de déployer les binaires dans un répertoire sans espace (et de manière générale, de bannir les espaces des noms de fichiers !).

Vous pouvez désormais ajouter les deux répertoires à la variable système PATH, comme ceci :

L'installation d'OpenSSH se fait en Powershell, avec une élévation en administrateur :

cd C:\OpenSSH-Win64
.\install-sshd.ps1

Ce script va créer deux services que l'on peut retrouver dans la console. Par défaut, les services ne sont pas démarrés (c'est pourquoi je les ai intégrés à mon master, ainsi je peux les activer si il y a besoin, sans cela ils restent "dormants" sans avoir d'impact sur le système). Il faut donc les démarrer, et en fonction du besoin, activer le démarrage automatique.

Ensuite, il convient de générer une clef SSH. Toujours dans le répertoire d'OpenSSH :

ssh-keygen.exe -A

Le fichier de configuration est identique à celui que l'on peut retrouver sur un système GNU/Linux utilisant OpenSSH. Il suffit de copier le fichier sshd_config_default vers un nouveau fichier nommé sshd_config dans le répertoire C:\ProgramData\ssh et d'y appliquer les paramètres désirés et de redémarrer le service pour que les changements soient pris en compte.

Tout est prêt. Il ne reste plus qu'à ouvrir une connexion en SSH pour tester le bon déroulement de l'installation. Une fois la connexion établie avec son login Windows usuel, il suffit d'appeler le moteur Powershell pour faire ce que l'on souhaite :

En utilisant la console, on peut tomber sur quelques bugs d'affichage si jamais la console Putty a été redimensionnée :

En dehors de ces petites imperfections qui montrent que ces binaires n'en sont pas encore à un véritable état de release, la connexion est stable. Je me suis pris au jeu d'effectuer quelques tâches et c'est relativement plaisant de pouvoir effectuer du Powershell à distance via SSH, WinRM étant bloqué dans mon environnement. OpenSSH permet par ailleurs de faire du transfert de fichier via SSH, grâce à WinSCP par exemple :

Powershell : liste des répertoires DFS portés par un serveur

Travaillant actuellement sur la migration de serveurs de fichiers, j'ai conçu un script Powershell prenant en paramètre le nom d'un serveur afin de lister tous les partages DFS qui y sont hébergés. Le script ne fait pas de distinguo entre les liens DFS actifs et inactifs.

Param([Parameter(Mandatory=$true)][string] $Server)
$roots = Get-DfsnRoot
foreach($root in $roots){
    $path = $root.Path+"\*"
	Get-DfsnFolder $path | Where-Object { (Get-DfsnFolderTarget $_.Path).TargetPath -like "\\$server*" } | select Path -ExpandProperty Path
}

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.