Microsoft Baseline Security Analyzer (MBSA) est un bon outil pour aider les informaticiens des petites et moyennes entreprises à déterminer et optimiser l’état de leur parc machine en termes de sécurité selon les recommandations de Microsoft.
Bien que convivial et performant, le produit ne permet pas de sortir un état consolidé de l’ensemble des machines d’un parc au format Excel. C’est ce que propose le petit script PowerShell suivant.
Le dossier complet de l’application est téléchargeable en cliquant ici ou si vous préférez en recopiant le code source complet fourni ci-après.
- Dossier du script
Le dossier du script doit contenir:
– Le script lui même
(ici MCO.ps1 mais pourrait s’appeler différemment)
– Un fichier paramètre contenant le nom netbios des machines à traiter
(ici MCO.txt, ce nom doit être identique au nom du script)
– Un sous-dossier appelé ‘Logs’ (obligatoire) destiné à recevoir le compte-rendu d’exécution
– Un sous-dossier appelé ‘Resultats’ (obligatoire) destiné à recevoir le fichier Excel résultant.
- Prérequis
– Microsoft Excel installé sur la machine sur laquelle tourne le script.
– Microsoft Baseline Security Analyzer 2.3, téléchargeable depuis ici.
– Lancer le script avec un compte administrateur de toutes les machines à traiter depuis une machine ayant accès à Internet.
- Fonctionnement du script
– Le script énumère le fichier paramètre et lance mbsacli.exe.
– mbsacli.exe génère un rapport pour chaque machine dans le dossier C:\Users\<username>\SecurityScans du poste où a été lancé le script.
Avertissement: La première fois que mbsacli.exe est lancé (ou sa version GUI mbsa.exe), il va, préalablement à toute chose, mettre à jour ses fichiers de configuration sur le web. Cette opération peut prendre plusieurs longues minutes.
– Le script reprend la main, renomme les fichiers *.mbsa en *.xml.
– Les fichiers xml de chaque machine sont consolidés dans un seul fichier au format Excel dans le sous-dossier Resultats et appelé MCOaaaammjjhhmm.xlsx.
- Source du script
####################################################################################################
#
# Script Name: MCO.ps1
#
# Author: EHX
# Version: 1.0
# Date: 15/12/2015
#
# Description: Lance mbsacli.exe sur plusieurs machines définies dans le fichier mco.txt
# Génère un rapport Excel consolidé de l'ensemble des machines
#
####################################################################################################
Param(
[Parameter(Mandatory=$false)]
[String]$param1
)
Process{
Cls
#Region "Functions"
####################################################################################################
# Get-Script-Directory
####################################################################################################
Function Get-Script-Directory
{
$scriptInvocation = (Get-Variable MyInvocation -Scope 1).Value
return Split-Path $scriptInvocation.MyCommand.Path
}
####################################################################################################
# Add To Log
####################################################################################################
Function Log([String]$LogtoAdd)
{
Add-Content -Path $LogFilePath -Value $LogtoAdd
If ($LogtoAdd.Contains('ERROR')) { Write-Host $LogtoAdd -ForegroundColor Red } Else { Write-Host $LogtoAdd }
}
####################################################################################################
# End Log
####################################################################################################
Function EndLog
{
# Stop Timer
$Watch.Stop()
$ts = $Watch.Elapsed
[String]$Time = [system.String]::Format("{0:00}h:{1:00}m:{2:00}s.{3:00}ms", $ts.Hours, $ts.Minutes, $ts.Seconds, $ts.Milliseconds / 10)
Log
Log ("****************************************************************************")
Log
Log ("Traitement terminé à: " + [datetime]::Now + " - Temps de Traitement: " + $Time)
Log
Log ("****************************************************************************")
Log
Log
Log
}
####################################################################################################
# Exit Script
####################################################################################################
Function ExitScript
{
EndLog
Exit
}
####################################################################################################
# Check Error With Exit
####################################################################################################
Function CheckErrorWithExit
{
If ($error -ne $null) {
Log (" $error")
ExitScript
}
}
####################################################################################################
# Check Error With No Exit
####################################################################################################
Function CheckErrorWithNoExit
{
If ($error -ne $null) {
Log (" ERROR: $error")
}
}
####################################################################################################
# mbsacli.exe + xml creation
####################################################################################################
Function CreateXml
{
Log
Log ("****************************************************************************")
Log ("Création des fichiers xml")
Log
# Emplacement de mbsacli.exe
$ExeFilePath = ${Env:ProgramFiles} + '\Microsoft Baseline Security Analyzer 2\mbsacli.exe'
if (!(Test-Path $ExeFilePath)) {
log ("Erreur - $ExeFilePath n'existe pas")
exitscript
}
# Paramètres de mbsacli.exe
$Listfile = "$PathScript\mco.txt"
$Parameters = "/listfile" + ' "' + $Listfile + '" ' + "/o %c%"
# L'historique des fichiers de sortie est supprimmé
remove-item "$Env:USERPROFILE\SecurityScans\*.mbsa"
# Appel de mbsacli.exe
log("Exécution de la commande: $ExeFilePath $Parameters")
$process = [System.Diagnostics.Process]::Start($ExeFilePath,$Parameters)
$process.WaitForExit()
if ($process.ExitCode -ne 0){
log("Exit code : " + $process.ExitCode)
exitscript
}
# L'historique éventuel de fichiers xml est supprimé dans le sous-dossier \resultat du dossier du script
remove-item "$PathScript\Resultats\*.xml"
# Déplace les fichiers résultants *.mbsa de chaque machine dans le sous-dossier \resultat
move-item "$Env:USERPROFILE\SecurityScans\*.mbsa" "$PathScript\Resultats\" -force
# Modifie l'extension des fichiers *.mbsa en *.xml
get-childitem -Path "$PathScript\Resultats" *.mbsa |rename-item -NewName {$_.name -replace ".mbsa",".xml"}
Log ("Fichiers $Env:USERPROFILE\SecurityScans\*.mbsa renommés en $PathScript\Resultats\*.xml")
}
####################################################################################################
# Creation of consolidated Excel file
####################################################################################################
Function BrowseXml
{
$Colonne = ""
$i = 7
# Lecture des fichiers xml
$ResultFiles=get-childitem -Path "$PathScript\Resultats" *.xml
forEach ($ResultFile in $ResultFiles){
[xml]$Xml = Get-Content -Path "$PathScript\Resultats\$ResultFile"
Log
log ("Fichier en cours de traitement: " + $ResultFile )
$xml.SecScan | ForEach {
$_.Check | ForEach {
$wSheet.Cells.item($intRow,1) = $xml.SecScan.Machine
$wSheet.Cells.item($intRow,2) = $_.ID
$wSheet.Cells.item($intRow,3) = $_.Name
$wSheet.Cells.item($intRow,4) = $_.Advice
$_.Detail | ForEach {
$i = 5
$_.Row | ForEach {
$Colonne = ""
$_.Col | ForEach {
$Colonne = $Colonne + " " + $_
}
$wSheet.Cells.item($intRow,$i) = $Colonne
$i++
}
$intRow++
}
}
}
}
}
#EndRegion
####################################################################################################
# Main Process
####################################################################################################
#Region "Main Process"
#Variables Definition
$PathScript = Get-Script-Directory
$LogFileName = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name)
$LogFilePath = $PathScript + '\Logs\' + $LogFileName + '.log'
$Computername = gc env:computername
$Watch = New-Object system.Diagnostics.Stopwatch #Timer
$PathYear = Get-Date -format yyyy
$PathMonth = Get-Date -format MM
$PathDay = Get-Date -format dd
$PathHour = Get-Date -format HH
$PathMin = Get-Date -format mm
$PathSec = Get-Date -format mm
$XlsFile = $PathScript + "\Resultats\MCO"+$PathYear+$PathMonth+$PathDay+$PathHour+$PathMin+".xlsx"
$intRow = 0
#Create Log File
If ((Test-Path $LogFilePath) -eq $False) {
$LogFile = [System.IO.File]::CreateText($LogFilePath)
$LogFile.Close()
}
#Write Eventlog if log file cannot be created
If ((Test-Path $LogFilePath) -eq $False) {
Write-Eventlog -LogName "Windows PowerShell" -Source PowerShell -EntryType Error -Eventid 100 -Message "Log file $LogFilePath cannot be created for script $LogFileName.ps1"
Exit
}
#Start Logging
Log ("****************************************************************************")
Log ("Processus démarré à : " + [datetime]::Now + " sur le poste: """ + $Computername + """")
Log ("Fichier Log (-log) : $LogFilePath")
log ("Fichier de paramètres: $PathScript\mco.txt")
log ("Fichier de résultats : $XlsFile")
Log ("****************************************************************************")
#Start Timer
$Watch.Start()
# Configure $ErrorActionPreference
$ErrorActionPreference = "SilentlyContinue"
# Appel mbsacli.exe + renommage des fichiers mbsa en xml
CreateXml
# Creation du fichier Excel consolidé
Log
Log ("Création du fichier Excel consolidé")
#Creation de l'objet Excel
$Excel = New-Object -Com Excel.Application
$Wbook = $Excel.Workbooks.Add()
$Excel.visible = $False
#Sheet1
$wSheet = $Excel.Worksheets.Item(1)
$wSheet.name = "MCO"
$wSheet.Cells.Item(1,1) = "MCO - Etat des Machines au " + $([datetime]::Now)
$wSheet.Cells.item(2,1) = "Machine"
$wSheet.Cells.item(2,2) = "ID"
$wSheet.Cells.item(2,3) = "Libellé"
$wSheet.Cells.item(2,4) = "Résultat"
$wSheet.Cells.item(2,5) = "Détail 1"
$wSheet.Cells.item(2,6) = "Détail 2"
$wSheet.Cells.item(2,7) = "Détail 3"
$wSheet.Cells.item(2,8) = "Détail 4"
$wSheet.Cells.item(2,9) = "Détail 5"
$wSheet.Cells.item(2,10) = "Détail 6"
$WorkBook = $wSheet.UsedRange
$WorkBook.Interior.ColorIndex = 37
$WorkBook.Font.ColorIndex = 1
$WorkBook.Font.Bold = $True
$intRow=3
# Browse XML files and feed Excel file
BrowseXml
# Sauve le fichier Excel
$Excel.displayalerts=$false
$Wbook.SaveAs($XlsFile)
$Wbook.Close()
$Excel.quit()
# Fin de script
Exitscript
#EndRegion
}