7.1 : Invoke-Command et sessions PSRemoting

Depuis la leçon 4.3, vous savez utiliser -ComputerName pour cibler un serveur distant, avec ses limites déjà signalées. Sophie ouvre la baie de brassage : « Nordika a 40 serveurs. Le jour où il faut vérifier quelque chose sur chacun d’eux, tu ne vas pas ouvrir 40 connexions RDP l’une après l’autre. » C’est exactement le rôle du Remoting : exécuter du code PowerShell sur une ou plusieurs machines distantes, comme si vous étiez assis devant chacune.

WinRM : le prérequis technique

PSRemoting repose sur le protocole WinRM (Windows Remote Management), qui doit être activé sur chaque machine distante. Sur un serveur à configurer pour la première fois :

Enable-PSRemoting -Force

Cette commande active le service WinRM, configure une règle de pare-feu adaptée, et enregistre les écouteurs nécessaires. Sur la plupart des environnements d’entreprise modernes, WinRM est déjà activé par défaut via une stratégie de groupe (GPO) au niveau du domaine — un point qu’on retrouvera en filigrane en section 8.

Retour d’expérience terrain : dans un environnement d’entreprise avec plusieurs domaines ou des serveurs en DMZ, l’échec le plus fréquent de Invoke-Command ne vient presque jamais de PowerShell lui-même, mais d’un pare-feu réseau bloquant le port 5985 (HTTP) ou 5986 (HTTPS) entre les deux machines. Avant de suspecter un problème de script, un simple Test-NetConnection -ComputerName SRV-02 -Port 5985 permet d’écarter rapidement cette cause.

Invoke-Command : exécuter à distance, une fois

La commande la plus directe pour lancer une action sur une ou plusieurs machines :

Invoke-Command -ComputerName "SRV-01" -ScriptBlock { Get-Service -Name "Spooler" }

Le code entre accolades (-ScriptBlock) s’exécute sur SRV-01, pas sur votre poste local, et le résultat vous revient ensuite comme n’importe quel objet PowerShell habituel — exploitable avec tout ce qui a été vu en section 2 (Sort-Object, Format-Table…).

Cibler plusieurs serveurs en une seule commande

C’est là que le Remoting change vraiment d’échelle par rapport à -ComputerName vu en 4.3 :

$serveurs = "SRV-01", "SRV-02", "SRV-03"

Invoke-Command -ComputerName $serveurs -ScriptBlock { 
    Get-Service -Name "Spooler" | Select-Object -Property PSComputerName, Status
}

PowerShell exécute le bloc en parallèle sur les trois serveurs, et non l’un après l’autre — un gain de temps considérable dès qu’on dépasse quelques machines. La propriété PSComputerName, ajoutée automatiquement au résultat, permet de savoir de quel serveur provient chaque ligne.

Transmettre des variables locales au serveur distant

Un piège fréquent : une variable définie sur votre poste local n’existe pas automatiquement dans le -ScriptBlock, qui s’exécute dans un contexte totalement différent (sur la machine distante). Il faut la transmettre explicitement avec -ArgumentList :

$nomService = "Spooler"

Invoke-Command -ComputerName "SRV-01" -ScriptBlock { 
    param($service)
    Get-Service -Name $service 
} -ArgumentList $nomService

Sessions persistantes : garder la connexion ouverte

Quand on doit exécuter plusieurs commandes successives sur le même serveur, ouvrir une connexion à chaque fois est inutilement coûteux. Une session (PSSession) garde la connexion active :

$session = New-PSSession -ComputerName "SRV-01"

Invoke-Command -Session $session -ScriptBlock { Get-Service -Name "Spooler" }
Invoke-Command -Session $session -ScriptBlock { Get-Process | Select-Object -First 5 }

Remove-PSSession -Session $session

Bonne pratique constatée en production : toujours fermer une session avec Remove-PSSession une fois le travail terminé. Une session PSRemoting oubliée consomme des ressources sur le serveur distant, et s’accumule silencieusement si le script est exécuté régulièrement sans nettoyage — un phénomène qu’on peut vérifier avec Get-PSSession sur le serveur concerné.

Entrer interactivement dans une session distante

Pour un dépannage ponctuel, on peut aussi transformer sa console locale en une véritable session sur le serveur distant, comme si on était physiquement connecté dessus :

