Cette page a pour but de décrire la mise en place d'une configuration minimale nécessaire pour un Windows supervisé par le pack windows-by-WinRM__shinken.
Afin de configurer des postes Windows d'un domaine ( Active Directory ), voir la page Configuration du Windows supervisé dans un Domaine ( Active Directory ) pour le pack windows-by-WinRM__shinken |
Voici la liste des versions Windows que la sonde peut superviser à distance :
|
La supervision d'un Windows par un poller Shinken se fait par requête WinRM.
|
Le service Windows WinRM sur un Windows supervisé permet l'exécution de commandes à distance, et notamment la récupération d'informations sur la machine mises à disposition par WMI ( Windows Management Instrumentation ).
Il est donc nécessaire de configurer :
Les configurations suivantes sont destinées à des serveurs Windows configurés en "groupe de travail" ( Workgroup ). |
Le service WinRM est installé par défaut sur les systèmes d'exploitations compatibles avec le pack. Voici comment le configurer :
Toutes les commandes ci-dessous doivent être exécutées dans un terminal PowerShell lancé en mode administrateur ( sauf mention contraire ) |
Voici la commande à exécuter pour vérifier si le service est bien démarré :
Get-Service WinRM |
Exemple :
C:\Users\Administrateur> Get-Service WinRM Status Name DisplayName ------ ---- ----------- Running WinRM Gestion à distance de Windows (Gest... |
Sur Windows 11 et Windows 10, il est nécessaire de configurer le démarrage automatique de WinRM :
|
Voici un script permettant de configurer rapidement par ligne de commandes un poste Windows.
Il doit être exécuté sur chaque poste Windows à superviser. |
Son usage n’est PAS obligatoire, il reprend l'entièreté des commandes décrites dans la procédure de configuration étape par étape détaillée plus bas dans la documentation.
Avant d’utiliser ce script, lire attentivement les points recommandés suivants :
|
Le script va :
Rappel : le script nécessite les droits administrateurs pour l’exécution |
<#
.SYNOPSIS
Configure un hôte Windows pour la supervision via WinRM avec le pack windows-by-WinRM__shinken
.DESCRIPTION
Ce script configure automatiquement un hôte Windows supervisé pour la supervision via WinRM avec le pack windows-by-WinRM__shinken
Le script va effectuer les opérations suivantes :
1. Vérifier si la langue Anglaise ou Française est installé.
2. Créer un utilisateur de supervision et l'ajouter dans les groupes nécessaires
(Remote Management Users, Performance Monitor Users)
3. Configurer la langue du nouvel utilisateur de supervision (en-US ou fr-FR)
4. Configurer WinRM pour l'authentification Basic ou Negotiate, puis HTTP
5. Configurer l'utilisateur de supervision pour exécuter des commandes WinRM
6. Configurer l'utilisateur de supervision pour récupérer les informations WMI/CIM root\cimv2
7. Configurer l'utilisateur de supervision pour récupérer les informations WMI/CIM root\standardcimv2
8. Configurer l'utilisateur de supervision pour récupérer les informations du journal de sécurité (Security Event Log)
9. Configurer l'utilisateur de supervision pour récupérer les informations de W32Time
(le service NTP de Windows)
10. Redémarrer les services winmgmt et WinRM pour appliquer toutes les modifications
.PARAMETER UserName
Nom d'utilisateur local à créer pour la supervision.
Exemple : "shinken_user"
.PARAMETER Password
Mot de passe de l'utilisateur.
.PARAMETER Negotiate
Active l'authentification Negotiate (true/false).
Recommandé pour environnements domaines AD
Plus sécurisé que Basic
.PARAMETER Basic
Active l'authentification Basic (true/false).
Nécessite AllowUnencrypted=true
.PARAMETER AllowUnencrypted
Autorise les connexions non chiffrées (true/false).
Obligatoire si Basic=true (HTTPS non supporté actuellement)
.PARAMETER Default
Active le mode par défaut avec les paramètres prédéfinis :
- UserName: shinken_user
- Password: Ch4nge_Th1s_P4ssw0rd
- Negotiate: true
- Basic: false
- AllowUnencrypted: false
.PARAMETER Interactive
Active le mode interactif avec un assistant pas-à-pas.
Recommandé pour les utilisateurs non familiers avec PowerShell.
Le mot de passe est saisi de manière masquée.
.PARAMETER Version
Affiche la version du script
.PARAMETER Help
Affiche cette aide complète.
Équivalent à : Get-Help .\Configure-Host.ps1 -Full
.NOTES
Prérequis :
- Windows Server 2012 R2+ ou Windows 10+
- PowerShell 4.0 ou supérieur
- Droits administrateur
- Service WinRM installé
Avertissements de sécurité :
- Negotiate est recommandé
- Le mode Basic transmet les identifiants en clair ( non chiffré )
- Le mot de passe par défaut doit être changé immédiatement
.EXAMPLE
.\Configure-Host.ps1 -Default
Utilise les paramètres par défaut (Negotiate, pas Basic)
.EXAMPLE
.\Configure-Host.ps1 -Interactive
Mode assistant pas-à-pas qui guide l'utilisateur à travers toutes les étapes
de configuration avec des explications contextuelles.
.EXAMPLE
$secPass = ConvertTo-SecureString "P@ssw0rd!" -AsPlainText -Force
.\Configure-Host.ps1 -UserName "shinken_user" -Password $secPass -Negotiate true -Basic false -AllowUnencrypted false
Configuration manuelle complète avec tous les paramètres spécifiés.
Note : Le mot de passe doit être converti en SecureString.
.EXAMPLE
$secPass = ConvertTo-SecureString "P@ssw0rd!" -AsPlainText -Force
.\Configure-Host.ps1 -UserName "monitoring_user" -Password $secPass -Basic true
Configuration avec authentification Basic (moins sécurisée).
AllowUnencrypted est obligatoire avec Basic.
#>
param(
[Parameter(Position=0, HelpMessage="Nom d'utilisateur local à créer pour la supervision (ex: shinken_user)")]
[string]$UserName,
[Parameter(Position=1, HelpMessage="Mot de passe de l'utilisateur")]
[object]$Password,
[Parameter(Position=2, HelpMessage="Active l'authentification Negotiate (true/false)")]
[string]$Negotiate,
[Parameter(Position=3, HelpMessage="Active l'authentification Basic (true/false)")]
[string]$Basic,
[Parameter(Position=4, HelpMessage="Autorise les connexions non chiffrées (true/false)")]
[string]$AllowUnencrypted,
[Parameter(HelpMessage="Active le mode par défaut avec paramètres prédéfinis")]
[switch]$Default,
[Parameter(HelpMessage="Active le mode interactif avec assistant pas-à-pas")]
[switch]$Interactive,
[Parameter(HelpMessage="Affiche cette aide complète")]
[switch]$Help,
[Parameter(HelpMessage="Affiche la version du script")]
[switch]$Version
)
# ==============================================================================
# Constantes - Valeurs par défaut
# ==============================================================================
$DEFAULT_USERNAME = "shinken_user"
$DEFAULT_PASSWORD = "Ch4nge_Th1s_P4ssw0rd"
$SCRIPT_VERSION = "V02.01.00-RC002.00"
# ==============================================================================
# Variable pour le suivi des étapes
# ==============================================================================
$Steps = New-Object System.Collections.ArrayList
function Get-Version {
Write-Host "Version : $SCRIPT_VERSION" -ForegroundColor Gray
}
# ==============================================================================
# SECTION 1 : FONCTIONS DE VALIDATION
# ==============================================================================
function Test-Prerequisites {
Write-Host "Vérification des prérequis..." -ForegroundColor Yellow
$checks = @()
# 1. Vérifier les droits administrateurs
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
$checks += @{
Name = "Droits administrateurs"
Result = $isAdmin
Error = "Ce script nécessite des droits administrateur."
}
# 2. Vérifier la version de PowerShell
$psVersion = $PSVersionTable.PSVersion.Major
$checks += @{
Name = "Version de PowerShell"
Result = ($psVersion -ge 4)
Error = "Ce script nécessite PowerShell 4.0 ou supérieur."
}
# 3. WinRM disponible
$winrmService = Get-Service -Name WinRM -ErrorAction SilentlyContinue
$checks += @{
Name = "Service WinRM présent"
Result = ($null -ne $winrmService)
Error = "Le service WinRM n'est pas installé"
}
$failed = $false
foreach ($check in $checks) {
if ($check.Result) {
Write-Host "[OK] $($check.Name)" -ForegroundColor Green
} else {
if ($check.ContainsKey("Warning") -and $check.Warning) {
Write-Host "[WARN] $($check.Name) : $($check.Error)" -ForegroundColor Yellow
} else {
Write-Host "[KO] $($check.Name) : $($check.Error)" -ForegroundColor Red
$failed = $true
}
}
}
Write-Host ""
if ($failed) {
throw "Pré-requis non satisfaits. Impossible de continuer."
}
}
function Test-ParameterCoherence {
param(
[bool]$Basic,
[bool]$Negotiate,
[bool]$AllowUnencrypted
)
$errors = @()
if (-not $Basic -and -not $Negotiate) {
$errors += "Aucune méthode d'authentification n'est paramétrée. Veuillez choisir Basic ou Negotiate."
}
if ($Basic -and -not $AllowUnencrypted) {
$errors += "La configuration a été interrompue par l'utilisateur.`n Veuillez choisir une des deux configurations suivante d'authentification :`n - Basic avec AllowUnencrypted`n - NTLM (recommandé)"
}
if (-not $Basic -and $Negotiate -and $AllowUnencrypted) {
$errors += "Negotiate ne nécessite pas une connection chiffré (AllowUnencrypted). Il est déconseillé de l'activer."
}
if ( -not $Basic -and $AllowUnencrypted) {
$errors += "AllowUnencrypted ne peut pas être activé si Basic n'est pas activé."
}
if ($errors.Count -gt 0) {
Write-Host "`n ERREURS DE CONFIGURATION :" -ForegroundColor Red
$errors | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
Write-Host "`nUtilisez -Help pour plus d'informations`n" -ForegroundColor Yellow
exit 1
}
}
function ConvertTo-Boolean {
param([string]$value)
try {
return [System.Convert]::ToBoolean($value.ToString().Trim())
} catch {
throw "Paramètre booléen invalide: '$value'. Utilisez 'true' ou 'false'."
}
}
# ==============================================================================
# SECTION 2 : FONCTIONS DE GESTION DES MODES
# ==============================================================================
function Get-ExecutionMode {
param(
[string]$UserNameParam,
$PasswordParam,
[string]$BasicParam,
[string]$NegotiateParam,
[string]$AllowUnencryptedParam
)
if ($script:Version) {
return "version"
}
if ($script:Help) {
return "help"
}
if ($script:Default) {
return "default"
}
if ($script:Interactive) {
return "interactive"
}
if ((-not [string]::IsNullOrWhiteSpace($UserNameParam)) -or
($null -ne $PasswordParam) -or
(-not [string]::IsNullOrWhiteSpace($BasicParam)) -or
(-not [string]::IsNullOrWhiteSpace($NegotiateParam)) -or
(-not [string]::IsNullOrWhiteSpace($AllowUnencryptedParam))) {
return "manual"
}
return "none"
}
function Get-DefaultParameters {
return @{
UserName = $DEFAULT_USERNAME
Password = $DEFAULT_PASSWORD
Basic = $false
Negotiate = $true
AllowUnencrypted = $false
}
}
# ==============================================================================
# SECTION 3 : FONCTIONS INTERACTIVES
# ==============================================================================
function Read-BoolInteractive {
param(
[string]$Prompt,
[bool]$Default = $false
)
$defaultText = if ($Default) { "Y/n" } else { "y/N" }
$response = Read-Host "$Prompt [$defaultText]"
if ([string]::IsNullOrWhiteSpace($response)) {
return $Default
}
return ($response -eq "Y" -or $response -eq "y" -or $response -eq "yes")
}
function Read-SecureStringInteractive {
param([string]$Prompt)
$securePass = Read-Host $Prompt -AsSecureString
# Convertir en clair (nécessaire pour le script)
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($securePass)
$plainPass = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
return $plainPass
}
function Read-PasswordWithConfirmation {
param(
[string]$Prompt = " Mot de passe (saisie masquée)",
[bool]$ShowHelp = $false
)
if ($ShowHelp) {
Write-Host " Le mot de passe doit respecter la politique de sécurité Windows configurée." -ForegroundColor Gray
Write-Host " Recommandation : Utilisez un mot de passe robuste (8+ caractères, majuscules, minuscules, chiffres, symboles)`n" -ForegroundColor Gray
}
do {
$password = Read-SecureStringInteractive $Prompt
if ([string]::IsNullOrWhiteSpace($password)) {
Write-Host " Le mot de passe ne peut être vide" -ForegroundColor Red
exit 1
}
$confirmPassword = Read-SecureStringInteractive " Confirmer le mot de passe"
if ($password -ne $confirmPassword) {
Write-Host " Les mots de passe ne correspondent pas. Veuillez réessayer.`n" -ForegroundColor Red
}
} while ($password -ne $confirmPassword)
Write-Host " Mot de passe confirmé." -ForegroundColor Green
return $password
}
function Read-AuthenticationMethods {
param(
[string]$BasicParam,
[string]$NegotiateParam,
[string]$AllowUnencryptedParam,
[bool]$Interactive = $false
)
Write-Host "`n====== Authentification WinRM ======`n" -ForegroundColor Yellow
Write-Host " Deux méthodes d'authentification disponibles :" -ForegroundColor Gray
Write-Host " - Negotiate (recommandé) - Chiffrement automatique (NTLM)" -ForegroundColor Cyan
Write-Host " - Basic - Moins sécurisé, nécessite AllowUnencrypted`n" -ForegroundColor Gray
if ($Interactive) {
# Mode interactif : demander Negotiate d'abord
$parsedNegotiate = Read-BoolInteractive " Activer Negotiate ?" -Default $true
if ($parsedNegotiate) {
# Negotiate activé → Basic et AllowUnencrypted désactivés
Write-Host "`n [OK] Negotiate activé" -ForegroundColor Green
Write-Host " -> Basic et AllowUnencrypted désactivés automatiquement" -ForegroundColor Cyan
Write-Host " -> Configuration sécurisée`n" -ForegroundColor Green
$parsedBasic = $false
$parsedAllowUnencrypted = $false
} else {
# Negotiate désactivé → demander Basic
Write-Host "`n [ATTENTION] Negotiate désactivé" -ForegroundColor Yellow
Write-Host " -> Configuration de Basic...`n" -ForegroundColor Gray
$parsedBasic = Read-BoolInteractive " Activer Basic ?" -Default $false
if ($parsedBasic) {
Write-Host "`n [ATTENTION]`n L'authentification Basic nécessite d'autoriser`n la connexion non chiffrée HTTP (AllowUnencrypted).`n" -ForegroundColor Yellow
$parsedAllowUnencrypted = Read-BoolInteractive " Voulez-vous authoriser les connexions WinRM non-chiffrées ?" -Default $true
} else {
Write-Host "`n [ERREUR] Aucune méthode d'authentification configurée !" -ForegroundColor Red
$parsedAllowUnencrypted = $false
}
}
} else {
# Mode manual (non-interactif)
if ([string]::IsNullOrWhiteSpace($NegotiateParam)) {
$NegotiateParam = Read-Host " Negotiate (true/false)"
}
$parsedNegotiate = ConvertTo-Boolean $NegotiateParam
if ($parsedNegotiate) {
Write-Host " [OK] Negotiate activé" -ForegroundColor Green
Write-Host " -> Basic et AllowUnencrypted désactivés automatiquement`n" -ForegroundColor Cyan
$parsedBasic = $false
$parsedAllowUnencrypted = $false
} else {
Write-Host " [ATTENTION] Negotiate désactivé - Configuration de Basic..." -ForegroundColor Yellow
if ([string]::IsNullOrWhiteSpace($BasicParam)) {
$BasicParam = Read-Host " Basic (true/false)"
}
$parsedBasic = ConvertTo-Boolean $BasicParam
if ($parsedBasic) {
if ([string]::IsNullOrWhiteSpace($AllowUnencryptedParam)) {
$AllowUnencryptedParam = Read-Host " AllowUnencrypted (true/false)"
}
$parsedAllowUnencrypted = ConvertTo-Boolean $AllowUnencryptedParam
} else {
$parsedAllowUnencrypted = $false
}
}
}
# Validation finale
if (-not $parsedBasic -and -not $parsedNegotiate) {
Write-Host "`n [ERREUR] Aucune méthode d'authentification configurée !" -ForegroundColor Red
throw "Au moins une méthode d'authentification (Basic ou Negotiate) doit être activée."
}
return @{
Basic = $parsedBasic
Negotiate = $parsedNegotiate
AllowUnencrypted = $parsedAllowUnencrypted
}
}
function Start-InteractiveMode {
Write-Host "`n========================================================" -ForegroundColor Cyan
Write-Host " MODE INTERACTIF - Configuration guidée" -ForegroundColor Cyan
Write-Host "========================================================`n" -ForegroundColor Cyan
Write-Host "====== Utilisateur de supervision ======`n" -ForegroundColor Yellow
Write-Host " Le script va créer un nouvel utilisateur de supervision local." -ForegroundColor Gray
Write-Host " Si l'utilisateur existe déjà, il sera mis à jour avec les permissions nécessaires pour WinRM.`n" -ForegroundColor Gray
$script:UserName = Read-Host " Nom d'utilisateur (défaut: $DEFAULT_USERNAME)"
if ([string]::IsNullOrWhiteSpace($script:UserName)) {
$script:UserName = $DEFAULT_USERNAME
Write-Host " -> Utilisation de la valeur par défaut : $DEFAULT_USERNAME" -ForegroundColor Gray
}
Write-Host "`n====== Mot de passe ======`n" -ForegroundColor Yellow
$script:Password = Read-PasswordWithConfirmation -ShowHelp $true
$authResult = Read-AuthenticationMethods -Interactive $true
$script:ParsedBasic = $authResult.Basic
$script:ParsedNegotiate = $authResult.Negotiate
$script:ParsedAllowUnencrypted = $authResult.AllowUnencrypted
Test-ParameterCoherence -Basic $script:ParsedBasic -Negotiate $script:ParsedNegotiate -AllowUnencrypted $script:ParsedAllowUnencrypted
Write-Host "`n========================================================" -ForegroundColor DarkGray
Write-Host " RECAPITULATIF DE LA CONFIGURATION" -ForegroundColor Cyan
Write-Host "========================================================" -ForegroundColor DarkGray
Write-Host " UserName : $script:UserName" -ForegroundColor White
Write-Host " Password : ********" -ForegroundColor White
Write-Host " Negotiate : $script:ParsedNegotiate" -ForegroundColor White
Write-Host " Basic : $script:ParsedBasic" -ForegroundColor White
Write-Host " AllowUnencrypted : $script:ParsedAllowUnencrypted" -ForegroundColor White
Write-Host "========================================================`n" -ForegroundColor DarkGray
$confirm = Read-Host " Confirmer et lancer la configuration ? (Y/n)"
if ($confirm -and $confirm -ne "Y" -and $confirm -ne "y") {
Write-Host "`n Configuration annulée`n" -ForegroundColor Red
exit 0
}
}
# ==============================================================================
# SECTION 4 : FONCTIONS DE GESTION DES ÉTAPES
# ==============================================================================
function Add-StepResult {
param([string]$Name,[bool]$Ok,[string]$Msg="")
$icon = if ($Ok) {"OK"} else {"KO"}
$status = if ($Ok) {"Success"} else {"Failed"}
[void]$Steps.Add([PSCustomObject]@{ Step=$Name; Status=$status; Message="$icon $Msg" })
}
function Invoke-ConfigurationStep {
param([string]$Name,[scriptblock]$Action)
try {
& $Action
Add-StepResult -Name $Name -Ok $true -Msg "Étape réussie"
} catch {
Add-StepResult -Name $Name -Ok $false -Msg ("Erreur : " + $_.Exception.Message)
throw "Étape $Name échouée"
}
}
# ==============================================================================
# SECTION 5 : FONCTIONS DE CONFIGURATION WINDOWS
# ==============================================================================
function Verify-InstalledLanguage {
param([string[]]$LangCodes)
Write-Host "[1/10] Vérification des langues installées $LangCodes" -ForegroundColor Yellow
$languages = Get-WinUserLanguageList
$has_required_lang = $false
foreach ($lang in $LangCodes) {
if ($languages.LanguageTag -contains $lang) {
$has_required_lang = $true
Write-Host " Langue $lang disponible." -ForegroundColor Green
}
}
if ($has_required_lang -eq $false) {
Write-Host " Aucune langue requise trouvé." -ForegroundColor Red
Write-Host " Pour Windows 11, 10 et Windows Server 2025, la commande suivante est disponible :" -ForegroundColor Red
Write-Host " Install-Language -Language fr-FR -ExcludeFeatures" -ForegroundColor Gray
Write-Host ""
Write-Host " Pour les autres versions de Windows, veuillez installer la langue par interface et vous référer à la documentation de configuration du pack." -ForegroundColor Red
Write-Host ""
throw "Aucune des langues requises pour le pack n'est installé. Veuillez installer l'une des langues suivantes : $LangCodes"
}
}
function Set-WinRMConfiguration {
Write-Host "[2/10] Configuration rapide de WinRM" -ForegroundColor Yellow
winrm quickconfig -q
if ($LASTEXITCODE -ne 0) { throw "WinRM quickconfig a échoué ($LASTEXITCODE)" }
Write-Host " WinRM configuré." -ForegroundColor Green
Write-Host ""
}
function Add-UserToExistingGroup {
param(
[string]$UserName,
[string]$PrimaryGroup,
[string]$FallbackGroup
)
$groupUsed = $null
foreach ($grp in @($PrimaryGroup,$FallbackGroup)) {
$output = net localgroup "$grp" 2>$null
if ($LASTEXITCODE -eq 0) {
$groupUsed = $grp
break
}
}
if (-not $groupUsed) {
throw "Aucun des groupes '$PrimaryGroup' ou '$FallbackGroup' n'existe."
}
if ($output -match "^\s*$UserName\s*$") {
Write-Host " Utilisateur $UserName déjà dans le groupe $groupUsed" -ForegroundColor Gray
} else {
& net localgroup "$groupUsed" $UserName /ADD | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Échec ajout utilisateur $UserName dans le groupe $groupUsed ($LASTEXITCODE)"
} else {
Write-Host " Utilisateur $UserName ajouté au groupe $groupUsed" -ForegroundColor Green
}
}
}
function New-LocalUser {
param([string]$UserName, [string]$Password)
Write-Host "[3/10] Création de l'utilisateur $UserName" -ForegroundColor Yellow
net user $UserName 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
& net user $UserName $Password /ADD /Y | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "Échec création utilisateur via 'net user' ($LASTEXITCODE)"
}
} else {
Write-Host " Utilisateur déjà existant : $UserName" -ForegroundColor Gray
}
Add-UserToExistingGroup -UserName $UserName -PrimaryGroup "Remote Management Users" -FallbackGroup "Utilisateurs de gestion à distance"
Add-UserToExistingGroup -UserName $UserName -PrimaryGroup "Performance Monitor Users" -FallbackGroup "Utilisateurs de l’Analyseur de performances"
Add-UserToExistingGroup -UserName $UserName -PrimaryGroup "Event Log Readers" -FallbackGroup "Lecteurs des journaux d’événements"
$SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential ($UserName, $SecurePassword)
try {
Start-Process -FilePath "whoami.exe" -WorkingDirectory "$env:USERPROFILE" -Credential $Credential -WindowStyle Hidden -Wait
} catch {
Write-Host " Impossible de lancer un logon test pour $UserName ($_)" -ForegroundColor Red
}
Write-Host " Utilisateur $UserName créé/validé et groupes assignés." -ForegroundColor Green
}
function Set-UserLanguage {
param(
[string]$UserName,
[string[]]$LangCodes
)
Write-Host "[4/10] Configuration de la langue pour l'utilisateur $UserName" -ForegroundColor Yellow
$Computer = $env:COMPUTERNAME
$SID = (Get-WmiObject Win32_UserAccount -Filter "Name='$UserName' AND Domain='$Computer'").SID
if (-not $SID) { throw "Impossible de récupérer le SID pour $UserName" }
$UserProfile = Get-CimInstance Win32_UserProfile | Where-Object SID -eq $SID
if (-not $UserProfile) { throw "Profil introuvable pour $UserName" }
$HivePath = Join-Path $UserProfile.LocalPath "NTUSER.DAT"
if (-not (Test-Path $HivePath)) { throw "Profil non initialisé (NTUSER.DAT introuvable) : $HivePath" }
$regRelative = "Control Panel\Desktop"
$valueName = "PreferredUILanguages"
$IsLoaded = Test-Path "Registry::HKEY_USERS\$SID"
if ($IsLoaded) {
$fullPath = "Registry::HKEY_USERS\$SID\$regRelative"
if (-not (Test-Path $fullPath)) { New-Item -Path $fullPath -Force | Out-Null }
if (-not (Get-ItemProperty -Path $fullPath -Name $valueName -ErrorAction SilentlyContinue)) {
New-ItemProperty -Path $fullPath -Name $valueName -Value $LangCodes -PropertyType MultiString -Force | Out-Null
} else {
Set-ItemProperty -Path $fullPath -Name $valueName -Value $LangCodes
}
} else {
Write-Host " Utilisateur non connecté. Chargement de la ruche..." -ForegroundColor Gray
reg load "HKU\TempHive" $HivePath | Out-Null
try {
$tempPath = "Registry::HKEY_USERS\TempHive\$regRelative"
if (-not (Test-Path $tempPath)) { New-Item -Path $tempPath -Force | Out-Null }
if (-not (Get-ItemProperty -Path $tempPath -Name $valueName -ErrorAction SilentlyContinue)) {
New-ItemProperty -Path $tempPath -Name $valueName -Value $LangArray -PropertyType MultiString -Force | Out-Null
} else {
Set-ItemProperty -Path $tempPath -Name $valueName -Value $LangArray
}
} finally {
reg unload "HKU\TempHive" | Out-Null
Write-Host " Ruche déchargée." -ForegroundColor Gray
}
}
Write-Host " Langue préférée utilisateur définie sur $LangCodes (REG_MULTI_SZ)." -ForegroundColor Green
Write-Host ""
}
function Set-WinRMConfigurationAuth {
param([bool]$Basic, [bool]$Negotiate, [bool]$AllowUnencrypted)
Write-Host "[5/10] Configuration de l'authentification WinRM" -ForegroundColor Yellow
if ($Basic) {
winrm set winrm/config/service/auth '@{Basic="true"}'
}
if ($Negotiate) {
winrm set winrm/config/service/auth '@{Negotiate="true"}'
}
if ($AllowUnencrypted) {
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
}
Write-Host " Configuration d'authentification définie." -ForegroundColor Green
Write-Host ""
}
function Set-WinRMConfigurationSDDL {
param([string]$UserName)
Write-Host "[6/10] Attribution des droits WinRM (SDDL)" -ForegroundColor Yellow
$GENERIC_READ = 0x80000000
$GENERIC_EXECUTE = 0x20000000
$user_sid = (New-Object System.Security.Principal.NTAccount $UserName).Translate([System.Security.Principal.SecurityIdentifier])
$sddl = (Get-Item -Path WSMan:\localhost\Service\RootSDDL).Value
$sd = New-Object System.Security.AccessControl.CommonSecurityDescriptor $false, $false, $sddl
$sd.DiscretionaryAcl.AddAccess(
[System.Security.AccessControl.AccessControlType]::Allow,
$user_sid,
($GENERIC_READ -bor $GENERIC_EXECUTE),
[System.Security.AccessControl.InheritanceFlags]::None,
[System.Security.AccessControl.PropagationFlags]::None
)
$new_sddl = $sd.GetSddlForm([System.Security.AccessControl.AccessControlSections]::All)
Set-Item -Path WSMan:\localhost\Service\RootSDDL -Value $new_sddl -Force
Write-Host " Droits SDDL appliqués." -ForegroundColor Green
Write-Host ""
}
function Set-WinRMPermission {
param(
[parameter(Mandatory=$true,Position=0)][string] $namespace,
[parameter(Mandatory=$true,Position=1)][string] $operation,
[parameter(Mandatory=$true,Position=2)][string] $account,
[parameter(Position=3)][string[]] $permissions = $null,
[bool] $allowInherit = $false,
[bool] $deny = $false,
[string] $computerName = ".",
[System.Management.Automation.PSCredential] $credential = $null
)
Write-Host "[7/10] Attribution des droits WMI/CIM" -ForegroundColor Yellow
$ErrorActionPreference = "Stop"
function Get-AccessMaskFromPermission($permissions) {
$WBEM_ENABLE = 1
$WBEM_METHOD_EXECUTE = 2
$WBEM_FULL_WRITE_REP = 4
$WBEM_PARTIAL_WRITE_REP = 8
$WBEM_WRITE_PROVIDER = 0x10
$WBEM_REMOTE_ACCESS = 0x20
$READ_CONTROL = 0x20000
$WRITE_DAC = 0x40000
$WBEM_RIGHTS_FLAGS = $WBEM_ENABLE,$WBEM_METHOD_EXECUTE,$WBEM_FULL_WRITE_REP,
$WBEM_PARTIAL_WRITE_REP,$WBEM_WRITE_PROVIDER,$WBEM_REMOTE_ACCESS,
$READ_CONTROL,$WRITE_DAC
$WBEM_RIGHTS_STRINGS = "Enable","MethodExecute","FullWrite","PartialWrite",
"ProviderWrite","RemoteAccess","ReadSecurity","WriteSecurity"
$permissionTable = @{}
for ($i = 0; $i -lt $WBEM_RIGHTS_FLAGS.Length; $i++) {
$permissionTable.Add($WBEM_RIGHTS_STRINGS[$i].ToLower(), $WBEM_RIGHTS_FLAGS[$i])
}
$accessMask = 0
foreach ($permission in $permissions) {
if (-not $permissionTable.ContainsKey($permission.ToLower())) {
throw "Permission inconnue: $permission`nPermissions authorisées: $($permissionTable.Keys)"
}
$accessMask += $permissionTable[$permission.ToLower()]
}
$accessMask
}
if ($PSBoundParameters.ContainsKey("Credential")) {
$remoteparams = @{ComputerName=$computerName;Credential=$credential}
} else {
$remoteparams = @{}
}
$invokeparams = @{Namespace=$namespace;Path="__systemsecurity=@"} + $remoteParams
$output = Invoke-WmiMethod @invokeparams -Name GetSecurityDescriptor
if ($output.ReturnValue -ne 0) {
throw "GetSecurityDescriptor a échoué: $($output.ReturnValue)"
}
$acl = $output.Descriptor
$OBJECT_INHERIT_ACE_FLAG = 0x1
$CONTAINER_INHERIT_ACE_FLAG = 0x2
$computerName = (Get-WmiObject @remoteparams Win32_ComputerSystem).Name
if ($account.Contains('\')) {
$domainaccount = $account.Split('\')
$domain = $domainaccount[0]
if (($domain -eq ".") -or ($domain -eq "BUILTIN")) {
$domain = $computerName
}
$accountname = $domainaccount[1]
} elseif ($account.Contains('@')) {
$domainaccount = $account.Split('@')
$domain = $domainaccount[1].Split('.')[0]
$accountname = $domainaccount[0]
} else {
$domain = $computerName
$accountname = $account
}
$getparams = @{Class="Win32_Account";Filter="Domain='$domain' and Name='$accountname'"} + $remoteParams
$win32account = Get-WmiObject @getparams
if ($null -eq $win32account) {
throw "Compte utilisateur inconnu: $account"
}
switch ($operation) {
"add" {
if ($null -eq $permissions) {
throw "Les permissions doivent être spécifié."
}
$accessMask = Get-AccessMaskFromPermission($permissions)
$ace = (New-Object System.Management.ManagementClass("win32_Ace")).CreateInstance()
$ace.AccessMask = $accessMask
$ace.AceFlags = if ($allowInherit) { $OBJECT_INHERIT_ACE_FLAG + $CONTAINER_INHERIT_ACE_FLAG } else { 0 }
$trustee = (New-Object System.Management.ManagementClass("win32_Trustee")).CreateInstance()
$trustee.SidString = $win32account.Sid
$ace.Trustee = $trustee
$ace.AceType = if ($deny) { 0x1 } else { 0x0 }
$acl.DACL += $ace.psobject.immediateBaseObject
}
default {
throw "Opération inconnue: $operation`nOpérations authorisés : add"
}
}
$setparams = @{Name="SetSecurityDescriptor";ArgumentList=$acl.psobject.immediateBaseObject} + $invokeParams
$output = Invoke-WmiMethod @setparams
if ($output.ReturnValue -ne 0) {
throw "SetSecurityDescriptor a échoué: $($output.ReturnValue)"
}
}
function Set-W32TimePermission {
param([string]$UserName)
Write-Host "[8/9] Attribution des droits sur W32Time" -ForegroundColor Yellow
$sid = (New-Object System.Security.Principal.NTAccount($UserName)).Translate([System.Security.Principal.SecurityIdentifier]).Value
$currentSddl = & sc.exe sdshow w32time
$newAce = "(A;;CCLCLO;;;${sid})"
$newSddl = $currentSddl + $newAce
sc.exe sdset w32time "$newSddl"
Restart-Service w32time
Write-Host " Droits W32Time appliqués pour $UserName." -ForegroundColor Green
Write-Host ""
}
function Set-WinEventLogSecurityPermission {
param([string]$UserName)
Write-Host "[9/10] Attribution des droits sur WinEventLog Security" -ForegroundColor Yellow
try {
$Path = "HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Security"
$acl = Get-Acl $Path
$rule = New-Object System.Security.AccessControl.RegistryAccessRule(
$UserName,
"ReadKey",
"Allow"
)
$acl.AddAccessRule($rule)
Set-Acl $Path $acl
Write-Host " Droits Registre appliqués." -ForegroundColor Green
} catch {
Write-Host " Erreur permissions EventLog Security: $_" -ForegroundColor Red
throw
}
}
function Restart-WinRMServices {
Write-Host "[10/10] Redémarrage des services WinRM et WinMgmt" -ForegroundColor Yellow
try {
Write-Host " Redémarrage du service winmgmt (Windows Management Instrumentation)..." -ForegroundColor Gray
Restart-Service -Name winmgmt -Force -ErrorAction Stop
Write-Host " Service winmgmt redémarré avec succès." -ForegroundColor Green
} catch {
Write-Host " Erreur lors du redémarrage de winmgmt : $_" -ForegroundColor Red
throw
}
try {
Write-Host " Redémarrage du service WinRM (Windows Remote Management)..." -ForegroundColor Gray
Restart-Service -Name WinRM -Force -ErrorAction Stop
Write-Host " Service WinRM redémarré avec succès." -ForegroundColor Green
} catch {
Write-Host " Erreur lors du redémarrage de WinRM : $_" -ForegroundColor Red
throw
}
Write-Host " Les services ont été redémarrés et sont opérationnels." -ForegroundColor Green
Write-Host ""
}
# ==============================================================================
# SECTION 6 : ORCHESTRATION
# ==============================================================================
function Invoke-ConfigurationSteps {
$LangCodes = "en-US", "fr-FR"
$script:ConfigurationSuccess = $true
try {
Invoke-ConfigurationStep "Langue $LangCodes" { Verify-InstalledLanguage -LangCodes $LangCodes }
Invoke-ConfigurationStep "WinRM quickconfig" { Set-WinRMConfiguration }
Invoke-ConfigurationStep "Création utilisateur + Ajout aux groupes" { New-LocalUser -UserName $script:UserName -Password $script:Password }
Invoke-ConfigurationStep "Langue UI du profil" { Set-UserLanguage -UserName $script:UserName -LangCodes $LangCodes }
Invoke-ConfigurationStep "WinRM Auth" { Set-WinRMConfigurationAuth $script:ParsedBasic $script:ParsedNegotiate $script:ParsedAllowUnencrypted }
Invoke-ConfigurationStep "WinRM RootSDDL" { Set-WinRMConfigurationSDDL -UserName $script:UserName }
Invoke-ConfigurationStep "WMI/CIM root\cimv2" { Set-WinRMPermission "root/cimv2" add $script:UserName Enable,RemoteAccess }
Invoke-ConfigurationStep "WMI/CIM root\standardcimv2" { Set-WinRMPermission "root/standardcimv2" add $script:UserName Enable,RemoteAccess }
Invoke-ConfigurationStep "W32Time SDDL" { Set-W32TimePermission -UserName $script:UserName }
Invoke-ConfigurationStep "WinEventLog Security" { Set-WinEventLogSecurityPermission -UserName $script:UserName }
Invoke-ConfigurationStep "Redémarrage services" { Restart-WinRMServices }
} catch {
Write-Host "$($_.Exception.Message)" -ForegroundColor Red
$script:ConfigurationSuccess = $false
}
}
function Start-HostConfiguration {
Write-Host "========================================================" -ForegroundColor DarkGray
Write-Host "CONFIGURE PACK [windows-by-WinRM] for supervised host" -ForegroundColor Cyan
Write-Host "========================================================" -ForegroundColor DarkGray
Write-Host ""
$script:ConfigurationSuccess = $true
Invoke-ConfigurationSteps
Write-Host ""
Write-Host ("=" * 70) -ForegroundColor DarkGray
Write-Host "RÉSUMÉ DES ÉTAPES" -ForegroundColor Yellow
Write-Host ("=" * 70) -ForegroundColor DarkGray
foreach ($s in $Steps) {
if ($s.Status -eq "Success") {
Write-Host ("[OK] {0} : {1}" -f $s.Step, $s.Message) -ForegroundColor Green
} else {
Write-Host ("[KO] {0} : {1}" -f $s.Step, $s.Message) -ForegroundColor Red
$script:ConfigurationSuccess = $false
}
}
Write-Host ("=" * 70) -ForegroundColor DarkGray
return $script:ConfigurationSuccess
}
# ==============================================================================
# SECTION 7 : LOGIQUE PRINCIPALE
# ==============================================================================
$ExecutionMode = Get-ExecutionMode -UserNameParam $UserName -PasswordParam $Password -BasicParam $Basic -NegotiateParam $Negotiate -AllowUnencryptedParam $AllowUnencrypted
switch ($ExecutionMode) {
"none" {
Write-Host "`n ERREUR : Aucun paramètre fourni`n" -ForegroundColor Red
Write-Host "Usage :"
Write-Host " .\Configure-Host.ps1 -Default # Valeurs par défaut"
Write-Host " .\Configure-Host.ps1 -Interactive # Mode assistant"
Write-Host " .\Configure-Host.ps1 -Help # Aide complète"
Write-Host " .\Configure-Host.ps1 -UserName ... -Password ... -Basic true ...`n"
Write-Host " .\Configure-Host.ps1 -Version"
exit 1
}
"version" {
Get-Version
exit 0
}
"help" {
Get-Help $PSCommandPath -Detailed
exit 0
}
"default" {
Test-Prerequisites
Write-Host "`n Mode par défaut activé`n" -ForegroundColor Cyan
$defaults = Get-DefaultParameters
Write-Host "Paramètres utilisés :"
Write-Host " UserName : $($defaults.UserName)"
Write-Host " Password : ********"
Write-Host " Negotiate : $($defaults.Negotiate)"
Write-Host " Basic : $($defaults.Basic)"
Write-Host " AllowUnencrypted : $($defaults.AllowUnencrypted)`n"
$confirm = Read-Host "Continuer avec ces paramètres ? (Y/n)"
if ($confirm -and $confirm -ne "Y" -and $confirm -ne "y") {
Write-Host "Configuration annulée" -ForegroundColor Red
exit 0
}
$script:UserName = $defaults.UserName
$script:Password = $defaults.Password
$script:ParsedBasic = $defaults.Basic
$script:ParsedNegotiate = $defaults.Negotiate
$script:ParsedAllowUnencrypted = $defaults.AllowUnencrypted
Test-ParameterCoherence -Basic $script:ParsedBasic -Negotiate $script:ParsedNegotiate -AllowUnencrypted $script:ParsedAllowUnencrypted
}
"interactive" {
Test-Prerequisites
Start-InteractiveMode
}
"manual" {
Test-Prerequisites
Write-Host "`n Mode manuel `n" -ForegroundColor Cyan
if ([string]::IsNullOrWhiteSpace($UserName)) {
$UserName = Read-Host "Nom d'utilisateur"
if ([string]::IsNullOrWhiteSpace($UserName)) {
Write-Host "Le nom d'utilisateur ne peut être vide" -ForegroundColor Red
exit 1
}
}
if ($null -eq $Password) {
$PlainPassword = Read-PasswordWithConfirmation -ShowHelp $true
} elseif ($Password -is [SecureString]) {
# Convertir SecureString en string si nécessaire
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
$PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
} else {
$PlainPassword = $Password
}
$authResult = Read-AuthenticationMethods -BasicParam $Basic -NegotiateParam $Negotiate -AllowUnencryptedParam $AllowUnencrypted -Interactive $false
$ParsedBasic = $authResult.Basic
$ParsedNegotiate = $authResult.Negotiate
$ParsedAllowUnencrypted = $authResult.AllowUnencrypted
Test-ParameterCoherence -Basic $ParsedBasic -Negotiate $ParsedNegotiate -AllowUnencrypted $ParsedAllowUnencrypted
Write-Host "`n==========================================" -ForegroundColor DarkGray
Write-Host "RÉCAPITULATIF DE LA CONFIGURATION" -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor DarkGray
Write-Host " UserName : $UserName"
Write-Host " Password : ********"
Write-Host " Negotiate : $ParsedNegotiate"
Write-Host " Basic : $ParsedBasic"
Write-Host " AllowUnencrypted : $ParsedAllowUnencrypted"
Write-Host "==========================================" -ForegroundColor DarkGray
$confirm = Read-Host "Confirmer et lancer la configuration ? (Y/n)"
if ($confirm -and $confirm -ne "Y" -and $confirm -ne "y") {
Write-Host "Configuration annulée" -ForegroundColor Red
exit 0
}
$script:UserName = $UserName
$script:Password = $PlainPassword
$script:ParsedBasic = $ParsedBasic
$script:ParsedNegotiate = $ParsedNegotiate
$script:ParsedAllowUnencrypted = $ParsedAllowUnencrypted
}
}
$ConfigSuccess = Start-HostConfiguration
# ==============================================================================
# AFFICHAGE DES ÉTAPES POST-CONFIGURATION
# ==============================================================================
# Afficher les instructions uniquement si la configuration a réussi
if ($ConfigSuccess -eq $true) {
Write-Host ""
Write-Host ("=" * 70) -ForegroundColor Cyan
Write-Host " ÉTAPES SUIVANTES - POST-CONFIGURATION" -ForegroundColor Yellow
Write-Host ("=" * 70) -ForegroundColor Cyan
Write-Host ""
Write-Host " La configuration automatique du poste Windows est terminée avec succès !" -ForegroundColor Green
Write-Host ""
Write-Host " IMPORTANT : Vous devez maintenant effectuer MANUELLEMENT les étapes suivantes" -ForegroundColor Yellow
Write-Host " pour valider la configuration et continuer l'installation du pack windows-by-WinRM :" -ForegroundColor Yellow
Write-Host ""
# Étape 1 : Test du pare-feu
Write-Host " [1] VÉRIFIER LE PARE-FEU WINDOWS" -ForegroundColor Yellow
Write-Host " Vérifiez que la règle WinRM autorise le port 5985 :`n" -ForegroundColor Gray
Write-Host " Get-NetFirewallRule -Name `"WINRM-HTTP-In-TCP`"`n" -ForegroundColor White
Write-Host " Résultat attendu : Enabled=True, Action=Allow`n" -ForegroundColor Gray
# Étape 2 : Test WinRM local
Write-Host " [2] TESTER WINRM EN LOCAL" -ForegroundColor Yellow
Write-Host " Testez la connexion WinRM avec l'utilisateur configuré :`n" -ForegroundColor Gray
if ($script:ParsedNegotiate) {
Write-Host " Test-WSMan -ComputerName localhost -Credential (Get-Credential) ``" -ForegroundColor White
Write-Host " -Authentication Negotiate`n" -ForegroundColor White
} elseif ($script:ParsedBasic) {
Write-Host " Test-WSMan -ComputerName localhost -Credential (Get-Credential) ``" -ForegroundColor White
Write-Host " -Authentication Basic`n" -ForegroundColor White
}
Write-Host " Identifiants à saisir :" -ForegroundColor Gray
Write-Host " - Utilisateur : $script:UserName" -ForegroundColor Cyan
Write-Host " - Mot de passe : (celui défini lors de la configuration)`n" -ForegroundColor Cyan
Write-Host " Résultat attendu : Réponse WSMan avec ProductVendor, ProductVersion, etc.`n" -ForegroundColor Gray
# Étape 3 : Configuration Shinken
Write-Host " [3] CONFIGURER DANS LE SYNCHRONIZER" -ForegroundColor Yellow
Write-Host " - Accédez au Synchronizer pour choisir, accrocher et paramétrer les modèles d'hôtes fournis dans le pack :" -ForegroundColor Gray
Write-Host " * windows-by-WinRM" -ForegroundColor Cyan
Write-Host " * windows-by-WinRM__extra " -ForegroundColor Cyan
Write-Host " * windows-by-WinRM__advanced " -ForegroundColor Cyan
Write-Host " - Testez les données d'authentification" -ForegroundColor Gray
Write-Host " - Testez le bon fonctionnement des checks`n" -ForegroundColor Gray
} else {
Write-Host ""
Write-Host ("=" * 70) -ForegroundColor Red
Write-Host " CONFIGURATION ÉCHOUÉE" -ForegroundColor Red
Write-Host ("=" * 70) -ForegroundColor Red
Write-Host ""
Write-Host " Une ou plusieurs étapes ont échoué." -ForegroundColor Yellow
Write-Host " Consultez le résumé ci-dessus pour identifier les erreurs.`n" -ForegroundColor Yellow
Write-Host ""
exit 1
} |
Ensuite, il est nécessaire de déployer le script sur chaque machine Windows à superviser.
Les méthodes de déploiement du script vont dépendre de votre environnement et de vos outils ( SSH, FTP, cloud, docker, Ansible, Terraform ... ) . |
Avant de déployer le script de configuration sur plusieurs serveurs Windows à superviser, il est fortement conseillé de tester le script de configuration sur UN serveur Windows, pour valider son comportement dans votre environnement. |
Nous vous recommandons d'utiliser vos propres solutions de déploiement afin de correspondre à vos enjeux de sécurités. Néanmoins, voici un exemple de déploiement via SSH.
Déploiement du script de configuration Windows via SSH :
Si le poste Windows à superviser dispose déjà d’un serveur SSH, il est possible d’y transférer directement le script de configuration.
Le script fourni se trouve dans le pack, sous le répertoire "supervised-host". Il est identique à celui présenté précédemment dans la documentation.
Exemple :
scp supervised-host/Configure-Host.ps1 Administrateur@<IP_HOST>:C:/Users/Administrateur/ |
Il est nécessaire pour les hôtes supervisés d'avoir d'installé au moins une des langues suivantes, pour le bon fonctionnement de la sonde :
La commande suivante permet d'afficher les langues installées sur votre machine :
Un résultat similaire à celui-la sera obtenu :
Alors, si vos Windows à superviser ont au moins une des langues nécessaires, passer à l'étape suivante. Sinon, voici quelques outils pour installer de nouvelles langues : Ici, la langue configurée n'a pas d'impact sur la traduction et l'affichage des résultats générés par la sonde, mais a un impact sur le bon fonctionnement. Pour les Windows ci-dessous, il est possible d'exécuter la commande suivante afin d'installer une langue :
Pour les autres versions de Windows Server, d'autres solutions existent :
Une façon de déployer un nouveau langage sur ses machines supervisées est d'utiliser Windows Feature On Demand ( FoD ) afin d'installer un pack de langue.
Pour les installations hors-ligne, il est possible de demander à son support Microsoft le pack de langue livré dans un fichier .iso ou .cab. Il faudra ensuite le déployer et l'installer avec l'outil DISM.EXE. Plus d'informations ici : https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/features-on-demand-v2--capabilities?view=windows-11. Sinon, il est possible d'installer les langues par interface graphique. |
Il est possible d'afficher l'aide du script avec la commande suivante :
.\Configure-Host.ps1 -Help |
La commande ci-dessous permet de configurer votre poste Windows avec les paramètres par défaut livrés avec les modèles hôtes.
.\Configure-Host.ps1 -Default |
La configuration par défaut est une bonne façon de tester le pack, mais il est recommandé de changer les paramètres d'authentification pour des environnements exposés. |
Ensuite, redémarrez le poste Windows à superviser afin d'appliquer les permissions, et passer à l'étape "Tester le pare-feu et WinRM"
La commande ci-dessous permet de configurer votre poste Windows pas à pas.
.\Configure-Host.ps1 -Interactive |
Il faudra ensuite entrer les paramètres demandés. Voici un example de configuration pas à pas :
|
Il est également possible de passer dans la ligne de commande les paramètres configurables :
.\Configure-Host.ps1 -UserName MyNewUser -Password MyNewPassword -Negotiate true -Basic false -AllowUnencrypted false |
Ensuite, redémarrez votre ordinateur afin d'appliquer les permissions, et passer à l'étape "Tester le pare-feu et WinRM"
Il est possible que vous obteniez l'erreur suivante. Par défaut, PowerShell peut empêcher l’exécution de scripts pour des raisons de sécurité. Cette restriction est contrôlée par votre stratégie d'exécution ( Execution Policy ) .
|
La solution suivante est de modifier temporairement la stratégie d'exécution :
Set-ExecutionPolicy Unrestricted -Scope Process |
|
Il est maintenant possible de relancer le script dans le même terminal PowerShell.
Les tests suivants sont à effectuer sur le poste Windows à superviser. |
L'objectif de ce test est de vérifier si le pare-feu possède une règle qui autorise la connexion WinRM.
Exécuter la commande (en administrateur) :
Get-NetFirewallRule -Name "WINRM-HTTP-In-TCP" |

Si ce n'est pas le cas, activer la règle ( toujours avec les droits administrateurs ):
Enable-NetFirewallRule -Name "WINRM-HTTP-In-TCP" |
L'objectif de ce test est de réaliser en local une connexion WinRM, avec les outils fournis par Windows.
Avec la commande "Test-WSMan" :
Si vous avez configuré Negotiate :
Test-WSMan localhost -Credential (Get-Credential) -Authentication Negotiate |
Si vous avez configuré Basic :
Test-WSMan localhost -Credential (Get-Credential) -Authentication Basic |
|
Résultat attendu :
![]() |
Cela confirme que le service WinRM et l'utilisateur de supervision sont actifs et opérationnels sur la machine.
Une fois ces deux tests validés, la configuration du poste Windows est terminée et il est prêt à être supervisé. L'étape suivante est de choisir, d'accrocher et de paramétrer les modèles d'hôtes fournis dans le pack ( Voir la page Modèles d'hôtes du pack windows-by-WinRM__shinken ). |
WinRM dispose d'une commande de configuration intégrée qui permet entre autres de :
Pour effectuer les actions de configuration, il suffit d'exécuter la commande suivante :
winrm quickconfig |
Exemple :
C:\Users\Administrateur> winrm quickconfig WinRM n'est pas configuré pour la gestion à distance de cet ordinateur. Les modifications suivantes doivent être effectuées : Créez un écouteur WinRM sur HTTP://* pour accepter les demandes de la gestion des services Web sur toutes les adresses IP de cet ordinateur. Activez l'exception de pare-feu WinRM. Configurez LocalAccountTokenFilterPolicy pour attribuer des droits d'administration à distance à des utilisateurs locaux. Effectuer ces modifications [y/n] ? y WinRM a été mis à jour pour la gestion à distance. Écouteur WinRM créé sur HTTP://* pour accepter les demandes de la gestion des services Web sur toutes les adresses IP de cet ordinateur. Exception de pare-feu WinRM activée. LocalAccountTokenFilterPolicy configuré pour attribuer des droits d'administration à distance à des utilisateurs locaux. |
Attention, Sur Windows 11 et Windows 10 l'hôte a besoin d'être en réseau privé et non public qui est par défaut. Sinon la configuration sera bloquée et non appliquée :
|
Sur Windows 11 et Windows 10, il est necessaire de configurer le démarrage automatique de WinRM :
|
Selon le choix du mode d'authentification, il faut configurer l'authentification à WinRM.
Plus de détails sur l'authentification ici ( Modèles d'hôtes du pack windows-by-WinRM__shinken ).
Par défaut, le service WinRM est configuré pour autoriser l'authentification "Negotiate" et désactive par défaut "Basic".
"Negotiate" est le protocole de négociation nécessaire pour communiquer via ntlm.
L'authentification ntlm peut être activé en configurant "Negotiate" avec la commande suivante :
winrm set winrm/config/service/auth '@{Negotiate="true"}' |
L’utilisation du protocole « Basic » n’est pas recommandée lorsque des modes d’authentification plus sécurisés sont disponibles sur le système. |
winrm set winrm/config/service/auth '@{Basic="true"}' |
L'authentification basic n'ajoute pas d'encryption, alors il est necessaire de configurer le Windows pour accepter les communications non-chiffrées :
winrm set winrm/config/service '@{AllowUnencrypted="true"}' |
La configuration nécessite la création d'un utilisateur spécifiquement utilisé pour la supervision via ce pack. Cet utilisateur bénéficiera de permissions nécessaires à la supervision et permettra à la sonde du pack de se connecter à distance afin d'exécuter des commandes.
L'utilisation du compte administrateur du poste Windows permettrait d'obtenir toutes les informations du système, car celui-ci possède par défaut tous les droits d'accès ( WMI, WinRM, etc. ).
Cependant, pour des raisons de sécurité, il n'est pas conseillé de l'utiliser pour effectuer la supervision. Il faut alors créer un utilisateur qui exécutera les commandes demandées par les sondes, avec uniquement les droits nécessaires.
Voici la procédure pour créer un nouvel utilisateur dédié à la supervision avec les droits suffisant pour collecter les informations nécessaires au fonctionnement des sondes fournies par Shinken.
Sur le poste Windows à superviser, ouvrir "Gestion de l'ordinateur" ( compmgmt.msc ) puis dans Utilisateurs et groupes locaux > Utilisateurs, clic droit et Nouvel utilisateur...

