mardi 18 septembre 2018

Powershell : journalisation des ouvertures de session en local et à distance

Deux scripts pour le prix d'un ! Ça pourrait être une véritable aubaine si ce n'était pas un script adapté à deux situations. 👍

Ce script, couplé à une tâche planifiée l'exécutant à chaque ouverture de session, enregistre dans un fichier CSV journalier ces dernières avec le timestamp associé, ce qui permet de tracer de manière générale et durable les connexions à une station de travail ou à un serveur par les utilisateurs.

Pourquoi deux scripts ? Lorsqu'on exécute une tâche planifiée, il faut spécifier un compte d'utilisateur, qu'il soit LOCAL SERVICE ou service-tacheplan par exemple. Le problème, c'est qu'une fois que la tâche sera créée et qu'elle sera déclenchée à l'ouverture de session, ce ne sera pas l'utilisateur martin qui ouvrira Powershell et exécutera le script. Ce sera le compte renseigné dans la tâche, et par conséquent, on ne peut utiliser $env:username dans le script pour récupérer le nom de l'utilisateur qui vient d'ouvrir la session. Il est possible de passer par la classe WMI Win32_ComputerSystem pour trouver le nom de l'utilisateur qui est connecté physiquement sur la station, ce qui permet de court-circuiter l'impersonnification réalisée par Windows. Mais ce ne serait pas amusant si c'était aussi facile, dans le cadre d'une session ouverte en RDP (un serveur, typiquement), cela ne fonctionne pas car WMI retourne uniquement les sessions ouvertes physiquement, et pas à distance. Il faut donc passer par quser et jouer avec la chaîne de caractère renvoyée pour déterminer l'utilisateur qui a sa session déclenchant la tâche. Bien qu'il soit possible de procéder avec la deuxième méthode pour la première, j'ai préféré réaliser deux scripts 😉

Workstations (local)

$date = Get-Date -f "yyMMdd"
$time = Get-Date -f "HH:mm:ss"
$logfile = "c:\log-connexion\$date.csv"
$date = Get-Date -f "dd/MM/yyyy"
$compname = $env:COMPUTERNAME
$user = (Get-WmiObject -class win32_ComputerSystem | select username).username
$os = (Get-WmiObject Win32_OperatingSystem).Caption
$ip = (Get-NetIPConfiguration | Where-Object { $_.IPv4DefaultGateway -ne $null -and $_.NetAdapter.Status  -ne "Disconnected" }).IPV4address.IPAddress
$infologin = "$date,$time,$user,$compname,$ip,$os"
add-content $logfile $infologin

Serveurs (RDP)

function getrdpuser{
$quout = quser
$found = $false
$point = ">"
$sid = (($quout | Where-Object { $_ -match $point }) -split ' +')[2]
while ($found -eq $false)
{
    $username = (($quout | Where-Object { $_ -match $point }) -split ' +')[0]
    $sid = (($quout | Where-Object { $_ -match $point }) -split ' +')[2]
    $found = $true
}
return $username.Substring(1,$username.Length-1)
}

$date = Get-Date -f "yyMMdd"
$time = Get-Date -f "HH:mm:ss"
$logfile = "c:\log-connexion\$date.csv"
$date = Get-Date -f "dd/MM/yyyy"
$compname = $env:COMPUTERNAME
$user = getrdpuser
$os = (Get-WmiObject Win32_OperatingSystem).Caption
$ip = (Get-NetIPConfiguration | Where-Object { $_.IPv4DefaultGateway -ne $null -and $_.NetAdapter.Status  -ne "Disconnected" }).IPV4address.IPAddress
$infologin = "$date,$time,$user,$compname,$ip,$os"
add-content $logfile $infologin

Ensuite, il suffit d'appeler ce script via une tâche planifiée.


Après plusieurs connexions, on obtient donc un joli fichier CSV que l'on ouvre avec Excel, comme celui-ci :


Il est naturellement possible en modifiant la variable du nom de fichier dans le script de tout enregistrer dans un seul et même fichier unique si l'on souhaite tenir un registre global.

Ces scripts sont disponibles dans des versions commentées 💾 : workstation - serveur

Aucun commentaire:

Enregistrer un commentaire