# Script d'Audit Firewall - Network Reputation Service # Auteur: Hubert Cornet # Date: 03/09/2025 # Version: 1.0 Clear-Host # Configuration globale $ErrorActionPreference = "Continue" $WarningPreference = "SilentlyContinue" ### Functions ### ## Function Write-ColorOutput Function Write-ColorOutput { Param( [string]$Text, [string]$Color = "White" ) Try { Write-Host $Text -ForegroundColor $Color } Catch { Write-Host $Text } } ## Function Prerequisites Function Prerequisites { Write-ColorOutput "`n=== Vérification des prérequis ===" "Cyan" # Vérification du fichier JSON $JsonFile = Join-Path $PSScriptRoot "file-nrs.json" If(-not (Test-Path $JsonFile)) { Write-ColorOutput "ERREUR: Le fichier 'file-nrs.json' n'existe pas!" "Red" Write-ColorOutput "Veuillez télécharger ou créer le fichier depuis:" "Yellow" Write-ColorOutput "https://github.com/your-repo/file-nrs.json" "Blue" Write-ColorOutput "Le fichier doit être placé dans le même dossier que ce script." "Yellow" Return $false } Write-ColorOutput "✓ Fichier 'file-nrs.json' trouvé" "Green" # Vérification/Installation des modules requis $RequiredModules = @('PSWriteHTML', 'PSWriteColor') Foreach ($Module in $RequiredModules) { If(-not (Get-Module -ListAvailable -Name $Module)) { Write-ColorOutput "Installation du module $Module..." "Yellow" Try { Install-Module -Name $Module -Force -Scope CurrentUser -AllowClobber Write-ColorOutput "✓ Module $Module installé" "Green" } Catch { Write-ColorOutput "ERREUR: Impossible d'installer le module $Module : $($_.Exception.Message)" "Red" Return $false } } Else { Write-ColorOutput "✓ Module $Module disponible" "Green" } Import-Module $Module -Force } return $true } ## Function Check-Categories Function Check-Categories { Param( [array]$Categories, [string]$ProxyUrl = "", [System.Management.Automation.PSCredential]$ProxyCredential = $null, [int]$TimeoutSeconds = 10 ) $AllResults = @() $CategoryCount = 0 $BlockKeywors = @("site bloqué", "access denied", "filtrage web", "Access Denied", "Site Blocked") # Définir les mots-clés des page des blocage Foreach ($Category in $Categories.Categorie) { $CategoryCount++ Show-ProgressBar -Current $CategoryCount -Total $Categories.Categorie.Count -Activity "Test des catégories" -Status "Catégorie: $($category.Categorie.nom)" Write-ColorOutput "`n=== Test de la catégorie: $($Category.nom) ===" "Cyan" #Write-ColorOutput "Description: $($category.description)" "Gray" $CategoryResults = @() $UrlCount = 0 Foreach ($UrlObj in $Category.urls) { $UrlCount++ Show-ProgressBar -Current $UrlCount -Total $Category.urls.Count -Activity "Test des URLs de '$($Category.nom)'" -Status $UrlObj.url Write-ColorOutput "Test de: $($UrlObj.url)" "Yellow" #$Result = Get-UrlStatus -Url $UrlObj.url -ProxyUrl $ProxyUrl -ProxyCredential $ProxyCredential -TimeoutSeconds $TimeoutSeconds -BlockPageKeywords $BlockPageKeywords $Result = Get-UrlStatus $UrlObj.url $UrlObj.expected_action $BlockPageKeywords $TestResult = [PSCustomObject]@{ Category = $category.nom CategoryId = $category.id Url = $urlObj.url Reputation = $urlObj.reputation ExpectedAction = $urlObj.expected_action Status = $result.ActualResult StatusCode = $result.StatusCode ResponseTime = $result.ResponseTime Error = $result.Details Score = $result.Score IsCorrect = (($TestResult.Status -eq "Bloqué" -and $UrlObj.expected_action -eq "block") -or ($TestResult.Status -eq "Autorisé" -and $UrlObj.expected_action -eq "allow")) } $StatusColor = If($testResult.IsCorrect) { "Green" } Else { "Red" } Write-ColorOutput " → Résultat: $($TestResult.Status) | Attendu: $($TestResult.ExpectedAction) | Correct: $($TestResult.IsCorrect)" $statusColor $categoryResults += $testResult $allResults += $testResult } $CategoryScore = Calculate-CategoryScore -Results $categoryResults $CategoryGrade = Convert-ScoreToGrade -Score $categoryScore Write-ColorOutput "Score de la catégorie '$($Category.nom)': $categoryScore% (Note: $CategoryGrade)" "Magenta" } Write-Progress -Activity "Test des catégories" -Completed Write-Progress -Activity "Test des URLs" -Completed return $allResults } ## Function Show-ProgressBar Function Show-ProgressBar { Param( [int]$Current, [int]$Total, [string]$Activity, [string]$Status = "" ) $Percent = [math]::Round(($Current / $Total) * 100, 1) Write-Progress -Activity $Activity -Status "$Status ($Current/$Total)" -PercentComplete $Percent } ## FunctionCalculate-CategoryScore Function Calculate-CategoryScore { Param( [array]$Results ) $TotalUrls = $Results.Count $CorrectResults = 0 Foreach ($Result in $Results) { $IsBlocked = $Result.Status -eq "Bloqué" $ShouldBeBlocked = $result.ExpectedAction -eq "block" If(($IsBlocked -and $ShouldBeBlocked) -or (-not $IsBlocked -and -not $ShouldBeBlocked)) { $CorrectResults++ } } If($TotalUrls -eq 0) { Return 0 } Return [math]::Round(($CorrectResults / $TotalUrls) * 100, 2) } ## Function Convert-ScoreToGrade Function Convert-ScoreToGrade { Param([double]$Score) switch ($Score) { {$_ -ge 95} { return 'A+' } {$_ -ge 90} { return 'A' } {$_ -ge 85} { return 'B+' } {$_ -ge 80} { return 'B' } {$_ -ge 75} { return 'C+' } {$_ -ge 70} { return 'C' } {$_ -ge 65} { return 'D+' } {$_ -ge 60} { return 'D' } {$_ -ge 55} { return 'E+' } {$_ -ge 50} { return 'E' } {$_ -ge 45} { return 'F+' } default { return 'F' } } } ## Function Get-UrlStatus Function Get-UrlStatus { Param( [string]$Url, [string]$ExpectedAction, # 'allow' ou 'block' [string[]]$BlockPageKeywords, # Exemple: @("Access Denied", "Site Blocked") [string]$ProxyAddress = $null, [string]$ProxyUseAuthentication = $null, [int]$Timeout = 10 ) $Result = [PSCustomObject]@{ Url = $Url Expected = $ExpectedAction ActualResult = "Indéterminé" # Ce qui s'est réellement passé (Bloqué/Autorisé) TestStatus = "Échec" # Le statut du test (Conforme/Non Conforme) Score = $Null StatusCode = "" Details = "" ResponseTime = "" } # Préparation des paramètres pour Invoke-WebRequest (Splatting) $IWRParams = @{ Uri = $Url UseBasicParsing = $True TimeoutSec = $Timeout ErrorAction = 'Stop' } $Response = $Null # Ajout des paramètres du proxy s'ils sont fournis If (-not [string]::IsNullOrEmpty($ProxyAddress)) { $IWRParams.Add('Proxy', $ProxyAddress) If ($ProxyUseAuthentication) { # Demande les identifiants de manière sécurisée et les ajoute à la commande $Creds = Get-Credential -Message "Veuillez saisir les identifiants pour le proxy $ProxyAddress" $IWRParams.Add('ProxyCredential', $Creds) } } # -- Exécution du test -- Try { # Exécution de la requête en utilisant les paramètres définis dans la hashtable $Response = Invoke-WebRequest @IWRParams # On vérifie si la réponse contient des mots-clés de la page de blocage $KeywordFound = $False Foreach ($Keyword in $BlockPageKeywords) { If ($Response.Content -match $Keyword) { $KeywordFound = $True break } } If ($KeywordFound) { $Result.ActualResult = "Bloqué" # $Result.Score = 1 $Result.Details = "Page de blocage détectée." $Result.StatusCode = $Response.StatusCode } Else { $Result.ActualResult = "Autorisé" # $Result.Score = 0 $Result.Details = "Le site a été atteint sans blocage." $Result.StatusCode = $Response.StatusCode } } Catch [System.Net.WebException] { If ($_.Exception.Status -eq 'Timeout') { $Result.ActualResult = "Bloqué (Timeout)" # $Result.Score = 1 $Result.Details = "La requête a expiré, indiquant un blocage probable par le pare-feu ou le proxy." $Result.StatusCode = $Response.StatusCode $Result.ResponseTime = "$Timeout" } # Elseif ($_.Exception.Response) { # $Result.Status = "Bloqué (Erreur HTTP)" # $Result.Score = 1 # $Result.Details = "Réponse HTTP non-200 reçue : $($_.Exception.Response.StatusCode)" # } Else { # On considère les autres erreurs réseau comme un blocage aussi $Result.ActualResult = "Erreur de Connexion" $Result.Details = "Impossible de joindre le serveur : $($_.Exception.Status)" $Result.StatusCode = $Response.StatusCode } } Catch { $Result.ActualResult = "Erreur Script" $Result.Details = "Erreur inattendue: $($_.Exception.Message)" #$Result.StatusCode = 0 <= A trouver #$Result.ResponseTime = 0 <= A trouver # Un test en erreur ne doit pas donner de point return $result } # Le test est réussi si l'action attendue correspond au résultat réel. If (($Result.Expected -eq 'block' -and $Result.ActualResult -eq 'Bloqué') -or ($Result.Expected -eq 'allow' -and $Result.ActualResult -eq 'Autorisé')) { $Result.TestStatus = "Conforme" $Result.Score = 1 # Le test est un succès ! $Result.Details += " (Résultat conforme à l'attendu)" } Else { $Result.TestStatus = "Non Conforme" $Result.Score = 0 # Le test est un échec ! $Result.Details += " (Résultat NON CONFORME; Attendu: $($Result.Expected); Obtenu: $($Result.ActualResult))" } Return $Result } ## Function Generate-HtmlReport Function Generate-HtmlReport { Param( [array]$Results, [string]$OutputPath ) Write-ColorOutput "Génération du rapport HTML..." "Yellow" # Calcul des scores $Categories = $Results | Group-Object Category $CategoryScores = @() Foreach ($Cat in $Categories) { $Score = Calculate-CategoryScore -Results $Cat.Group $Grade = Convert-ScoreToGrade -Score $Score $CategoryScores += [PSCustomObject]@{ Category = $cat.Name Score = $score Grade = $grade Color = $GradeColors[$grade] TotalUrls = $cat.Group.Count CorrectResults = ($cat.Group | Where-Object IsCorrect).Count } } # Score global $globalScore = Calculate-CategoryScore -Results $Results $globalGrade = Convert-ScoreToGrade -Score $globalScore # Création du rapport HTML New-HTML -TitleText "Audit Firewall - Network Reputation Service" -Online -FilePath $OutputPath { New-HTMLHeader { New-HTMLText -Text "Audit Firewall - Network Reputation Service" -FontSize 28 -FontWeight bold -Color Blue -Alignment center New-HTMLText -Text "Rapport généré le $(Get-Date -Format 'dd/MM/yyyy à HH:mm')" -FontSize 14 -Color Gray -Alignment center } New-HTMLSection -HeaderText "Résumé Exécutif" -BackgroundColor LightBlue { New-HTMLPanel { New-HTMLText -Text "Score Global: $globalScore% - Note: $globalGrade" -FontSize 24 -FontWeight bold -Color $GradeColors[$globalGrade] New-HTMLText -Text "Total des URLs testées: $($Results.Count)" -FontSize 16 New-HTMLText -Text "URLs correctement filtrées: $(($Results | Where-Object IsCorrect).Count)" -FontSize 16 New-HTMLText -Text "Taux de réussite: $([math]::Round((($Results | Where-Object IsCorrect).Count / $Results.Count) * 100, 2))%" -FontSize 16 } } New-HTMLSection -HeaderText "Scores par Catégorie" -BackgroundColor LightGray { New-HTMLTable -DataTable $categoryScores -HideFooter { New-HTMLTableHeader -Names "Category", "Score", "Grade", "TotalUrls", "CorrectResults" -Title "Scores par Catégorie" New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'A+' -BackgroundColor '#28a745' -Color White New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'A' -BackgroundColor '#52b83a' -Color White New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'B+' -BackgroundColor '#7ac92e' -Color White New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'B' -BackgroundColor '#a3da23' -Color Black New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'C+' -BackgroundColor '#cceb17' -Color Black New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'C' -BackgroundColor '#f5f90c' -Color Black New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'D+' -BackgroundColor '#f7d808' -Color Black New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'D' -BackgroundColor '#f9b604' -Color Black New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'E+' -BackgroundColor '#fb9500' -Color White New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'E' -BackgroundColor '#fd7300' -Color White New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'F+' -BackgroundColor '#ff5100' -Color White New-HTMLTableCondition -Name 'Grade' -ComparisonType string -Operator eq -Value 'F' -BackgroundColor '#dc3545' -Color White } } New-HTMLSection -HeaderText "Détail des Tests par Catégorie" -BackgroundColor White { foreach ($category in $categories) { $catScore = ($categoryScores | Where-Object Category -eq $category.Name).Score $catGrade = ($categoryScores | Where-Object Category -eq $category.Name).Grade New-HTMLSection -HeaderText "$($category.Name) - Score: $catScore% ($catGrade)" -BackgroundColor LightYellow -Collapsible { $detailedResults = $category.Group | Select-Object Url, Reputation, ExpectedAction, Status, IsCorrect, Error New-HTMLTable -DataTable $detailedResults -HideFooter { New-HTMLTableCondition -Name 'IsCorrect' -ComparisonType string -Operator eq -Value 'True' -BackgroundColor '#d4edda' -Color '#155724' New-HTMLTableCondition -Name 'IsCorrect' -ComparisonType string -Operator eq -Value 'False' -BackgroundColor '#f8d7da' -Color '#721c24' } } } } New-HTMLSection -HeaderText "Barème de Notation" -BackgroundColor LightGreen -Collapsible { $gradingScale = @( [PSCustomObject]@{Grade='A+'; Score='95-100%'; Interpretation='Excellent / Parfait'} [PSCustomObject]@{Grade='A'; Score='90-95%'; Interpretation='Très bon niveau de filtrage'} [PSCustomObject]@{Grade='B+'; Score='85-90%'; Interpretation='Très bon'} [PSCustomObject]@{Grade='B'; Score='80-85%'; Interpretation='Bon, mais quelques ajustements nécessaires'} [PSCustomObject]@{Grade='C+'; Score='75-80%'; Interpretation='Assez bon'} [PSCustomObject]@{Grade='C'; Score='70-75%'; Interpretation='Moyen, lacunes importantes'} [PSCustomObject]@{Grade='D+'; Score='65-70%'; Interpretation='Passable'} [PSCustomObject]@{Grade='D'; Score='60-65%'; Interpretation='Faible, filtrage inefficace'} [PSCustomObject]@{Grade='E+'; Score='55-60%'; Interpretation='Très faible'} [PSCustomObject]@{Grade='E'; Score='50-55%'; Interpretation='Insuffisant'} [PSCustomObject]@{Grade='F+'; Score='45-50%'; Interpretation='Critique'} [PSCustomObject]@{Grade='F'; Score='0-45%'; Interpretation='Très faible, action immédiate requise'} ) New-HTMLTable -DataTable $gradingScale -HideFooter } } Write-ColorOutput "✓ Rapport généré: $OutputPath" "Green" } ## Function Main Function Main { Write-ColorOutput @" ╔══════════════════════════════════════════════════════════════════════════════╗ ║ AUDIT FIREWALL - NETWORK REPUTATION SERVICE ║ ║ Version 1.0 ║ ╚══════════════════════════════════════════════════════════════════════════════╝ "@ "Cyan" # Vérification des prérequis If(-not (Prerequisites)) { Write-ColorOutput "ERREUR: Les prérequis ne sont pas satisfaits. Arrêt du script." "Red" Return } # Chargement du fichier JSON Try { $JsonFile = Join-Path $PSScriptRoot "file-nrs.json" $Categories = Get-Content $JsonFile -Raw -Encoding UTF8 | ConvertFrom-Json Write-ColorOutput "✓ Fichier JSON chargé avec $($Categories.categorie.Count) catégories" "Green" } Catch { Write-ColorOutput "ERREUR: Impossible de charger le fichier JSON: $($_.Exception.Message)" "Red" Return } # Création du dossier de sortie $ReportDate = Get-Date -Format "dddd dd MMMM yyyy-HH mm" $ReportsDir = Join-Path $PSScriptRoot "Rapports" $OutputDir = Join-Path $ReportsDir $ReportDate If (-not (Test-Path $ReportsDir)) { New-Item -ItemType Directory -Path $ReportsDir -Force | Out-Null } If (-not (Test-Path $OutputDir)) { New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null } Write-ColorOutput "`n Dossier de sortie: $outputDir" "Yellow" # Début des tests Write-ColorOutput "`n=== DÉBUT DES TESTS ===" "Green" $StartTime = Get-Date $AllResults = Check-Categories -Categories $Categories -ProxyUrl $ProxyUrl -ProxyCredential $ProxyCredential -TimeoutSeconds $TimeoutSeconds -BlockPageKeywords $BlockKeywors $EndTime = Get-Date $Duration = $EndTime - $StartTime Write-ColorOutput "`n=== RÉSULTATS FINAUX ===" "Green" Write-ColorOutput "`n Temps total d'exécution: $($duration.ToString('hh\:mm\:ss'))" "Yellow" Write-ColorOutput "`n Total des URLs testées: $($allResults.Count)" "Yellow" # Calcul du score global $GlobalScore = Calculate-CategoryScore -Results $AllResults $GlobalGrade = Convert-ScoreToGrade -Score $GlobalScore Write-ColorOutput "`n `n Score global: $GlobalScore% - Note: $GlobalGrade" "Magenta" # Génération du rapport HTML $ReportPath = Join-Path $OutputDir "Audit_Firewall_Report.html" Generate-HtmlReport -Results $AllResults -OutputPath $ReportPath # Sauvegarde des résultats en JSON $JsonResultsPath = Join-Path $outputDir "Results.json" $AllResults | ConvertTo-Json -Depth 10 | Out-File -FilePath $JsonResultsPath -Encoding UTF8 Write-ColorOutput "✓ Résultats sauvegardés: $JsonResultsPath" "Green" Write-ColorOutput "`n=== AUDIT TERMINÉ ===" "Green" Write-ColorOutput "Rapport disponible à: $ReportPath" "Cyan" # Ouverture automatique du rapport If (Get-Command "Start-Process" -ErrorAction SilentlyContinue) { $OpenReport = Read-Host "Voulez-vous ouvrir le rapport maintenant? (O/N)" If ($OpenReport -eq "O" -or $OpenReport -eq "o" -or $OpenReport -eq "Y" -or $OpenReport -eq "y") { Start-Process $ReportPath } } } ### Main Clear-Host # Exécution du script principal Try { Main } Catch { Write-ColorOutput "ERREUR FATALE: $($_.Exception.Message)" "Red" Write-ColorOutput "Stack Trace: $($_.ScriptStackTrace)" "Red" }