Enter-PSSession -ComputerName "SRV-01"

L’invite de commande change pour indiquer clairement qu’on agit désormais sur SRV-01. Exit-PSSession (ou simplement exit) referme la session et ramène à la console locale.

Un exemple concret Nordika

En reprenant l’exemple de supervision de la section 5, mais à l’échelle réelle des 40 serveurs de Nordika, sans attendre les vérifications une par une :

$serveurs = Get-Content -Path ".\liste-serveurs.txt"

$resultats = Invoke-Command -ComputerName $serveurs -ScriptBlock {
    $services = "Spooler", "W32Time", "Dnscache"
    foreach ($nom in $services) {
        $service = Get-Service -Name $nom -ErrorAction SilentlyContinue
        [PSCustomObject]@{
            Service = $nom
            Statut  = $service.Status
        }
    }
} -ErrorAction SilentlyContinue

$resultats | Format-Table -Property PSComputerName, Service, Statut -AutoSize

Un script qui aurait pris plusieurs dizaines de minutes en connexions RDP successives s’exécute ici en quelques secondes, sur l’ensemble du parc, avec un rapport consolidé et directement exploitable.

Source officielle : la documentation Microsoft about_Remote et about_PSSessions détaille l’ensemble des mécanismes de Remoting, y compris les scénarios plus avancés (double authentification, CredSSP, JEA — Just Enough Administration) qui dépassent le cadre de cette formation mais valent le détour pour un environnement de production exigeant.

Retenez le principe central de cette leçon, dans la continuité de la section 6 sur la sécurité AD : le Remoting donne accès à des dizaines de machines à la fois. Les mêmes précautions de moindre privilège s’appliquent ici avec encore plus de force — un script mal écrit exécuté via Invoke-Command sur 40 serveurs simultanément peut propager une erreur 40 fois plus vite qu’un script exécuté localement.

PSRemoting via SSH : le Remoting devient multiplateforme

Tout ce qu’on vient de voir repose sur WinRM, un protocole propre à Windows. Mais depuis PowerShell 7, Invoke-Command et Enter-PSSession fonctionnent aussi via SSH, ce qui ouvre une possibilité impossible avec WinRM seul : piloter du Linux depuis Windows, du Windows depuis Linux, ou même du macOS, avec exactement la même syntaxe.

Le prérequis : un serveur SSH installé et configuré pour PowerShell sur la machine distante (sshd sur Linux, ou le composant OpenSSH Server sur Windows), avec le sous-système PowerShell déclaré dans la configuration SSH (sshd_config).

Invoke-Command -HostName "srv-linux-01.nordika.local" -UserName "admin" -ScriptBlock { 
    Get-Process 
}

Notez le changement de paramètre : -HostName et -UserName remplacent -ComputerName, signalant explicitement qu’on utilise le transport SSH plutôt que WinRM.

Une session persistante fonctionne de la même façon :

$sessionLinux = New-PSSession -HostName "srv-linux-01.nordika.local" -UserName "admin"
Invoke-Command -Session $sessionLinux -ScriptBlock { Get-Content /var/log/syslog -Tail 20 }
Remove-PSSession -Session $sessionLinux

Retour d’expérience terrain : ce mode SSH est particulièrement utile dans les environnements Nordika hybrides, de plus en plus courants : une stack applicative sous Linux (comme évoqué en introduction avec des serveurs de bases de données ou des conteneurs) supervisée depuis les mêmes scripts PowerShell que les serveurs Windows historiques, sans avoir à maintenir deux outillages différents.

Point de vigilance : l’authentification par clé SSH (plutôt que par mot de passe) reste la pratique recommandée en production, exactement pour les mêmes raisons de sécurité déjà évoquées en section 6 concernant les secrets et les mots de passe en clair.

Source officielle : la documentation Microsoft PowerShell Remoting over SSH (accessible sur learn.microsoft.com) détaille la configuration complète côté serveur, notamment la déclaration du Subsystem powershell dans sshd_config, indispensable avant que Invoke-Command -HostName ne fonctionne.

Avec WinRM pour l’écosystème Windows et SSH pour tout le reste, le Remoting PowerShell couvre désormais l’intégralité du parc Nordika, quel que soit le système d’exploitation — cohérent avec ce qu’on a posé dès la leçon 1.3 sur PowerShell 7 et le multiplateforme.