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:
@@ -4,3 +4,4 @@ plan/
|
||||
Audit_*/
|
||||
*.csv
|
||||
*.bat
|
||||
*.log
|
||||
+122
-9
@@ -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
|
||||
|
||||
$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
|
||||
}
|
||||
|
||||
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 (user: $($creds.Username))" -Level INFO
|
||||
|
||||
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"
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user