Ajout initial du script IPv6ManagerCLI et de sa documentation"
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
plan/
|
||||
.claude
|
||||
.idea/
|
||||
*.csv
|
||||
*.log
|
||||
@@ -0,0 +1,386 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
CLI d'activation/desactivation IPv6 pour automates Distech Controls Eclypse Facilities (API v2).
|
||||
|
||||
.DESCRIPTION
|
||||
IPv6ManagerCLI active ou desactive l'IPv6 sur toutes les interfaces reseau
|
||||
IPv6-capables (secondary, auxiliary, wireless, bridge, primary...) de chaque
|
||||
automate Distech Controls Eclypse Facilities liste dans un CSV d'entree.
|
||||
|
||||
Pour chaque automate :
|
||||
1. GET /api/rest/v2/services/platform/network/interfaces - recupere la liste des interfaces
|
||||
2. Filtre les interfaces possedant une section "ipv6" (peu importe son contenu)
|
||||
3. POST /api/rest/v2/services/platform/network/interfaces/{name}/ipv6 avec {"enabled": true|false}
|
||||
pour chaque interface IPv6-capable detectee
|
||||
|
||||
Compatible uniquement avec les automates Eclypse Facilities supportant l'API v2
|
||||
(pas de fallback API v1).
|
||||
|
||||
.PARAMETER Action
|
||||
Etat IPv6 a appliquer sur toutes les interfaces IPv6-capables detectees :
|
||||
Enable - Active l'IPv6
|
||||
Disable - Desactive l'IPv6 (defaut)
|
||||
|
||||
.PARAMETER CsvInput
|
||||
Chemin vers le fichier CSV d'entree (separateur point-virgule).
|
||||
Colonnes obligatoires : Hostname, Current Ip, HttpPort, HttpsPort.
|
||||
Colonnes optionnelles : Username, Password (surchargent -Username/-Password).
|
||||
|
||||
.PARAMETER Username
|
||||
Nom d'utilisateur pour l'authentification API (defaut: admin).
|
||||
Peut etre surcharge par la colonne Username du CSV.
|
||||
|
||||
.PARAMETER Password
|
||||
Mot de passe pour l'authentification API (defaut: vide).
|
||||
Peut etre surcharge par la colonne Password du CSV.
|
||||
|
||||
.EXAMPLE
|
||||
.\IPv6ManagerCLI.ps1 -Action Disable -CsvInput ".\automates.csv"
|
||||
|
||||
Desactive l'IPv6 sur toutes les interfaces IPv6-capables de chaque automate du CSV.
|
||||
|
||||
.EXAMPLE
|
||||
.\IPv6ManagerCLI.ps1 -Action Enable -CsvInput ".\automates.csv" -Password "MonMotDePasse"
|
||||
|
||||
Active l'IPv6 sur toutes les interfaces IPv6-capables de chaque automate du CSV.
|
||||
|
||||
.NOTES
|
||||
Prerequis : PowerShell 5.1+ (inclus dans Windows 10/11)
|
||||
API : Distech Controls Eclypse Facilities REST API v2 uniquement
|
||||
(platform/network/interfaces) - pas de fallback v1
|
||||
Securite : TLS 1.0/1.1/1.2, certificats auto-signes acceptes
|
||||
#>
|
||||
|
||||
param(
|
||||
[ValidateSet("Enable", "Disable")]
|
||||
[string]$Action = "Disable",
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[string]$CsvInput,
|
||||
|
||||
[string]$Username = "admin",
|
||||
|
||||
[string]$Password = ""
|
||||
)
|
||||
|
||||
# Performance : desactiver la barre de progression Invoke-WebRequest
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
# =====================================================================
|
||||
# UTILITAIRES
|
||||
# =====================================================================
|
||||
|
||||
$script:LogFilePath = Join-Path (Get-Location) "IPv6ManagerCLI_$(Get-Date -Format 'yyyy-MM-dd_HH-mm').log"
|
||||
|
||||
function Write-Log {
|
||||
param(
|
||||
[string]$Message,
|
||||
[ValidateSet("INFO", "WARN", "ERROR", "OK")]
|
||||
[string]$Level = "INFO"
|
||||
)
|
||||
$ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
$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
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# FONCTION : Initialize-ApiClient
|
||||
# Force TLS 1.2 et accepte les certificats auto-signes (equivalent curl -k)
|
||||
# =====================================================================
|
||||
$script:CurlAvailable = $false
|
||||
|
||||
function Initialize-ApiClient {
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls
|
||||
|
||||
if (-not ([System.Management.Automation.PSTypeName]'TrustAllCertsPolicy').Type) {
|
||||
Add-Type @"
|
||||
using System.Net;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
public class TrustAllCertsPolicy : ICertificatePolicy {
|
||||
public bool CheckValidationResult(
|
||||
ServicePoint srvPoint, X509Certificate certificate,
|
||||
WebRequest request, int certificateProblem) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
"@
|
||||
}
|
||||
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
|
||||
|
||||
$script:CurlAvailable = [bool](Get-Command curl.exe -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Test-SslError {
|
||||
param([System.Exception]$Exception)
|
||||
$msg = $Exception.Message
|
||||
return ($msg -match "SSL" -or $msg -match "TLS" -or $msg -match "confiance" -or $msg -match "trust" -or $msg -match "certificate" -or $msg -match "envoi")
|
||||
}
|
||||
|
||||
function Invoke-CurlGet {
|
||||
param(
|
||||
[string]$Url,
|
||||
[string]$Username,
|
||||
[AllowEmptyString()][string]$Password
|
||||
)
|
||||
$output = & curl.exe -s -k -u "${Username}:${Password}" -H "Accept: application/json" $Url 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "curl GET erreur (exit code $LASTEXITCODE): $output"
|
||||
}
|
||||
return ($output | Out-String)
|
||||
}
|
||||
|
||||
function Invoke-CurlPost {
|
||||
param(
|
||||
[string]$Url,
|
||||
[string]$Username,
|
||||
[AllowEmptyString()][string]$Password,
|
||||
[string]$BodyJson
|
||||
)
|
||||
$output = & curl.exe -s -k -u "${Username}:${Password}" -H "Content-Type: application/json" -H "Accept: application/json" -X POST -d $BodyJson $Url 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "curl POST erreur (exit code $LASTEXITCODE): $output"
|
||||
}
|
||||
return ($output | Out-String)
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# FONCTION : Read-AutomateCsv
|
||||
# =====================================================================
|
||||
function Read-AutomateCsv {
|
||||
param([string]$CsvPath)
|
||||
|
||||
if (-not (Test-Path $CsvPath)) {
|
||||
throw "Fichier CSV introuvable : $CsvPath"
|
||||
}
|
||||
$rows = @(Import-Csv -Path $CsvPath -Delimiter ";" -Encoding UTF8)
|
||||
if ($rows.Count -eq 0) {
|
||||
throw "Fichier CSV vide : $CsvPath"
|
||||
}
|
||||
Write-Log -Message "CSV charge : $($rows.Count) ligne(s) depuis $CsvPath" -Level INFO
|
||||
return $rows
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# FONCTION : Get-BaseUrl
|
||||
# HTTPS priorise sur HTTP, automate ignore si aucun port valide
|
||||
# =====================================================================
|
||||
function Get-BaseUrl {
|
||||
param([PSCustomObject]$Automate)
|
||||
|
||||
$ip = $Automate."Current Ip"
|
||||
$httpsPort = $Automate.HttpsPort
|
||||
$httpPort = $Automate.HttpPort
|
||||
|
||||
if ($httpsPort -and $httpsPort -ne "" -and [int]$httpsPort -gt 0 -and [int]$httpsPort -ne -1) {
|
||||
if ([int]$httpsPort -eq 443) { return "https://$ip" }
|
||||
return "https://${ip}:$httpsPort"
|
||||
}
|
||||
if ($httpPort -and $httpPort -ne "" -and [int]$httpPort -gt 0 -and [int]$httpPort -ne -1) {
|
||||
if ([int]$httpPort -eq 80) { return "http://$ip" }
|
||||
return "http://${ip}:$httpPort"
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# FONCTION : Get-Credentials
|
||||
# Identifiants CSV prioritaires sur les parametres globaux
|
||||
# =====================================================================
|
||||
function Get-Credentials {
|
||||
param(
|
||||
[PSCustomObject]$Automate,
|
||||
[string]$DefaultUsername,
|
||||
[string]$DefaultPassword
|
||||
)
|
||||
$username = $DefaultUsername
|
||||
$password = $DefaultPassword
|
||||
if ($Automate.Username -and $Automate.Username -ne "") { $username = $Automate.Username }
|
||||
if ($Automate.Password -and $Automate.Password -ne "") { $password = $Automate.Password }
|
||||
return @{ Username = $username; Password = $password }
|
||||
}
|
||||
|
||||
function Get-AuthHeader {
|
||||
param(
|
||||
[string]$Username,
|
||||
[AllowEmptyString()][string]$Password
|
||||
)
|
||||
$pair = "${Username}:${Password}"
|
||||
$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
|
||||
$base64 = [System.Convert]::ToBase64String($bytes)
|
||||
return @{
|
||||
"Authorization" = "Basic $base64"
|
||||
"Accept" = "application/json"
|
||||
}
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# FONCTIONS : API v2 - interfaces reseau IPv6
|
||||
# =====================================================================
|
||||
function Get-NetworkInterfacesUrl {
|
||||
param([string]$BaseUrl)
|
||||
return "$BaseUrl/api/rest/v2/services/platform/network/interfaces"
|
||||
}
|
||||
|
||||
function Get-InterfaceIpv6Url {
|
||||
param([string]$BaseUrl, [string]$InterfaceName)
|
||||
return "$BaseUrl/api/rest/v2/services/platform/network/interfaces/$InterfaceName/ipv6"
|
||||
}
|
||||
|
||||
function Invoke-NetworkInterfacesGet {
|
||||
param(
|
||||
[string]$Url,
|
||||
[string]$Username,
|
||||
[AllowEmptyString()][string]$Password
|
||||
)
|
||||
$headers = Get-AuthHeader -Username $Username -Password $Password
|
||||
try {
|
||||
$response = Invoke-WebRequest -Uri $Url -Method GET -Headers $headers -UseBasicParsing -TimeoutSec 30
|
||||
return $response.Content
|
||||
}
|
||||
catch {
|
||||
if ((Test-SslError -Exception $_.Exception) -and $script:CurlAvailable) {
|
||||
Write-Log -Message "Bascule sur curl.exe -k (echec TLS .NET)" -Level WARN
|
||||
return Invoke-CurlGet -Url $Url -Username $Username -Password $Password
|
||||
}
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-InterfaceIpv6Post {
|
||||
param(
|
||||
[string]$Url,
|
||||
[string]$Username,
|
||||
[AllowEmptyString()][string]$Password,
|
||||
[bool]$Enabled
|
||||
)
|
||||
$headers = Get-AuthHeader -Username $Username -Password $Password
|
||||
$bodyJson = (@{ enabled = $Enabled } | ConvertTo-Json -Compress)
|
||||
try {
|
||||
Invoke-WebRequest -Uri $Url -Method POST -Headers $headers -ContentType "application/json" -Body $bodyJson -UseBasicParsing -TimeoutSec 30 | Out-Null
|
||||
}
|
||||
catch {
|
||||
if ((Test-SslError -Exception $_.Exception) -and $script:CurlAvailable) {
|
||||
Write-Log -Message "Bascule sur curl.exe -k (echec TLS .NET)" -Level WARN
|
||||
Invoke-CurlPost -Url $Url -Username $Username -Password $Password -BodyJson $bodyJson | Out-Null
|
||||
return
|
||||
}
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
||||
function Get-Ipv6CapableInterfaces {
|
||||
param([PSCustomObject]$InterfacesObject)
|
||||
|
||||
$result = @()
|
||||
foreach ($prop in $InterfacesObject.PSObject.Properties) {
|
||||
if ($prop.Value.PSObject.Properties.Name -contains "ipv6") {
|
||||
$result += [PSCustomObject]@{
|
||||
Name = $prop.Name
|
||||
OldState = $prop.Value.ipv6.enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# INITIALISATION
|
||||
# =====================================================================
|
||||
Initialize-ApiClient
|
||||
Write-Log -Message "=== IPv6ManagerCLI demarre - Action: $Action ===" -Level INFO
|
||||
|
||||
$automates = Read-AutomateCsv -CsvPath $CsvInput
|
||||
$desiredState = ($Action -eq "Enable")
|
||||
|
||||
$statsAutomates = 0
|
||||
$statsInterfacesOk = 0
|
||||
$statsInterfacesError = 0
|
||||
$resultRows = @()
|
||||
|
||||
# =====================================================================
|
||||
# TRAITEMENT DE CHAQUE AUTOMATE
|
||||
# =====================================================================
|
||||
foreach ($automate in $automates) {
|
||||
$hostname = $automate.Hostname
|
||||
$ip = $automate."Current Ip"
|
||||
$statsAutomates++
|
||||
|
||||
$baseUrl = Get-BaseUrl -Automate $automate
|
||||
if (-not $baseUrl) {
|
||||
Write-Log -Message "[$hostname] Aucun port HTTP/HTTPS valide - ignore" -Level WARN
|
||||
$resultRows += [PSCustomObject]@{
|
||||
Hostname = $hostname; IP = $ip; Interface = ""
|
||||
AncienEtat = ""; NouvelEtat = ""
|
||||
Statut = "Erreur"; Message = "Aucun port HTTP/HTTPS valide"
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
$creds = Get-Credentials -Automate $automate -DefaultUsername $Username -DefaultPassword $Password
|
||||
|
||||
try {
|
||||
$interfacesUrl = Get-NetworkInterfacesUrl -BaseUrl $baseUrl
|
||||
Write-Log -Message "[$hostname] GET $interfacesUrl (user: $($creds.Username))" -Level INFO
|
||||
$content = Invoke-NetworkInterfacesGet -Url $interfacesUrl -Username $creds.Username -Password $creds.Password
|
||||
$interfaces = $content | ConvertFrom-Json
|
||||
|
||||
$capableInterfaces = Get-Ipv6CapableInterfaces -InterfacesObject $interfaces
|
||||
Write-Log -Message "[$hostname] $($capableInterfaces.Count) interface(s) IPv6-capable(s) detectee(s)" -Level INFO
|
||||
|
||||
foreach ($iface in $capableInterfaces) {
|
||||
$ipv6Url = Get-InterfaceIpv6Url -BaseUrl $baseUrl -InterfaceName $iface.Name
|
||||
try {
|
||||
Write-Log -Message "[$hostname] POST $ipv6Url (enabled=$desiredState)" -Level INFO
|
||||
Invoke-InterfaceIpv6Post -Url $ipv6Url -Username $creds.Username -Password $creds.Password -Enabled $desiredState
|
||||
Write-Log -Message "[$hostname] Interface '$($iface.Name)' IPv6 -> $Action" -Level OK
|
||||
$statsInterfacesOk++
|
||||
$resultRows += [PSCustomObject]@{
|
||||
Hostname = $hostname; IP = $ip; Interface = $iface.Name
|
||||
AncienEtat = $iface.OldState; NouvelEtat = $desiredState
|
||||
Statut = "Succes"; Message = ""
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log -Message "[$hostname] ERREUR interface '$($iface.Name)' : $($_.Exception.Message)" -Level ERROR
|
||||
$statsInterfacesError++
|
||||
$resultRows += [PSCustomObject]@{
|
||||
Hostname = $hostname; IP = $ip; Interface = $iface.Name
|
||||
AncienEtat = $iface.OldState; NouvelEtat = $desiredState
|
||||
Statut = "Erreur"; Message = $_.Exception.Message
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log -Message "[$hostname] ERREUR : $($_.Exception.Message)" -Level ERROR
|
||||
$resultRows += [PSCustomObject]@{
|
||||
Hostname = $hostname; IP = $ip; Interface = ""
|
||||
AncienEtat = ""; NouvelEtat = ""
|
||||
Statut = "Erreur"; Message = $_.Exception.Message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# ECRITURE DU CSV DE RESULTAT
|
||||
# =====================================================================
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm"
|
||||
$outputFile = Join-Path (Get-Location) "ipv6manager_$timestamp.csv"
|
||||
if ($resultRows.Count -gt 0) {
|
||||
$resultRows | Export-Csv -Path $outputFile -NoTypeInformation -Encoding UTF8 -Delimiter ";"
|
||||
Write-Log -Message "CSV de resultat ecrit : $outputFile ($($resultRows.Count) ligne(s))" -Level OK
|
||||
}
|
||||
else {
|
||||
Write-Log -Message "Aucune donnee a ecrire dans le CSV de resultat" -Level WARN
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# RESUME FINAL
|
||||
# =====================================================================
|
||||
Write-Log -Message "========== RESUME ==========" -Level INFO
|
||||
Write-Log -Message "Automates traites : $statsAutomates" -Level INFO
|
||||
Write-Log -Message "Interfaces modifiees avec succes : $statsInterfacesOk" -Level INFO
|
||||
Write-Log -Message "Interfaces en erreur : $statsInterfacesError" -Level $(if ($statsInterfacesError -gt 0) { "WARN" } else { "INFO" })
|
||||
Write-Log -Message "============================" -Level INFO
|
||||
@@ -0,0 +1,421 @@
|
||||
<!-- FR -->
|
||||
# IPv6ManagerCLI
|
||||
|
||||
Outil en ligne de commande pour activer ou désactiver l'IPv6 sur les interfaces réseau des automates **Distech Controls Eclypse Facilities** (API v2 uniquement), via leur API REST.
|
||||
|
||||
---
|
||||
|
||||
> **IMPORTANT : Ce projet est un développement personnel indépendant.**
|
||||
>
|
||||
> Ce projet a été développé par Charles-Arthur DAVID à titre personnel.
|
||||
> Distech Controls n'est pas responsable de ce projet et ne le supporte pas.
|
||||
> Aucune demande de support ne sera prise en charge par Distech Controls.
|
||||
> Distech Controls ne fournit aucune garantie ni assistance technique pour ce projet.
|
||||
|
||||
---
|
||||
|
||||
## Prérequis
|
||||
|
||||
- **Windows 10 ou 11** (PowerShell 5.1 est inclus par défaut, rien à installer)
|
||||
- Un accès réseau aux automates Eclypse Facilities
|
||||
- Les identifiants de connexion aux automates (par défaut : `admin` / mot de passe vide)
|
||||
- Automates compatibles **API v2** (Eclypse Facilities).
|
||||
|
||||
## Ce que fait cet outil
|
||||
|
||||
Pour chaque automate listé dans un CSV :
|
||||
|
||||
1. Récupère la liste des interfaces réseau (`GET /api/rest/v2/services/platform/network/interfaces`).
|
||||
2. Détecte les interfaces IPv6-capables : celles possédant une section `ipv6` dans leur configuration (ex : `secondary`, `auxiliary`, `wireless`, `bridge`, `primary`).
|
||||
3. Applique l'état demandé (`Enable` ou `Disable`) sur **chacune** de ces interfaces (`POST /api/rest/v2/services/platform/network/interfaces/{name}/ipv6` avec `{"enabled": true|false}`), indépendamment de leur état actuel.
|
||||
|
||||
En cas d'erreur sur un automate ou une interface (injoignable, échec du POST...), le script logue l'erreur, marque la ligne concernée en erreur, et continue avec l'interface/l'automate suivant.
|
||||
|
||||
Un CSV récapitulatif est généré à la fin, avec l'ancien et le nouvel état de chaque interface traitée.
|
||||
|
||||
---
|
||||
|
||||
## Utilisation avec cadMasterCLI
|
||||
|
||||
Ce script peut être piloté depuis **[cadMasterCLI](https://git.cadjou.net/DistechControls/cadMasterCLI)**, qui évite d'avoir à utiliser PowerShell manuellement.
|
||||
|
||||
Quand ce script est sélectionné dans cadMasterCLI :
|
||||
|
||||
- Les paramètres sont détectés automatiquement et affichés sous forme de champs :
|
||||
- `Action` : RadioButtons `Enable` / `Disable` (valeurs du `[ValidateSet]`, `Disable` sélectionné par défaut)
|
||||
- `CsvInput` : bouton "Parcourir" + zone de collage d'IPs (conversion automatique en CSV)
|
||||
- `Username`, `Password` : champs texte
|
||||
- Il suffit de renseigner les champs puis de lancer l'exécution depuis l'interface — aucune commande PowerShell à taper, aucune politique d'exécution à modifier manuellement.
|
||||
|
||||
Se référer à la section suivante pour le détail des paramètres, du format du CSV attendu et du dépannage.
|
||||
|
||||
---
|
||||
|
||||
## Utilisation en autonome
|
||||
|
||||
### Vérifier que PowerShell est disponible
|
||||
|
||||
Ouvrir un terminal (touche `Windows` + `R`, taper `powershell`, puis `Entrée`) et taper :
|
||||
|
||||
```powershell
|
||||
$PSVersionTable.PSVersion
|
||||
```
|
||||
|
||||
Le numéro `Major` doit être **5 ou plus**.
|
||||
|
||||
### Installation
|
||||
|
||||
Aucune installation requise. Télécharger ou cloner le dépôt :
|
||||
|
||||
```
|
||||
IPv6ManagerCLI/ (ce dépôt)
|
||||
├── IPv6ManagerCLI.ps1 <- Script principal
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### Utilisation
|
||||
|
||||
#### Ouvrir PowerShell dans le bon dossier
|
||||
|
||||
1. Ouvrir l'explorateur de fichiers et naviguer dans le dossier du dépôt
|
||||
2. Cliquer dans la barre d'adresse, taper `powershell`, puis appuyer sur `Entrée`
|
||||
|
||||
Ou bien dans un terminal PowerShell :
|
||||
|
||||
```powershell
|
||||
cd "C:\chemin\vers\IPv6ManagerCLI"
|
||||
```
|
||||
|
||||
#### Politique d'exécution
|
||||
|
||||
Si c'est la première fois, PowerShell peut bloquer l'exécution des scripts. Autoriser pour la session en cours :
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
|
||||
```
|
||||
|
||||
Cette commande est sans risque : elle n'autorise les scripts que pour la fenêtre PowerShell en cours.
|
||||
|
||||
#### Désactiver l'IPv6 (action par défaut)
|
||||
|
||||
```powershell
|
||||
.\IPv6ManagerCLI.ps1 -CsvInput ".\automates.csv"
|
||||
```
|
||||
|
||||
#### Activer l'IPv6
|
||||
|
||||
```powershell
|
||||
.\IPv6ManagerCLI.ps1 -Action Enable -CsvInput ".\automates.csv"
|
||||
```
|
||||
|
||||
Avec un mot de passe :
|
||||
|
||||
```powershell
|
||||
.\IPv6ManagerCLI.ps1 -Action Enable -CsvInput ".\automates.csv" -Password "MonMotDePasse"
|
||||
```
|
||||
|
||||
**Résultat** : Un fichier `ipv6manager_yyyy-MM-dd_HH-mm.csv` est créé dans le dossier courant, avec le détail par interface (ancien état, nouvel état, statut).
|
||||
|
||||
#### Aide intégrée
|
||||
|
||||
```powershell
|
||||
Get-Help .\IPv6ManagerCLI.ps1 -Detailed
|
||||
```
|
||||
|
||||
### Format du CSV d'entrée
|
||||
|
||||
Le fichier CSV utilise le **point-virgule** (`;`) comme séparateur.
|
||||
|
||||
#### Colonnes obligatoires
|
||||
|
||||
| Colonne | Description |
|
||||
|---------|-------------|
|
||||
| `Hostname` | Nom de l'automate |
|
||||
| `Current Ip` | Adresse IP de l'automate |
|
||||
| `HttpPort` | Port HTTP (`80` ou `-1` si désactivé) |
|
||||
| `HttpsPort` | Port HTTPS (`443` ou `-1` si désactivé) |
|
||||
|
||||
#### Colonnes optionnelles
|
||||
|
||||
| Colonne | Description |
|
||||
|---------|-------------|
|
||||
| `Username` | Login spécifique à cet automate |
|
||||
| `Password` | Mot de passe spécifique à cet automate |
|
||||
|
||||
#### Exemple de CSV
|
||||
|
||||
```csv
|
||||
"Hostname";"Current Ip";"HttpPort";"HttpsPort"
|
||||
"ECY-BATIMENT-01";"10.60.105.42";"-1";"443"
|
||||
"ECY-BATIMENT-02";"10.60.105.44";"-1";"443"
|
||||
```
|
||||
|
||||
### CSV de résultat
|
||||
|
||||
Un fichier `ipv6manager_yyyy-MM-dd_HH-mm.csv` est généré dans le dossier courant, avec une ligne par interface traitée :
|
||||
|
||||
| Colonne | Description |
|
||||
|---------|-------------|
|
||||
| `Hostname` | Nom de l'automate |
|
||||
| `IP` | Adresse IP de l'automate |
|
||||
| `Interface` | Nom de l'interface (secondary, auxiliary, wireless, bridge, primary...) |
|
||||
| `AncienEtat` | État IPv6 avant modification (`True`/`False`) |
|
||||
| `NouvelEtat` | État IPv6 appliqué (`True`/`False`) |
|
||||
| `Statut` | `Succes` ou `Erreur` |
|
||||
| `Message` | Détail de l'erreur si applicable |
|
||||
|
||||
### Logs
|
||||
|
||||
Chaque exécution affiche sa progression directement dans la console, avec un résumé final (automates traités, interfaces modifiées, interfaces en erreur).
|
||||
|
||||
#### Niveaux de log
|
||||
|
||||
| Niveau | Couleur console | Signification |
|
||||
|--------|----------------|---------------|
|
||||
| `INFO` | Cyan | Opération normale |
|
||||
| `OK` | Vert | Opération réussie |
|
||||
| `WARN` | Jaune | Avertissement (port invalide...) |
|
||||
| `ERROR` | Rouge | Erreur (connexion échouée, automate injoignable...) |
|
||||
|
||||
### Résumé des paramètres
|
||||
|
||||
```
|
||||
.\IPv6ManagerCLI.ps1 [-Action <Enable|Disable>] -CsvInput <chemin> [-Username <login>] [-Password <mdp>]
|
||||
```
|
||||
|
||||
| Paramètre | Obligatoire | Défaut | Description |
|
||||
|-----------|:-----------:|--------|-------------|
|
||||
| `-Action` | Non | `Disable` | `Enable` ou `Disable` |
|
||||
| `-CsvInput` | Oui | — | Chemin du fichier CSV d'entrée |
|
||||
| `-Username` | Non | `admin` | Login API (surchargeable par le CSV) |
|
||||
| `-Password` | Non | *(vide)* | Mot de passe API (surchargeable par le CSV) |
|
||||
|
||||
### Dépannage
|
||||
|
||||
#### "Impossible d'exécuter le script car l'exécution de scripts est désactivée"
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
|
||||
```
|
||||
|
||||
#### "Aucun port HTTP/HTTPS valide"
|
||||
|
||||
Vérifier que les colonnes `HttpPort` et `HttpsPort` du CSV contiennent des valeurs valides. Un port à `-1` signifie "désactivé". Au moins un des deux doit être actif.
|
||||
|
||||
#### Timeout ou erreur de connexion
|
||||
|
||||
- Vérifier que l'automate est joignable (`ping 10.60.105.x`)
|
||||
- Vérifier les identifiants (Username / Password)
|
||||
- Vérifier que le port est correct (HTTP 80 ou HTTPS 443)
|
||||
- Vérifier que l'automate est bien un Eclypse Facilities compatible API v2
|
||||
|
||||
<!-- EN -->
|
||||
# IPv6ManagerCLI
|
||||
|
||||
Command-line tool to enable or disable IPv6 on the network interfaces of **Distech Controls Eclypse Facilities** controllers (API v2 only), via their REST API.
|
||||
|
||||
---
|
||||
|
||||
> **IMPORTANT: This project is an independent personal development.**
|
||||
>
|
||||
> This project was developed by Charles-Arthur DAVID on a personal basis.
|
||||
> Distech Controls is not responsible for this project and does not support it.
|
||||
> No support requests will be handled by Distech Controls.
|
||||
> Distech Controls provides no warranty or technical assistance for this project.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Windows 10 or 11** (PowerShell 5.1 is included by default, nothing to install)
|
||||
- Network access to the Eclypse Facilities controllers
|
||||
- Login credentials for the controllers (default: `admin` / empty password)
|
||||
- Controllers compatible with **API v2** (Eclypse Facilities).
|
||||
|
||||
## What this tool does
|
||||
|
||||
For each controller listed in a CSV:
|
||||
|
||||
1. Retrieves the list of network interfaces (`GET /api/rest/v2/services/platform/network/interfaces`).
|
||||
2. Detects IPv6-capable interfaces: those with an `ipv6` section in their configuration (e.g. `secondary`, `auxiliary`, `wireless`, `bridge`, `primary`).
|
||||
3. Applies the requested state (`Enable` or `Disable`) on **each** of these interfaces (`POST /api/rest/v2/services/platform/network/interfaces/{name}/ipv6` with `{"enabled": true|false}`), regardless of their current state.
|
||||
|
||||
On error for a controller or interface (unreachable, failed POST...), the script logs the error, flags the row as an error, and continues with the next interface/controller.
|
||||
|
||||
A summary CSV is generated at the end, with the old and new state of each processed interface.
|
||||
|
||||
---
|
||||
|
||||
## Using with cadMasterCLI
|
||||
|
||||
This script can be run from **[cadMasterCLI](https://git.cadjou.net/DistechControls/cadMasterCLI)**, which avoids having to use PowerShell manually.
|
||||
|
||||
When this script is selected in cadMasterCLI:
|
||||
|
||||
- Parameters are detected automatically and rendered as input fields:
|
||||
- `Action`: RadioButtons `Enable` / `Disable` (values from `[ValidateSet]`, `Disable` selected by default)
|
||||
- `CsvInput`: a "Browse" button plus an IP paste area (automatic conversion to CSV)
|
||||
- `Username`, `Password`: text fields
|
||||
- Simply fill in the fields and launch the run from the interface — no PowerShell command to type, no execution policy to change manually.
|
||||
|
||||
See the next section for parameter details, the expected CSV format, and troubleshooting.
|
||||
|
||||
---
|
||||
|
||||
## Standalone usage
|
||||
|
||||
### Check that PowerShell is available
|
||||
|
||||
Open a terminal (`Windows` key + `R`, type `powershell`, then `Enter`) and type:
|
||||
|
||||
```powershell
|
||||
$PSVersionTable.PSVersion
|
||||
```
|
||||
|
||||
The `Major` number must be **5 or higher**.
|
||||
|
||||
### Installation
|
||||
|
||||
No installation required. Download or clone this repository:
|
||||
|
||||
```
|
||||
IPv6ManagerCLI/ (this repo)
|
||||
├── IPv6ManagerCLI.ps1 <- Main script
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
#### Open PowerShell in the right folder
|
||||
|
||||
1. Open File Explorer and navigate to the repository folder
|
||||
2. Click in the address bar, type `powershell`, then press `Enter`
|
||||
|
||||
Or in a PowerShell terminal:
|
||||
|
||||
```powershell
|
||||
cd "C:\path\to\IPv6ManagerCLI"
|
||||
```
|
||||
|
||||
#### Execution policy
|
||||
|
||||
The first time, PowerShell may block script execution. Allow it for the current session:
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
|
||||
```
|
||||
|
||||
This command is safe: it only allows scripts for the current PowerShell window.
|
||||
|
||||
#### Disable IPv6 (default action)
|
||||
|
||||
```powershell
|
||||
.\IPv6ManagerCLI.ps1 -CsvInput ".\controllers.csv"
|
||||
```
|
||||
|
||||
#### Enable IPv6
|
||||
|
||||
```powershell
|
||||
.\IPv6ManagerCLI.ps1 -Action Enable -CsvInput ".\controllers.csv"
|
||||
```
|
||||
|
||||
With a password:
|
||||
|
||||
```powershell
|
||||
.\IPv6ManagerCLI.ps1 -Action Enable -CsvInput ".\controllers.csv" -Password "MyPassword"
|
||||
```
|
||||
|
||||
**Result**: A file `ipv6manager_yyyy-MM-dd_HH-mm.csv` is created in the current folder, with per-interface detail (old state, new state, status).
|
||||
|
||||
#### Built-in help
|
||||
|
||||
```powershell
|
||||
Get-Help .\IPv6ManagerCLI.ps1 -Detailed
|
||||
```
|
||||
|
||||
### Input CSV format
|
||||
|
||||
The CSV file uses a **semicolon** (`;`) as separator.
|
||||
|
||||
#### Required columns
|
||||
|
||||
| Column | Description |
|
||||
|---------|-------------|
|
||||
| `Hostname` | Controller name |
|
||||
| `Current Ip` | Controller IP address |
|
||||
| `HttpPort` | HTTP port (`80` or `-1` if disabled) |
|
||||
| `HttpsPort` | HTTPS port (`443` or `-1` if disabled) |
|
||||
|
||||
#### Optional columns
|
||||
|
||||
| Column | Description |
|
||||
|---------|-------------|
|
||||
| `Username` | Login specific to this controller |
|
||||
| `Password` | Password specific to this controller |
|
||||
|
||||
#### CSV example
|
||||
|
||||
```csv
|
||||
"Hostname";"Current Ip";"HttpPort";"HttpsPort"
|
||||
"ECY-BUILDING-01";"10.60.105.42";"-1";"443"
|
||||
"ECY-BUILDING-02";"10.60.105.44";"-1";"443"
|
||||
```
|
||||
|
||||
### Result CSV
|
||||
|
||||
A file `ipv6manager_yyyy-MM-dd_HH-mm.csv` is generated in the current folder, with one row per processed interface:
|
||||
|
||||
| Column | Description |
|
||||
|---------|-------------|
|
||||
| `Hostname` | Controller name |
|
||||
| `IP` | Controller IP address |
|
||||
| `Interface` | Interface name (secondary, auxiliary, wireless, bridge, primary...) |
|
||||
| `AncienEtat` | IPv6 state before the change (`True`/`False`) |
|
||||
| `NouvelEtat` | Applied IPv6 state (`True`/`False`) |
|
||||
| `Statut` | `Succes` or `Erreur` |
|
||||
| `Message` | Error detail if applicable |
|
||||
|
||||
### Logs
|
||||
|
||||
Each run displays its progress directly in the console, with a final summary (controllers processed, interfaces changed, interfaces in error).
|
||||
|
||||
#### Log levels
|
||||
|
||||
| Level | Console color | Meaning |
|
||||
|--------|----------------|---------------|
|
||||
| `INFO` | Cyan | Normal operation |
|
||||
| `OK` | Green | Successful operation |
|
||||
| `WARN` | Yellow | Warning (invalid port...) |
|
||||
| `ERROR` | Red | Error (connection failed, controller unreachable...) |
|
||||
|
||||
### Parameters summary
|
||||
|
||||
```
|
||||
.\IPv6ManagerCLI.ps1 [-Action <Enable|Disable>] -CsvInput <path> [-Username <login>] [-Password <password>]
|
||||
```
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|-----------|:-----------:|--------|-------------|
|
||||
| `-Action` | No | `Disable` | `Enable` or `Disable` |
|
||||
| `-CsvInput` | Yes | — | Path to the input CSV file |
|
||||
| `-Username` | No | `admin` | API login (overridable by the CSV) |
|
||||
| `-Password` | No | *(empty)* | API password (overridable by the CSV) |
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### "Cannot run the script because script execution is disabled"
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
|
||||
```
|
||||
|
||||
#### "No valid HTTP/HTTPS port"
|
||||
|
||||
Check that the CSV's `HttpPort` and `HttpsPort` columns contain valid values. A port set to `-1` means "disabled". At least one of the two must be active.
|
||||
|
||||
#### Timeout or connection error
|
||||
|
||||
- Check that the controller is reachable (`ping 10.60.105.x`)
|
||||
- Check the credentials (Username / Password)
|
||||
- Check that the port is correct (HTTP 80 or HTTPS 443)
|
||||
- Check that the controller is an Eclypse Facilities unit compatible with API v2
|
||||
Reference in New Issue
Block a user