Dans un PowerShell en Administrateur sur le poste Windows supervisé :
& {
param(
[Parameter(Mandatory=$true)]
[string]$UserName,
[Parameter(Mandatory=$true)]
[string]$Password
)
net user $Username $Password /ADD
} |
Pour assurer l'interprétation des commandes Windows par la sonde, il est nécessaire d'avoir une des langues suivantes, et de la configurer pour son utilisateur de supervision :
La commande suivante permet d'afficher les langues installées sur la machine :
Get-WinUserLanguageList |
Voici un exemple de résultat de la commande.
LanguageTag : en-US
Autonym : English (United States)
EnglishName : English
LocalizedName : English (United States)
ScriptName : Latin
InputMethodTips : {0409:0001040C}
Spellchecking : True
Handwriting : False
LanguageTag : fr-FR
Autonym : Français (France)
EnglishName : French
LocalizedName : French (France)
ScriptName : Latin
InputMethodTips : {040C:0000040C}
Spellchecking : True
Handwriting : False |
Si au moins une des langues nécessaires est installée, alors il faut la configurer pour l'utilisateur de supervision, passez à l'étape suivante.
Sinon, installer une des langues requises.
La première étape est de télécharger la langue "English (United-States)" depuis le compte de l'administrateur.
Lancer les paramètres Windows puis accéder à la catégorie "Heure et Langue".
|
Ensuite, accéder à la sous-catégorie "Langue" puis sélectionner "Ajouter une langue"
|
Dans la nouvelle fenêtre, choisir "English (United-States)", et installer la langue.
![]() |
La langue sera désormais listée. Cliquer dessus et sélectionner "Option", puis s'assurer que le module linguistique est installé.
|
La langue "English (United-States)" est désormais disponible sur la machine et il est nécessaire de l'ajouter depuis le compte de supervision.
Après avoir ouvert un PowerShell en mode administrateur ( sur le compte administrateur de la machine ) :
La commande ci-dessous va installer le pack de langage nécessaire à la sonde.
Cette commande n'est disponible que sur Windows 10, Windows 11 et Windows Server 2025. |
Cette opération peut prendre 5 à 30 minutes en fonction de votre machine et de la charge des serveurs de téléchargement Windows.
# Installer la langue en Anglais Install-Language -Language en-US -ExcludeFeatures # Installer la langue en Francais Install-Language -Language fr-FR -ExcludeFeatures |
Il est nécessaire de se connecter au nouveau compte de supervision créé pour changer la langue de l'utilisateur. |
Répéter les mêmes étapes que pour l'installation de la langue par l'administrateur.
Lors de l'installation, sélectionner "Installer le module linguistique et définir comme ma langue d'affichage Windows".
Une fois installé, s'assurer que :
![]() |
|
Une fois le pack de langue téléchargé, il est possible de l'appliquer au nouvel utilisateur de supervision créé :
& {
param(
[Parameter(Mandatory=$true)]
[string]$UserName,
[Parameter(Mandatory=$true)]
[string]$Password
)
$LangCode = "en-US", "fr-FR"
$Computer = $env:COMPUTERNAME
$SID = (Get-WmiObject Win32_UserAccount -Filter "Name='$UserName' AND Domain='$Computer'").SID
if (-not $SID) { throw "Impossible de récupérer le SID pour $UserName" }
# Recupération du profil
$UserProfile = Get-CimInstance Win32_UserProfile | Where-Object SID -eq $SID
# Le profil peut ne pas exister si l'utilisateur a été créé mais jamais été connecté.
# Tentative de connection à l'utilisateur ...
if (-not $UserProfile) {
$SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential ($UserName, $SecurePassword)
try {
Start-Process -FilePath "whoami.exe" -Credential $Credential -WindowStyle Hidden -Wait
} catch {
Write-Host "Impossible de lancer un logon test pour $UserName ($_)" -ForegroundColor Red
}
# Récupération à nouveau du profil
$UserProfile = Get-CimInstance Win32_UserProfile | Where-Object SID -eq $SID
}
if (-not $UserProfile) { throw "Profil introuvable pour $UserName" }
$HivePath = Join-Path $UserProfile.LocalPath "NTUSER.DAT"
if (-not (Test-Path $HivePath)) { throw "Profil non initialisé (NTUSER.DAT introuvable) : $HivePath" }
$regRelative = "Control Panel\Desktop"
$valueName = "PreferredUILanguages"
$IsLoaded = Test-Path "Registry::HKEY_USERS\$SID"
if ($IsLoaded) {
$fullPath = "Registry::HKEY_USERS\$SID\$regRelative"
if (-not (Test-Path $fullPath)) { New-Item -Path $fullPath -Force | Out-Null }
if (-not (Get-ItemProperty -Path $fullPath -Name $valueName -ErrorAction SilentlyContinue)) {
New-ItemProperty -Path $fullPath -Name $valueName -Value $LangCode -PropertyType MultiString -Force | Out-Null
} else {
Set-ItemProperty -Path $fullPath -Name $valueName -Value $LangCode
}
} else {
Write-Host "Utilisateur non connecté. Chargement de la ruche..." -ForegroundColor Gray
reg load "HKU\TempHive" $HivePath | Out-Null
try {
$tempPath = "Registry::HKEY_USERS\TempHive\$regRelative"
if (-not (Test-Path $tempPath)) { New-Item -Path $tempPath -Force | Out-Null }
if (-not (Get-ItemProperty -Path $tempPath -Name $valueName -ErrorAction SilentlyContinue)) {
New-ItemProperty -Path $tempPath -Name $valueName -Value $LangCode -PropertyType MultiString -Force | Out-Null
} else {
Set-ItemProperty -Path $tempPath -Name $valueName -Value $LangCode
}
} finally {
reg unload "HKU\TempHive" | Out-Null
Write-Host "Ruche déchargée." -ForegroundColor Gray
}
}
Write-Host "Langue préférée utilisateur définie sur $LangCode (REG_MULTI_SZ)." -ForegroundColor Green
} |
Ensuite, il est nécessaire de se déconnecter puis se reconnecter au nouvel utilisateur afin de correctement appliquer le changement de langue. |
Une fois l’opération réalisée, il est possible de se reconnecter au compte administrateur Windows et de poursuivre la configuration.
Une fois le nouvel utilisateur créé sur le poste client, et sa langue configurée, il faut ajouter sur le poste Windows concerné l'utilisateur dans les groupes suivants :
Cela s'effectue dans la console de "Gestion de l'ordinateur" ( compmgmt.msc ) puis dans Utilisateurs et groupes locaux > Groupes, clic droit sur le groupe puis Propriétés. Une nouvelle fenêtre s'ouvre, cliquer sur Ajouter… :

