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.

A la recherche d'informations.

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.

Let's Code!

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!

Au final...

  • Le script nécessite le module Active Directory pour Powershell pour fonctionner. Il doit fonctionner sur du Powershell V2 (estimé mais non testé) et marche sans problème à partir de la V3!
  • Lors du premier lancement, exécutez le script manuellement (pas en tâche planifiée). Il effectuera toute la configuration et vous posera diverses questions (Pools DHCP à surveiller, serveurs à interroger, chemin pour l'enregistrement des fichiers de configuration, serveur smtp, etc.). Mettez le en tâche planifiée une fois cette configuration faite.
  • Un fichier exceptions.txt se trouvera dans le repertoire que vous aurez spécifié dans la configuration. En mettant une adresse mac ou un nom de pc par ligne, ces entrées seront ignorées, vous permettant de ne pas avoir d'alerte pour des périphériques hors domaine connus

Et une petite capture d'écran d'un résultat reçu par mail pour quelques "intrus" d'un domaine !

DHCP

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

        }
    }
}

Ajouter un commentaire

Article précédent Article suivant