Ajout du support API v2 (package de diagnostic) et du log fichier

- AuditLogCLI.ps1 : detection auto V1/V2 avec fallback sur erreur HTTP
- Téléchargement/extraction du zip de diagnostic
- Extraction des événements connexion/déconnexion (logs eclypse_*.log et karaf.log)
- Nettoyage automatique des fichiers temporaires
- Écriture d'un fichier .log horodate en complement de la console
- README.md : documentation FR/EN de la détection V1/V2
This commit is contained in:
2026-07-15 10:00:09 +02:00
parent 3025e97263
commit b156b1647f
3 changed files with 150 additions and 10 deletions
+2 -1
View File
@@ -3,4 +3,5 @@ plan/
.idea/
Audit_*/
*.csv
*.bat
*.bat
*.log
+122 -9
View File
@@ -3,11 +3,18 @@
CLI d'export des journaux d'audit pour automates Distech Controls Eclypse.
.DESCRIPTION
AuditLogCLI recupere les journaux d'audit (audit-logs) de chaque automate
Distech Controls Eclypse liste dans un CSV d'entree, via leur API REST,
et les enregistre au format CSV (un fichier par automate, ou un fichier
AuditLogCLI recupere les journaux d'audit de chaque automate Distech
Controls Eclypse liste dans un CSV d'entree, via leur API REST, et les
enregistre au format CSV (un fichier par automate, ou un fichier
consolide unique).
Detection automatique de la version d'API par automate :
- API v2 (package de diagnostic) essayee en premier. Le zip retourne
est extrait et les evenements connexion/deconnexion (logger
DConnection) des logs eclypse_*.log et karaf.log sont convertis en CSV.
- En cas d'erreur HTTP sur l'appel v2, bascule automatique sur
l'API v1 (audit-logs), qui retourne directement un CSV.
.PARAMETER CsvInput
Chemin vers le fichier CSV d'entree (separateur point-virgule).
Colonnes obligatoires : Hostname, Current Ip, HttpPort, HttpsPort.
@@ -46,9 +53,10 @@
.NOTES
Prerequis : PowerShell 5.1+ (inclus dans Windows 10/11)
API : Distech Controls Eclypse REST API v1
Securite : TLS 1.2, certificats auto-signes acceptes
Important : les noms de query params "startDate"/"endDate" sont une
API : Distech Controls Eclypse REST API v1 (audit-logs) et v2
(package de diagnostic), detection automatique par automate
Securite : TLS 1.0/1.1/1.2, certificats auto-signes acceptes
Important : les noms de query params "startDate"/"endDate" (v1) sont une
hypothese non validee contre la documentation officielle de
l'API audit-logs. A verifier avant utilisation en production.
#>
@@ -76,6 +84,8 @@ $ProgressPreference = 'SilentlyContinue'
# UTILITAIRES
# =====================================================================
$script:LogFilePath = Join-Path (Get-Location) "AuditLogCLI_$(Get-Date -Format 'yyyy-MM-dd_HH-mm').log"
function Write-Log {
param(
[string]$Message,
@@ -86,6 +96,7 @@ function Write-Log {
$tag = switch ($Level) { "INFO" {"[INFO ]"} "WARN" {"[WARN ]"} "ERROR" {"[ERR ]"} "OK" {"[ OK ]"} }
$color = switch ($Level) { "INFO" {"Cyan"} "WARN" {"Yellow"} "ERROR" {"Red"} "OK" {"Green"} }
Write-Host "$ts $tag $Message" -ForegroundColor $color
Add-Content -Path $script:LogFilePath -Value "$ts $tag $Message" -Encoding UTF8
}
# =====================================================================
@@ -238,6 +249,81 @@ function Invoke-AuditLogGet {
}
}
# =====================================================================
# FONCTIONS : API v2 (package de diagnostic)
# =====================================================================
function Get-DiagnosticPackageUrl {
param([string]$BaseUrl)
return "$BaseUrl/api/rest/v2/services/packages/diagnostic"
}
function Invoke-DiagnosticGet {
param(
[string]$Url,
[string]$Username,
[AllowEmptyString()][string]$Password
)
$headers = Get-AuthHeader -Username $Username -Password $Password
$zipPath = Join-Path $env:TEMP "AuditLogCLI_diag_$(Get-Random).zip"
Invoke-WebRequest -Uri $Url -Method GET -Headers $headers -UseBasicParsing -TimeoutSec 120 -OutFile $zipPath
return $zipPath
}
function Expand-DiagnosticPackage {
param(
[string]$ZipPath,
[string]$DestinationDir
)
Expand-Archive -Path $ZipPath -DestinationPath $DestinationDir -Force
}
# =====================================================================
# FONCTION : Get-ConnectionEvents
# Extrait les evenements connexion/deconnexion (logger DConnection) des
# logs eclypse_*.log et karaf.log d'un package de diagnostic V2 extrait
# =====================================================================
function Get-ConnectionEvents {
param(
[string]$LogDir,
[string]$StartDate,
[string]$EndDate
)
$logFiles = @(Get-ChildItem -Path $LogDir -Filter "eclypse_*.log" -ErrorAction SilentlyContinue)
$karafLog = @(Get-ChildItem -Path $LogDir -Filter "karaf.log" -ErrorAction SilentlyContinue)
$logFiles += $karafLog
$startDt = if ($StartDate) { [DateTime]::ParseExact($StartDate, "yyyy-MM-dd", $null) } else { $null }
$endDt = if ($EndDate) { [DateTime]::ParseExact($EndDate, "yyyy-MM-dd", $null).AddDays(1) } else { $null }
$events = @()
foreach ($logFile in $logFiles) {
$hits = Select-String -Path $logFile.FullName -Pattern "DConnection.*'(.+?)' (connected|disconnected)"
foreach ($hit in $hits) {
$tsPart = $hit.Line.Split('|')[0].Trim()
$ts = [DateTime]::MinValue
if (-not [DateTime]::TryParseExact($tsPart, "yyyy-MM-ddTHH:mm:ss,fff", $null, [System.Globalization.DateTimeStyles]::None, [ref]$ts)) {
continue
}
if ($startDt -and $ts -lt $startDt) { continue }
if ($endDt -and $ts -ge $endDt) { continue }
$events += [PSCustomObject]@{
Timestamp = $ts
User = $hit.Matches[0].Groups[1].Value
Action = $hit.Matches[0].Groups[2].Value
SourceFile = $logFile.Name
}
}
}
return @($events | Sort-Object Timestamp)
}
function ConvertTo-DiagnosticCsv {
param([array]$Events)
if ($Events.Count -eq 0) { return "" }
return ($Events | ConvertTo-Csv -NoTypeInformation | Out-String)
}
# =====================================================================
# VALIDATION DES PARAMETRES DE DATE
# =====================================================================
@@ -290,11 +376,38 @@ foreach ($automate in $automates) {
}
$creds = Get-Credentials -Automate $automate -DefaultUsername $Username -DefaultPassword $Password
$url = Get-AuditLogUrl -BaseUrl $baseUrl -StartDate $StartDate -EndDate $EndDate
Write-Log -Message "[$hostname] GET $url (user: $($creds.Username))" -Level INFO
$content = $null
$isV2 = $false
$diagUrl = Get-DiagnosticPackageUrl -BaseUrl $baseUrl
$zipPath = $null
try {
Write-Log -Message "[$hostname] GET $diagUrl (V2, user: $($creds.Username))" -Level INFO
$zipPath = Invoke-DiagnosticGet -Url $diagUrl -Username $creds.Username -Password $creds.Password
$isV2 = $true
}
catch {
Write-Log -Message "[$hostname] V2 indisponible ($($_.Exception.Message)), bascule V1" -Level WARN
}
$content = Invoke-AuditLogGet -Url $url -Username $creds.Username -Password $creds.Password
if ($isV2) {
$tempDir = Join-Path $env:TEMP "AuditLogCLI_$($ip)_$(Get-Random)"
try {
Expand-DiagnosticPackage -ZipPath $zipPath -DestinationDir $tempDir
$events = Get-ConnectionEvents -LogDir (Join-Path $tempDir "logs") -StartDate $StartDate -EndDate $EndDate
$content = ConvertTo-DiagnosticCsv -Events $events
Write-Log -Message "[$hostname] $($events.Count) evenement(s) connexion/deconnexion extrait(s) (V2)" -Level OK
}
finally {
Remove-Item -Path $zipPath -Force -ErrorAction SilentlyContinue
Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
else {
$url = Get-AuditLogUrl -BaseUrl $baseUrl -StartDate $StartDate -EndDate $EndDate
Write-Log -Message "[$hostname] GET $url (V1, user: $($creds.Username))" -Level INFO
$content = Invoke-AuditLogGet -Url $url -Username $creds.Username -Password $creds.Password
}
if ($OutputFormat -eq "PerAutomate") {
$filePath = Join-Path $outputDir "$ip.csv"
+26
View File
@@ -29,6 +29,15 @@ Se connecte à chaque automate listé dans un CSV, récupère son journal d'audi
Un filtrage optionnel par période (`-StartDate`/`-EndDate`) peut être appliqué à la requête.
### Détection automatique API v1 / v2
Le script détecte automatiquement la version d'API supportée par chaque automate, sans configuration :
1. **API v2** (package de diagnostic) est essayée en premier : `GET /api/rest/v2/services/packages/diagnostic`. La réponse est un fichier `.zip` de diagnostic complet, que le script télécharge, extrait, puis analyse pour en extraire les événements de connexion/déconnexion (`connected`/`disconnected`) présents dans `logs/eclypse_*.log` et `logs/karaf.log`. Le fichier zip et les fichiers extraits sont supprimés automatiquement après traitement ; seul le CSV final est conservé.
2. En cas d'erreur HTTP sur l'appel v2 (404, 401, 500...), le script bascule automatiquement sur **l'API v1** (`GET /api/rest/v1/system/audit-logs`), qui retourne directement un CSV.
Le CSV obtenu (v1 ou v2) suit ensuite le même traitement de sortie (`PerAutomate` ou `Consolidated`).
---
## Utilisation avec cadMasterCLI
@@ -216,6 +225,10 @@ Vérifier que les colonnes `HttpPort` et `HttpsPort` du CSV contiennent des vale
Les noms des paramètres de requête (`startDate`/`endDate`) utilisés par ce script sont une hypothèse non validée contre la documentation officielle de l'API `audit-logs`. Si le filtrage ne fonctionne pas, vérifier la documentation de l'API Eclypse de l'automate concerné.
#### "V2 indisponible, bascule V1" dans les logs
Message normal (niveau `WARN`) : l'automate ne supporte pas l'API v2 (package de diagnostic), le script utilise donc l'API v1 (`audit-logs`) à la place. Aucune action requise.
<!-- EN -->
# AuditLogCLI
@@ -247,6 +260,15 @@ Connects to each controller listed in a CSV, retrieves its audit log via the RES
An optional date-range filter (`-StartDate`/`-EndDate`) can be applied to the request.
### Automatic API v1 / v2 detection
The script automatically detects which API version each controller supports, with no configuration needed:
1. **API v2** (diagnostic package) is tried first: `GET /api/rest/v2/services/packages/diagnostic`. The response is a full diagnostic `.zip` file, which the script downloads, extracts, then parses to pull out connection/disconnection events (`connected`/`disconnected`) found in `logs/eclypse_*.log` and `logs/karaf.log`. The zip file and extracted files are automatically deleted after processing; only the final CSV is kept.
2. On any HTTP error from the v2 call (404, 401, 500...), the script automatically falls back to **API v1** (`GET /api/rest/v1/system/audit-logs`), which returns a CSV directly.
The resulting CSV (v1 or v2) then goes through the same output handling (`PerAutomate` or `Consolidated`).
---
## Using with cadMasterCLI
@@ -435,3 +457,7 @@ Check that the CSV's `HttpPort` and `HttpsPort` columns contain valid values. A
#### The `-StartDate`/`-EndDate` filter seems to have no effect
The query parameter names (`startDate`/`endDate`) used by this script are an unverified assumption against the official `audit-logs` API documentation. If filtering does not work, check the Eclypse API documentation for the specific controller.
#### "V2 indisponible, bascule V1" in the logs
Normal message (`WARN` level): the controller does not support the v2 API (diagnostic package), so the script uses the v1 API (`audit-logs`) instead. No action needed.