Dans un PowerShell :
Si la langue de l'utilisateur administrateur est français :
& {
param([Parameter(Mandatory=$true)][string]$UserName)
net localgroup "Utilisateurs de gestion à distance" $UserName /ADD
net localgroup "Utilisateurs de l’Analyseur de performances" $UserName /ADD
}
|
Si la langue de l'utilisateur administrateur est anglais :
& {
param([Parameter(Mandatory=$true)][string]$UserName)
net localgroup "Remote Management Users" $UserName /ADD
net localgroup "Performance Monitor Users" $UserName /ADD
}
|
Il est possible que la commande "net localgroup "Utilisateurs de l’Analyseur de performances" $UserName /ADD" ne fonctionne pas lors d'un copier-coller. Exemple du bug du copier-coller dans un terminal PowerShell Administrateur où l'apostrophe n'est pas retranscrite :
|
.
Il est nécessaire d'ajouter les droits de lecture et d'exécution aux commandes WinRM au nouvel utilisateur de supervision :
Dans une console PowerShell en Administrateur, exécuter la commande suivante :
winrm configSDDL default |
Une nouvelle fenêtre s'ouvre. Dans celle-ci, ajouter le nouvel utilisateur et cliquer sur Ajouter... et attribuer les droits :
En cochant les cases correspondantes dans le tableau des droits situé en dessous de la liste des utilisateurs ( cliquer sur l'utilisateur au préalable ).
|
Dans un PowerShell :
& {
param(
[Parameter(Mandatory = $true)][string]$UserName
)
$GENERIC_READ = 0x80000000
$GENERIC_EXECUTE = 0x20000000
$user_sid = (New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList $UserName).Translate([System.Security.Principal.SecurityIdentifier])
# get the existing SDDL of the WinRM listener
$sddl = (Get-Item -Path WSMan:\localhost\Service\RootSDDL).Value
# convert the SDDL string to a SecurityDescriptor object
$sd = New-Object -TypeName System.Security.AccessControl.CommonSecurityDescriptor -ArgumentList $false, $false, $sddl
# apply a new DACL to the SecurityDescriptor object
$sd.DiscretionaryAcl.AddAccess(
[System.Security.AccessControl.AccessControlType]::Allow,
$user_sid,
($GENERIC_READ -bor $GENERIC_EXECUTE),
[System.Security.AccessControl.InheritanceFlags]::None,
[System.Security.AccessControl.PropagationFlags]::None
)
# get the SDDL string from the changed SecurityDescriptor object
$new_sddl = $sd.GetSddlForm([System.Security.AccessControl.AccessControlSections]::All)
# apply the new SDDL to the WinRM listener
Set-Item -Path WSMan:\localhost\Service\RootSDDL -Value $new_sddl -Force
Write-Host "Permissions de 'Lecture' et 'Execution' WinRM ajoutées pour l'utilisateur $UserName" -ForegroundColor Green
} |
La sonde va demander les informations systèmes via les objets CIM, il est nécessaire d'ajouter les droits à l'utilisateur.
Cette section n'est pas nécessaire si les machines supervisées sont configurées avec un Active Directory. |
Il faut en premier temps lancer la fenêtre de contrôle WMI avec la commande :
wmimgmt.msc |
Une fois lancé, clic droit sur Contrôle WMI (local) puis sélectionner Propriétés.
|
Accéder à la section Sécurité, puis dans l'arborescence ci-dessous, sélectionner Root > CIMV2 puis cliquer sur le bouton Sécurité situé en bas à droite.
|
Enfin, ajouter l'utilisateur afin de lui appliquer de nouveaux droits, puis cocher Activer le compte et Appel à distance autorisé.
|
Ensuite, répétez l'opération pour StandardCimV2
|
Dans un PowerShell en Administrateur. Ce script permet d'ajouter les droits nécessaires à la lecture des objets CIM.
&{
Param (
[parameter(Mandatory=$true)][string] $username,
[bool] $allowInherit = $false,
[bool] $deny = $false,
[string] $computerName = ".",
[System.Management.Automation.PSCredential] $credential = $null
)
$namespaces = @("root\cimv2", "root\standardcimv2")
$permissions = @("Enable", "RemoteAccess")
foreach ($namespace in $namespaces) {
Write-Host "Configuration des permissions pour le namespace: $namespace"
$ErrorActionPreference = "Stop"
Function Get-AccessMaskFromPermission($permissions) {
$WBEM_ENABLE = 1
$WBEM_METHOD_EXECUTE = 2
$WBEM_FULL_WRITE_REP = 4
$WBEM_PARTIAL_WRITE_REP = 8
$WBEM_WRITE_PROVIDER = 0x10
$WBEM_REMOTE_ACCESS = 0x20
$READ_CONTROL = 0x20000
$WRITE_DAC = 0x40000
$WBEM_RIGHTS_FLAGS = $WBEM_ENABLE,$WBEM_METHOD_EXECUTE,$WBEM_FULL_WRITE_REP,`
$WBEM_PARTIAL_WRITE_REP,$WBEM_WRITE_PROVIDER,$WBEM_REMOTE_ACCESS,`
$READ_CONTROL,$WRITE_DAC
$WBEM_RIGHTS_STRINGS = "Enable","MethodExecute","FullWrite","PartialWrite",`
"ProviderWrite","RemoteAccess","ReadSecurity","WriteSecurity"
$permissionTable = @{}
for ($i = 0; $i -lt $WBEM_RIGHTS_FLAGS.Length; $i++) {
$permissionTable.Add($WBEM_RIGHTS_STRINGS[$i].ToLower(), $WBEM_RIGHTS_FLAGS[$i])
}
$accessMask = 0
foreach ($permission in $permissions) {
if (-not $permissionTable.ContainsKey($permission.ToLower())) {
throw "Unknown permission: $permission`nValid permissions: $($permissionTable.Keys)"
}
$accessMask += $permissionTable[$permission.ToLower()]
}
$accessMask
}
if ($PSBoundParameters.ContainsKey("Credential")) {
$remoteparams = @{ComputerName=$computerName;Credential=$credential}
} else {
$remoteparams = @{}
}
$invokeparams = @{Namespace=$namespace;Path="__systemsecurity=@"} + $remoteParams
$output = Invoke-WmiMethod @invokeparams -Name GetSecurityDescriptor
if ($output.ReturnValue -ne 0) {
throw "GetSecurityDescriptor failed: $($output.ReturnValue)"
}
$acl = $output.Descriptor
$OBJECT_INHERIT_ACE_FLAG = 0x1
$CONTAINER_INHERIT_ACE_FLAG = 0x2
$computerName = (Get-WmiObject @remoteparams Win32_ComputerSystem).Name
if ($username.Contains('\')) {
$domainaccount = $username.Split('\')
$domain = $domainaccount[0]
if (($domain -eq ".") -or ($domain -eq "BUILTIN")) {
$domain = $computerName
}
$accountname = $domainaccount[1]
} elseif ($username.Contains('@')) {
$domainaccount = $username.Split('@')
$domain = $domainaccount[1].Split('.')[0]
$accountname = $domainaccount[0]
} else {
$domain = $computerName
$accountname = $username
}
$getparams = @{Class="Win32_Account";Filter="Domain='$domain' and Name='$accountname'"} + $remoteParams
$win32account = Get-WmiObject @getparams
if ($win32account -eq $null) {
throw "Account was not found: $username"
}
$accessMask = Get-AccessMaskFromPermission($permissions)
$ace = (New-Object System.Management.ManagementClass("win32_Ace")).CreateInstance()
$ace.AccessMask = $accessMask
if ($allowInherit) {
$ace.AceFlags = $OBJECT_INHERIT_ACE_FLAG + $CONTAINER_INHERIT_ACE_FLAG
} else {
$ace.AceFlags = 0
}
$trustee = (New-Object System.Management.ManagementClass("win32_Trustee")).CreateInstance()
$trustee.SidString = $win32account.Sid
$ace.Trustee = $trustee
$ACCESS_ALLOWED_ACE_TYPE = 0x0
$ACCESS_DENIED_ACE_TYPE = 0x1
if ($deny) {
$ace.AceType = $ACCESS_DENIED_ACE_TYPE
} else {
$ace.AceType = $ACCESS_ALLOWED_ACE_TYPE
}
$acl.DACL += $ace.psobject.immediateBaseObject
$setparams = @{Name="SetSecurityDescriptor";ArgumentList=$acl.psobject.immediateBaseObject} + $invokeParams
$output = Invoke-WmiMethod @setparams
if ($output.ReturnValue -ne 0) {
throw "SetSecurityDescriptor failed: $($output.ReturnValue)"
}
Write-Host "Permissions configurées avec succès pour $username sur $namespace"
}
Write-Host "Configuration terminée pour tous les namespaces"
} |
Afin de récupérer les informations de temps, il est nécessaire au nouvel utilisateur d'avoir certains accès en lecture au service de temps de Windows W32Time.
Dans un PowerShell :
&{
Param (
[parameter(Mandatory=$true)][string] $UserName
)
$sid = (New-Object System.Security.Principal.NTAccount($UserName)).Translate([System.Security.Principal.SecurityIdentifier]).Value
$currentSddl = & sc.exe sdshow w32time
# Ajoute les droits suivants à l'utilisateur
# CC – SERVICE_QUERY_CONFIG
# LC – SERVICE_QUERY_STATUS
# LO – SERVICE_INTERROGATE
$newAce = "(A;;CCLCLO;;;${sid})"
$newSddl = $currentSddl + $newAce
sc.exe sdset w32time "$newSddl"
Restart-Service w32time
} |
Afin de récupérer les tentatives de connexions échouées, il est nécessaire au nouvel utilisateur d'avoir certains accès en lecture au journal d'événements de sécurité.
Dans un PowerShell :
&{
Param (
[parameter(Mandatory=$true)][string] $UserName
)
try {
$Path = "HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Security"
$acl = Get-Acl $Path
$rule = New-Object System.Security.AccessControl.RegistryAccessRule(
$UserName,
"ReadKey",
"Allow"
)
$acl.AddAccessRule($rule)
Set-Acl $Path $acl
Write-Host " Droits Registre appliqués." -ForegroundColor Green
} catch {
Write-Host " Erreur permissions EventLog Security: $_" -ForegroundColor Red
throw
}
} |
Les nouvelles permissions attribuées au nouvel utilisateur seront appliquées lorsque de nouveaux tokens de connections seront générés. Il est possible de :
Les tests suivants sont à effectuer sur le poste Windows à superviser. |
L'objectif de ce test est de vérifier si le pare-feu possède une règle qui autorise la connection WinRM.
Exécuter la commande (en administrateur) :
Get-NetFirewallRule -Name "WINRM-HTTP-In-TCP" |

Si ce n'est pas le cas, activer la règle ( toujours avec les droits administrateurs ):
Enable-NetFirewallRule -Name "WINRM-HTTP-In-TCP" |
L'objectif de ce test est de réaliser en local une connexion WinRM, avec les outils fournis par Windows.
Avec la commande "Test-WsMan" :
Test-WSMan localhost -Credential (Get-Credential) -Authentication Default |
Rentrer le nom d'utilisateur ainsi que le mot de passe de l'utilisateur de supervision :
|
Résultat attendu :
![]() |
Cela confirme que le service WinRM et l'utilisateur de supervision sont actifs et opérationnels sur la machine.
Une fois ces deux tests validés, la configuration du poste Windows est terminée et il est prêt à être supervisé. L'étape suivante est de choisir, d'accrocher et de paramétrer les modèles d'hôtes fournis dans le pack ( Voir la page Modèles d'hôtes du pack windows-by-WinRM__shinken ). |
Votre essai Premium est terminéVotre essai Premium est terminé