Lorsque mon directeur est venu me voir avec la demande de pouvoir avoir un monitoring des entrées du DHCP, d'avertir lorsque se connecte une machine hors domaine, ainsi que de prévenir / communiquer lorsqu'une réservation DHCP est modifiée, je m'étais déja imaginé l'aisance avec laquelle les commandes Powershell natives de Windows Server 2012 me permettraient de récupérer l'intégralité des informations. Lorsqu'il m'a ajouté qu'il n'y avait aucun serveur 2012, mais du 2003 ou 2008, j'ai commencé par grimacer avant de me dire : "Il DOIT y avoir un moyen!".
Petit retour sur mes recherches, et partage de mon script en fin d'article.
Les commandes natives de 2012 sont une vraie bénédiction. Les serveurs DHCP de mon client principal sont sous cet OS, et je n'ai qu'une commande à lancer pour obtenir un retour sous la forme d'un objet, aisément manipulable. Même si cette commande est utilisable depuis un serveur 2012 vers un serveur 2008/R2, elle n'existe que depuis 2012. Ce qui en exclut l'utilisation dans un domaine sans 2012... Et combien d'entreprises ne souhaitent pas / n'ont pas l'utilité de passer sur cet O.S.? Difficile à dire, mais cela représente tout de même une partie non négligeable. Exit donc cette commande, il va falloir réinventer la roue pour avoir les informations tant désirées. Et lorsque l'on avait pas Powershell, de quoi se servait-on?
Et bien de ce bon vieux CMD, pardi! Les quelques mots de recherche "DHCP" et "invité de commandes" me renvoient un lien vers le MSDN, expliquant avec moult détails comment l'utilisation de NETSH qui, avec quelques arguments bien choisis, nous permettront d'avoir un retour sur les baux DHCP, mais également les réservations d'IP... sous un retour format texte.
S'en est suivi un long moment à créer la bonne REGEX qui permettra de découper de manière automatique le texte renvoyé afin d'en extraire à chaque fois les informations pertinentes, et de faire de même pour les réservations DHCP. Ceci fait, j'ai du réfléchir à la manière dont les données issues de la commande NetSH allaient être envoyées aux serveurs... En imaginant que chaque serveur gère 5 pools, et que nous ayons 3 serveurs, nous aurions 5*3 commandes à envoyer ... et si l'information prend un peu de temps à arriver, il est préférable de paralléliser le processus. J'ai donc pris la décision de me servir des jobs Powershell au lieu de faire se dérouler le script de manière linéaire. Le gain de temps est considérable!
Une fois ce point résolu, il me fallait savoir comment traiter les informations et les comparer... Le cœur du script, en quelque sorte. J'ai du chercher les différentes combinaisons de cas possibles, quelles alertes remonter, que chercher et faire en sorte que l'information soit lisible. Et c'est à ce moment que j'ai ajouté une possibilité d'ajouter des exceptions, soit des adresses mac soit des noms dns, afin de ne pas déclencher d'alerte pour des équipements hors domaine pour des raisons légitimes (Linux, Imprimantes, etc.)
Une fois le script fonctionnel, il m'a été demandé d'ajouter un contrôle sur la création / modification / suppression des réservations d'adresses IP, informations qui sont déjà remontées par la commande NETSH, ainsi que de développer une partie d'autoconfiguration qui permet de copier / coller simplement le script chez un autre client sans avoir à faire des modifications à l'intérieur même du script. J'ai également ajouté l'export des données au format CSV pour permettre une relecture aisée sans avoir à lire chaque mail!
Et une petite capture d'écran d'un résultat reçu par mail pour quelques "intrus" d'un domaine !
N'hésitez pas à me faire part de vos remarques en commentaire de cet article!
Vous pouvez télécharger ce script sur mon espace git personnel.
$scriptPath = $null
$answer = "z"
if ((Get-Host).Version.Major -le 2)
{
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
}
else
{
$scriptPath = $PSScriptRoot
}
$configfile = Join-Path $scriptPath "config.ini"
try
{
$configuration = Get-Content $configfile -ErrorAction Stop
}
catch
{
#region CONFIGFILECREATION
While($answer.tolower()[0] -ne "y" -and $answer.tolower()[0] -ne "n")
{
$answer = Read-host "Impossible d'accéder au fichier $configfile `nVoulez vous le créer? (Y/N)"
}
if ($answer.ToLower()[0] -eq "n")
{
throw("Fin du script")
}
else
{
#region DHCPPOOLS
$answer = "z"
while($answer.tolower()[0] -ne "y")
{
$ippoolarray = @()
$answer = "z"
Write-Host "Saisissez les plages DHCP, une par ligne. Entrez une ligne vide pour terminer."
do
{
$ippool = "Add_pools"
while($ippool -as [System.Net.IPAddress] -isnot [System.Net.IPAddress] -and $ippool -ne "")
{
$ippool = Read-Host "=>"
}
if ($ippool -ne "")
{
Write-host "$(([System.Net.IPAddress]$ippool).Ipaddresstostring) ajouté!"
$ippoolarray += $ippool
}
}while ($ippool -ne "")
$ippoolarray = $ippoolarray | Sort-Object -Unique
Write-Host "Vous avez choisi les pools suivants :`n"
$ippoolarray
while ($answer.tolower()[0] -ne "y" -and $answer.tolower()[0] -ne "n")
{
$answer = Read-Host "Est-ce correct? (Y/N)"
}
}
#endregion
#region DHCPSERVERS
$answer = "z"
while($answer.tolower()[0] -ne "y")
{
$dhcpserversarray = @()
$answer = "z"
Write-Host "Saisissez les noms ou ips des serveurs DHCP, un par ligne. Entrez une ligne vide pour terminer."
do
{
$dhcpserver = "Add_server"
while($dhcpserver -ne "")
{
$dhcpserver = Read-Host "=>"
if ($dhcpserver -ne "")
{
Write-host "$dhcpserver ajouté!"
$dhcpserversarray += $dhcpserver
}
}
}while ($dhcpserver -ne "")
$dhcpserversarray = $dhcpserversarray | Sort-Object -Unique
Write-Host "Vous avez choisi les serveurs suivants :`n"
$dhcpserversarray
while ($answer.tolower()[0] -ne "y" -and $answer.tolower()[0] -ne "n")
{
$answer = Read-Host "Est-ce correct? (Y/N)"
}
$answertotest = "z"
while ($answertotest.tolower()[0] -ne "y" -and $answertotest.tolower()[0] -ne "n" -and $answer -ne "n")
{
$answertotest = Read-Host "voulez vous tester la connexion aux serveurs? (Y/N)"
}
if ($answertotest.ToLower()[0] -eq "y")
{
$iserror = $false
foreach ($server in $dhcpserversarray)
{
$message = "Succès!"
$color = "Green"
if (!(Test-Connection $server -Count 1 -Quiet -ErrorAction Stop))
{
$iserror = $true
$message = "Echec! :c"
$color = "Red"
}
Write-host $server " => " $message -ForegroundColor $color
}
if ($iserror -eq $false)
{
Write-host "Tous les tests sont passés :)"
}
else
{
Write-Host "Une ou plusieurs erreurs sont arrivées."
do
{
$answer = Read-host "Voulez vous continuer malgré tout? (Y/N)"
}while ($answer.tolower()[0] -ne "y" -and $answer.tolower()[0] -ne "n")
if ($answer.tolower()[0] -eq "n")
{
throw("Vous avez arrêté le script")
}
}
}
}
#endregion
#region MAIL
$answertomail = "z"
while($answertomail.ToLower()[0] -ne "y")
{
do
{
Write-Host "Renseignez le nom du SMTP de messagerie"
$mailserver = Read-Host "=>"
Write-Host "Renseignez l'adresse de l'EXPEDITEUR"
$from = Read-Host "=>"
Write-Host "Renseignez l'adresse du DESTINATAIRE"
$to = Read-Host "=>"
$mailconfiguration = [pscustomobject]@{
"Mailserver"=$mailserver
"From" = $from
"To" = $to
}
$mailconfiguration | ft
$answertomail = Read-Host "Est-ce correct? (Y/N)"
}while($answertomail.ToLower()[0] -ne "y" -and $answertomail.ToLower()[0] -ne "n")
$answertosendmail = "z"
$mailreceived = "z"
if ($answertomail.ToLower()[0] -eq "y")
{
while($answertosendmail -ne "n")
{
do
{
$answertosendmail = Read-Host "Voulez vous envoyer un mail de test? (Y/N)"
} while($answertosendmail.ToLower()[0] -ne "y" -and $answertosendmail.ToLower()[0] -ne "n")
if ($answertosendmail.ToLower()[0] -eq "y")
{
$sendmailerror = $false
try
{
Send-MailMessage -From $from -To $to -Subject "Test mail du script Powershell" -SmtpServer $mailserver
}
catch
{
$sendmailerror = $true
Write-host "Une erreur s'est produite durant l'envoi du mail!"
}
if ($sendmailerror -eq $false)
{
do
{
$mailreceived = read-host "Le mail a été envoyé. L'avez vous recu? (Y/N)."
}while ($mailreceived.ToLower()[0] -ne "y" -and $mailreceived.ToLower()[0] -ne "n")
if ($mailreceived.ToLower()[0] -eq "n")
{
do
{
$answertomail = Read-Host "Voulez vous continuer et reconfigurer? (Y/N)"
}while ($answertomail.ToLower()[0] -ne "y" -and $answertomail.ToLower()[0] -ne "n")
switch ($answertomail.tolower()[0])
{
"y" { $answertomail = "n";$answertosendmail = "n" }
"n" { throw("Impossible d'envoyer le mail. Arrêt du script") }
}
}
else
{
$answertosendmail = "n"
}
}
}
}
}
}
#endregion
#region CHEMIN
$answer = "z"
$path = $null
do
{
do
{
$path = Read-Host "Entrez un chemin (local ou UNC) pour l'enregistrement des données du script`n=>"
$answerpathtest = Read-Host "Voulez vous tester le chemin :`n$path`n(Y/N) =>"
} until ($answerpathtest.ToLower()[0] -eq "y" -or $answerpathtest.ToLower()[0] -eq "n")
if ($answerpathtest -eq "y")
{
$answerpathretry = "z"
if (Test-Path $path)
{
Write-host -ForegroundColor Green "Le chemin est valide.`nTest d'écriture."
$testfilename = [string](get-date).Ticks+".test"
$answer = "y"
try
{
New-Item -ItemType File (Join-Path $path $testfilename) -Force
}
catch
{
Write-Host "Impossible d'écrire dans $path `nVeuillez selectionner un autre dossier."
$answer = "z"
}
Remove-Item (Join-Path $path $testfilename) -Force -ErrorAction SilentlyContinue
}
else
{
do
{
Write-Host "La destination n'existe pas. Voulez-vous la créer? (Y/N)"
$answerpathretry = Read-Host "=>"
} until ($answerpathretry.ToLower()[0] -eq "y" -or $answerpathretry.ToLower()[0] -eq "n")
if ($answerpathretry.ToLower()[0] -eq "n")
{
throw("Arrêt du script")
}
$answer = "z"
}
}
} until ($answer.ToLower()[0] -eq "y" -or $answer.ToLower()[0] -eq "n")
$answer = "z"
do
{
$answer = Read-Host "Voulez vous surveiller les réservations DHCP également? (Y/N)"
} until($answer.ToLower()[0] -eq "y" -or $answer.ToLower()[0] -eq "n")
#endregion
$dhcprescheck = $true
if ($answer.ToLower()[0] -eq "n")
{
$dhcprescheck = $false
}
}
try
{
$configurationarray = New-Object PSCUSTOMOBJECT
$configurationarray | Add-Member -Name pools -MemberType NoteProperty -Value $ippoolarray
$configurationarray | Add-Member -name servername -MemberType NoteProperty -Value $dhcpserversarray
$configurationarray | Add-Member -Name mailconfiguration -MemberType NoteProperty -Value $mailconfiguration
$configurationarray | Add-Member -Name path -MemberType NoteProperty -Value $path
$configurationarray | Add-Member -Name rescheck -MemberType NoteProperty -Value $dhcprescheck
}
catch
{
Write-Host -ForegroundColor Red "Une erreur s'est produite durant l'assemblage des infos de configuration. Voici l'état actuel de l'objet représentant la configuration :`n$configurationarray"
}
try
{
$configurationarray | Export-Clixml $configfile -ErrorAction Stop
}
catch
{
Write-Host -ForegroundColor Red "Impossible d'enregistrer le fichier de configuration. Le script va s'arrêter"
}
#endregion
} #end catch
$configurationarray = Import-Clixml $configfile -ErrorAction Stop
#region fichiers
#Précisez le chemin du fichier ou seront sauvegardées les données des PC détectés
$path = $configurationarray.path
$filename = "outsidedomain.xml" #Nom a donner au fichier.
$staticfile = "staticaddress.xml" #Nom a donner au fichier.
$exceptionfile = "exceptions.txt" #Nom du fichier d'exceptions
$exceptionpath = Join-Path $path $exceptionfile
$fullpath = Join-Path $path $filename
$staticpath = Join-Path $path $staticfile
$dateforcsv = Get-Date -Format "yyyy_MM"
#endregion
#region DHCP
$plages = $configurationarray.pools #Plage(s) à surveiller
$servername = $configurationarray.servername #nom de serveur(s) DHCP
#endregion
#region MAIL
$from = $configurationarray.mailconfiguration.From #Adresse mail de l'expéditeur
$to = $configurationarray.mailconfiguration.To #Adresse mail du destinataire
$smtpserver = $configurationarray.mailconfiguration.Mailserver #Serveur SMTP
$encoding = [System.Text.UTF8Encoding]::UTF8 #Encodage en UTF8 pour éviter les problèmes d'accents, entre autre
#endregion
#region jobs
$maximaljobperserver = 4
#endregion
#region variables
try
{
Import-module ActiveDirectory
}
catch
{
Write-host "Impossible de charger le module Active Directory pour Powershell. Ce module est-il bien installé et activé?"
Start-Sleep -Seconds 5
throw("No AD Module")
}
$computerlist = Get-ADComputer -filter *
$arraylist = New-Object System.Collections.ArrayList
$notindomainarraylist = New-Object System.Collections.ArrayList
$resultingarray = New-Object System.Collections.ArrayList
$staticresults = New-Object System.Collections.ArrayList
$staticmodified = New-Object System.Collections.ArrayList
$monitorstatic = $true
#endregion
function Report-StaticChange {
param(
[string]$Raison = "non spécifiée",
[string]$NewIP = $null,
[string]$OldIP = $null,
[string]$NewMAC = $null,
[string]$OldMAC = $null)
$staticmodified.Add([pscustomobject]@{
"Raison" = $Raison
"Nouvelle_IP" = $NewIP
"Ancienne_IP" = $OldIP
"Nouvelle_MAC" = $NewMAC
"Ancienne_MAC" = $OldMAC}) | Out-Null
}
try {
$staticresultsprevious = Import-Clixml $staticpath
}
catch
{
"Aucun fichier précedent d'IP reservées"
}
try{
$exceptions = Get-content $exceptionpath -erroraction stop
}
catch
{
Try
{
New-Item -ItemType File $exceptionpath -Force
}
catch
{
"Impossible de créer le fichier d'exception. Arrêt du script"
Start-Sleep -Seconds 5
throw("STOP FICHIER EXCEPT.")
}
}
try
{
$fichiernondomaine = Import-Clixml $fullpath
}
catch
{
Write-Output "Aucun fichier de précedence à $fullpath, vérification du chemin."
if (!(Test-Path $fullpath))
{
Write-Output "Chemin inexistant, création du fichier"
try
{
New-Item -ItemType File $fullpath -Force -ErrorAction Stop
}
catch
{
Write-Output "Impossible de créer le fichier, arret du script."
Start-Sleep -Seconds 5
throw($error[0].Exception)
}
}
}
foreach($plage in $plages)
{
foreach ($server in $servername)
{
if ($monitorstatic -eq $true)
{
if ((get-job -Name "$server*" | Where-Object {$_.state -eq "Running"}).count -ge $maximaljobperserver)
{
Write-Output "Plus de $maximaljobperserver jobs actifs sur $server. En attente de la libération de jobs."
do
{
Start-Sleep -Seconds 1
} while ((get-job -Name "$server*" | Where-Object {$_.state -eq "Running"}).count -ge $maximaljobperserver)
}
Start-Job -Name $($server+"_"+$plage+"_static") -ScriptBlock {
param($plage,$server)
$jobstaticresults = New-Object System.Collections.ArrayList
$staticstats = Invoke-Command -computername $server -scriptblock {powershell.exe "chcp 1252;Netsh dhcp server scope $($args[0]) show reservedip"} -ArgumentList $plage
foreach ($entry in $staticstats)
{
if ($entry.trim() -match "(?<ip>\d+.\d+.\d+.\d+)\W+-\W+(?<mac>\w+-\w+-\w+-\w+-\w+-\w+)")
{
$jobstaticresults.Add([PSCUSTOMOBJECT]@{
"IP" = $Matches.IP
"MAC" = $Matches.MAC
}) | Out-Null
}
}
return $jobstaticresults
} -ArgumentList $plage,$server #end start-job
} #end if ($monitostatic -eq $true)
if ((get-job -Name "$server*" | Where-Object {$_.state -eq "Running"}).count -ge $maximaljobperserver)
{
Write-Output "Plus de $maximaljobperserver jobs actifs sur $server. En attente de la libération de jobs. (leases)"
do
{
Start-Sleep -Seconds 1
} while ((get-job -Name "$server*" | Where-Object {$_.state -eq "Running"}).count -ge $maximaljobperserver)
}
Start-Job -Name $($server+"_"+$plage+"_leases") -ScriptBlock {
param($plage,$server)
$jobarraylist = New-Object System.Collections.ArrayList
$stats = Invoke-Command -computername $server -scriptblock {powershell.exe "chcp 1252;Netsh dhcp server scope $($args[0]) show clients 1"} -ArgumentList $plage
foreach ($entry in $stats)
{
if ($entry.trim() -match "(?<ip>\d+.\d+.\d+.\d+.)\W+-\W+(?<masque>\d+.\d+.\d+.\d+.).*?[^\w+](?<mac>\w+-\w+-\w+-\w+-\w+-\w+).*?[^\d+](?<bail>\d+/\d+/\d+\s+\d+:\d+:\d+).*?[^\w+](?<type>\w+).*?[^\w+](?<pc>\w+.*)$")
{
$jobarraylist.Add([pscustomobject]@{
"IP" = $Matches.ip
"Masque" = $Matches.MASQUE
"MAC" = $Matches.MAC
"PC" = $Matches.PC
"Type" = $Matches.TYPE
"Date" = (get-date $Matches.Bail )
}) | Out-Null
}
}
return $jobarraylist
} -ArgumentList $plage,$server #end start-job
}
}
Get-job | Wait-Job
$joblist = Get-Job | Where-Object {$_.State -eq "Completed"}
Write-Output "Obtention des résultats d'IP statiques"
foreach ($job in ($joblist |Where-Object {$_.name -like "*static"}))
{
$value = Receive-Job $job
if ($value -ne $null)
{
try
{
$staticresults.AddRange($value) | Out-Null
}
catch
{
try
{
$staticresults.Add($value) | Out-Null
}
catch
{
Write-Output "Erreur lors de l'ajout des données du job $($job.name) avec comme valeur $($value)"
}
}
}
Remove-Job $job
}
$joblist = Get-Job
foreach ($job in $joblist)
{
$value = Receive-Job $job
if ($value -ne $null)
{
try{
$arraylist.AddRange($value) | Out-Null
}
catch
{
try
{
$arraylist.Add($value) | Out-Null
}
catch
{
Write-Output "Erreur sur l'ajout de données du job $($job.name) avec comme valeur $($value)"
}
}
}
Remove-Job $job -ErrorAction stop
}
foreach ($job in Get-Job)
{
Write-Output "Erreur sur $job. $Job.state"
Receive-Job $job
}
foreach ($computer in $arraylist)
{
$results = $arraylist | Where-Object {$_.pc -eq $computer.PC}
foreach ($result in $results)
{
if ($computerlist.dnshostname -notcontains $result.pc)
{
"$($result.pc) N'EST PAS CONNU DANS L'AD."
$notindomainarraylist.Add($result) | Out-Null
}
}
}
#Filtrage en fonction des exceptions. Ne garder que ce qui n'a pas d'adresse mac et de nom correspondant à la liste.
$notindomainwithexceptions = $notindomainarraylist | Where-Object {$_.MAC -notin $exceptions -and $_.PC -notin $exceptions}
if ($fichiernondomaine -ne $null)
{
foreach ($computer in $notindomainwithexceptions)
{
if ($fichiernondomaine.pc.contains($computer.pc))
{
#Recherche du pc X avec l'adresse mac Y
$results = $fichiernondomaine | Where-Object {$_.pc -eq $computer.pc -and $_.MAC -eq $computer.MAC} | Sort-Object -property ip,date -Unique
if ($results -eq $null)
{
"results eq null"
#L'ordinateur est trouvé, mais sous une autre carte réseau
$index = $notindomainwithexceptions.pc.IndexOf($computer.pc) #changé $_.pc en $computer.pc
$item = $notindomainwithexceptions[$index]
$item | Add-Member -MemberType NoteProperty -Name "Raison" -Value "Nouvelle carte réseau" -force
$resultingarray.Add($item) | Out-Null
}
elseif ($results.ip -contains $computer.ip)
{
#L'ordinateur est trouvé dans le DHCP, on vérifie si le bail expire à la même date.
#On filtre uniquement sur l'objet ayant la même adresse que l'ordinateur
$item = $results | Where-Object {$_.ip -eq $computer.ip}
if ($computer.Date -gt $item.Date)
{
#La valeur date est plus grande, il a donc eu un renouvellement de bail
$item | Add-Member -MemberType NoteProperty -Name "Raison" -Value "Renouvellement du bail DHCP" -Force
$resultingarray.Add($item) | Out-Null
}
#Sinon, on enregistre pas, on avertit pas.
}
}
else
{
#Si le fichier xml importé ne comporte pas l'ordinateur, c'est donc une nouvelle connexion
$item = $computer
$item | Add-Member -MemberType NoteProperty -Name "Raison" -Value "Nouvelle connexion" -Force
$resultingarray.Add($item) | Out-Null
}
}
$notindomainarraylist | Export-Clixml $fullpath
if ($resultingarray -ne $null)
{
$resultingarray = $resultingarray | Select-object -property IP,Masque,Mac,PC,Type,Date,Raison
Send-MailMessage -From $from -To $to -Subject "Nouvelles connexions détectées" -Bodyashtml $([string]($resultingarray | ConvertTo-Html -PreContent "Type : N - AUCUN, D - DHCP B - BOOTP, U - NON SPÉCIFIÉ, R - RÉSERVATION IP" -Head "")) -Encoding $encoding -SmtpServer $smtpserver
$resultingarray | Export-Csv (join-path $configurationarray.path $("out_domain_"+ $dateforcsv +".csv")) -NoTypeInformation -Append -Delimiter ";" -Encoding UTF8
}
}
else
{
Write-Output "Aucun fichier de précedence du DHCP trouvé. Enregistrement des données actuelles en tant que reference"
$notindomainarraylist | Export-Clixml $fullpath
Send-MailMessage -From $from -To $to -Subject "Première analyse faite. Surveillance de ces entrées." -Bodyashtml $([string]($notindomainwithexceptions | ConvertTo-Html -PreContent "Type : N - AUCUN, D - DHCP B - BOOTP, U - NON SPÉCIFIÉ, R - RÉSERVATION IP" -Head "")) -Encoding $encoding -SmtpServer $smtpserver
}
#Gestion des IP Statiques
if ($monitorstatic -eq $true)
{
$staticresults = $staticresults | Select-object -property IP,MAC | Sort-Object -Property "ip","mac" -Unique
if ($staticresultsprevious -eq $null)
{
Write-Output "Aucun fichier de précedence des réservations trouvé. Enregistrement des données actuelles en tant que reference"
$staticresults | Export-Clixml $staticpath
}
else
{
foreach ($entry in $staticresults)
{
#Si l'ip est bien dans la liste des résultats précedents...
if ($entry.ip -in $staticresultsprevious.ip)
{
#On reprends l'objet de la fois précedente...
$check = $staticresultsprevious | Where-Object {$_.ip -eq $entry.ip}
#Si leurs macs différent, l'adresse mac a été changée
if ($entry.MAC -ne $check.MAC)
{
"Mac."
Report-StaticChange -Raison "Mac Changée" -OldIP $check.ip -NewIP $entry.ip -OldMAC $check.mac -NewMAC $entry.MAC
}
}
#Si l'ip n'est pas dans la liste des résultats précédents
#MAIS que la MAC y est... L'IP a donc changé
elseif ($entry.mac -in $staticresultsprevious.mac)
{
"ip"
$check = $staticresultsprevious | Where-Object {$_.mac -eq $entry.mac}
Report-StaticChange -Raison "IP Changée" -OldIP $check.ip -NewIP $entry.ip -OldMAC $check.mac -NewMAC $entry.MAC
}
#Si ni MAC ni IP, alors c'est une nouvelle entrée
else
{
"new"
Report-StaticChange -Raison "Nouvelle entrée" -OldIP $null -NewIP $entry.ip -NewMAC $entry.MAC
}
}
#On loop et vérifie que chaque ancien résultat est toujours présent pour s'assurer que rien n'est supprimé
foreach ($staticresultprevious in $staticresultsprevious)
{
#Si l'IP n'est pas dans la liste actuelle, et que la MAC n'est pas dans la liste actuelle
if ($staticresultprevious.ip -notin $staticresults.ip -and $staticresultprevious.mac -notin $staticresults.mac)
{
#On regarde si l'adresse et la mac ne sont pas dans les dernières détections de changement MAC / IP
#afin de ne pas marquer une entrée comme retirée alors qu'elle est simplement modifiée
if ($staticresultprevious.ip -notin $staticmodified.ip -or $staticresultprevious.mac -notin $staticmodified.mac)
{
Report-StaticChange -Raison "Entrée retirée" -OldIP $null -NewIP $staticresultprevious.ip -NewMAC $staticresultprevious.MAC
}
}
}
$staticresults | Export-Clixml $staticpath
if ($staticmodified.Count -gt 0)
{
Send-MailMessage -From $from -To $to -Subject "Modifications des reservations DHCP" -Bodyashtml $([string]($staticmodified | ConvertTo-Html -PreContent "Liste des modifications détectées sur les réservations du DHCP" -Head "")) -Encoding $encoding -SmtpServer $smtpserver
$staticmodified | Export-Csv (join-path $configurationarray.path $("reserved_changed_"+ $dateforcsv +".csv")) -NoTypeInformation -Append -Delimiter ";" -Encoding UTF8
}
}
}