Ce petit didacticiel vous permettra de créer une base de données simple vous permettant de savoir qui est connecté sur quel ordinateur en temps et en heure, de récupérer des informations sur leur heure de login / logout, mais également (dans un prochain article) comment prendre la main sur l'ordinateur simplement en cliquant sur un lien hypertexte.
Comme les ordinateurs qui se connecteront / déconnecteront écriront dans un fichier de log, le chemin de ce fichier doit être partagé et accessible à chacun. Pour plus de praticité, créons un répértoire partagé. Pour cet exemple, supposons que nous avons crée un partage sur \\storage\logs$
Dans le repertoire NETLOGON de votre controlleur de domaine, créez deux fichiez :
@echo off
ECHO %DATE%;%TIME%;%USERNAME%;%COMPUTERNAME%;%LOGONSERVER%;login >> \\storage\logs$\loginout.TXT
@echo off
ECHO %DATE%;%TIME%;%USERNAME%;%COMPUTERNAME%;%LOGONSERVER%;logout >> \\storage\logs$\loginout.TXT
Dans cet exemple, ces scripts sont liés à la Default Domain Policy.
Pour lier un scripts à ces GPO, ouvrez l'éditeur de stratégies de groupe, sélectionnez la Police par Défaut du Domaine, puis clic droit : Modifier.
Allez dans Configuration Utilisateur => Polices => Paramètres Windows => Scripts puis ajoutez les scripts de logon / logout, en précisant le chemin réseau (quelque chose comme \DC\netlogon\login.bat et pas le chemin local comme C:\Chemin\Vers\Script.ps1)
Sauvegardez les changements, et à partir de maintenant, vos ordinateurs vont commencer à enregistrer des données à chaque ouverture ou fermeture de session dans \storage\logs$\loginlogout.TXT
En utilisant mon script, vous pouvez récolter, obtenir les dernières informations du fichier de log et génerer un rapport en HTML.
Vous pouvez télécharger le script depuis mon répertoire git personnel.
#Requires -version 3
#Ce script requiert Powershell V3 ou supérieur pour fonctionner correctement, car l'export vers un fichier HTML ne fonctionnera pas correctement si c'est une version 2.
#Pensez à faire correspondre le chemin du fichier a ce que vous avez dans les .bat mis en GPO
$filename = "\\storage\logs$\loginout.TXT"
$logs = Get-Content $filename
# Cette partie est utilisée pour éviter d'avoir un trop gros fichier. Au dessus de 20000 entrées, il sauvegardera le contenu dans un autre fichier, puis réecrira le fichier avec les 10000 dernières. Vous pouvez changer ces valeurs à volonté.
if ($logs.count -gt 20000)
{
Copy-Item $filename $($filename + "_archive_" + $(Get-Date -Format dd_MM_yy) + ".txt")
$logs[-10000..-1] | Out-File $filename -Force utf8
}
$tableau = new-object System.Collections.ArrayList
$tableau2 = new-object System.Collections.ArrayList
#L'outil RSAT avec le module Active Directory n'est nécessaire que si vous lancer le script depuis un poste client. Si vous vous en servez depuis le serveur, ce doit être, celui ci doit être au moins un 2008 R2.
ipmo activedirectory
# Obtient la liste des utilisateurs depuis le controlleur de domaine. Necessaire pour retrouver le nom complet à partir du Sam Account Name.
$userlist = get-aduser -filter * | Select-Object -Property samaccountname,name
# Lisons le fichier ligne par ligne!
foreach ($log in $logs)
{
# J'utilise une REGEX pour retrouver les diverses informations de chaque ligne du fichier
if ($log -match "(?<date>\d+/\d+/\d+);(?<heure>.+:\d+:\d+[,.]\d+);(?<compte>\S+);(?<pc>\S+);(?<serveur>\W{2}\w+);(?<action>.*$)")
{
# Dans certains cas, le format de date diffère et affiche l'année en premier. Je vérifie juste si le format correspond à un format étranger, et le cas écheant, je réorganise le tout.
$date = $Matches.date -split("/")
if ($date[0].length -le 2)
{
$matches.date = [string]$($date[1]+"/"+$date[0]+"/"+$date[2])
}
$object = [pscustomobject]@{
"Date" = $([datetime]$Matches.date)
"Time" = $($($Matches.heure) -replace(",\d+",""))
"Account" = $Matches.compte
"Pc" = $matches.pc
"Action" = $Matches.action
"Server" = $Matches.serveur
}
$tableau.add($object) | Out-Null
}
}
# Je trie le tableau récapitulatif, par date en descendant, puis je regroupe tout par nom d'ordinateur
$tableaugroupe = $tableau | sort-object -property @{Expression="Date";descending=$true} | Group-Object -Property "PC"
# Comme certains ordinateurs n'ont pas d'information de login / logout en fonction de leur utilisation (travail par VPN par exemple), je crée un objet avec des valeurs pré-définies pour ces cas
$itemsansvaleur = [pscustomobject]@{
"Date" = $([datetime]"01/01/1901")
"Time" = "00:00:00"
}
# Pour chaque entrée dans le tableau trié, je prends le premier login et logout (qui sont les valeurs les plus récentes), puis je retrouve les informations dessus.
foreach ($entree in $tableaugroupe)
{
$lastlogin = $lastlogout = [PSCustomObject]
try
{
$lastlogin = $($entree.group | Where-Object {$_.action -like "*login*"})[0]
}
catch
{
Write-Host "Erreur login sur $($entree.Name)"
$lastlogin = $itemsansvaleur
}
try
{
$lastlogout = $($entree.group | Where-Object {$_.action -like "*logout*"})[0]
}
catch
{
Write-Host "Erreur logout sur $($entree.Name)"
$lastlogout = $itemsansvaleur
}
# Je retrouve le nom complet
$nom = $userlist | where-object {$_.samaccountname -eq $($lastlogin.account)} | Select-Object -ExpandProperty "Name"
# Puis je crée l'objet.
$object = [pscustomobject]@{
"Compte" = $lastlogin.account
"Name" = $nom
"PC" = $entree.group[0].pc
"Dernier Login" = get-date $(($lastlogin.Date).ToShortDateString()+" "+$lastlogin.heure) -Format "dd/MM/yy HH:mm:ss"
"Serveur Login" = $lastlogin.server
"Dernier Logout" = get-date $(($lastlogout.Date).ToShortDateString()+" "+$lastlogout.heure) -Format "dd/MM/yy HH:mm:ss"
"Serveur Logout" = $lastlogout.server
}
$tableau2.Add($object) | out-null
}
$date = Get-Date
# Je trie le tableau par ordinateur, puis je le convertit au format HTML. J'ai rajouté un fichier CSS pour rendre le tout plus joli. Si vous voulez donner un look plus sympa à votre fichier, créez juste un fichier nommé "tableaux.css" dans le même répertoire que le fichier HTML et laissez votre créativité travailler :D
$tableau2 | sort-object -Property "PC" | ConvertTo-Html -title "$($date.ToShortDateString()) $($date.ToShortTimeString())" -CssUri "tableaux.css" | Out-File "\\storage\logs$\logintohtml.html" -Encoding utf8 -Force
#Après cela, j'uploade le fichier sur un serveur web en me servant de .NET et en passant via le FTP. Ce n'est pas utile si vous stockez la page localement.
# Le login / password est en clair ici. Je ne le recommande pas, mais c'est uniquement à but d'exemple. Vous pouvez le rendre plus sur, mais ce n'est pas le but de ce script.
$credentials = new-object System.Net.NetworkCredential("username","password")
$webclient = new-object System.Net.WebClient
$webclient.Credentials = $credentials
$uri = New-Object System.Uri("ftp://webserver/www/logintohtml.html")
$webclient.uploadFile($uri,'\\storage\log$\logintohtml.html')
Le résultat est la génération d'un fichier html contenant diverses informations.
J'ai amélioré depuis le script en ajoutant les résultats issus des pools DHCP de nos serveurs 2012, ainsi qu'ajouté des liens hypertexte sur les noms des PC pour pouvoir lancer directement la prise de main via Dameware dessus. Pour la tâche planifiée, vous pouvez regarder mon autre article expliquant comment créer et gérer les scripts Powershell. Pour un groupe de 150 utilisateurs, je fais tourner mon script toutes les 5 minutes et il ne prends pas plus de 30 secondes à s'exécuter.