Guide technique ANYSYS · vérifié le 26 octobre 2026
Exploiter UniFi : sauvegardes, mises à jour, SIEM et inventaire par API

Sauvegarder et migrer une console, encadrer les mises à jour, envoyer les journaux vers un SIEM en CEF et inventorier sites, équipements et clients avec l’API officielle UniFi Network, grâce à un script PowerShell en lecture seule.
01 / Cadre
Périmètre
Ce dernier guide de la série traite du maintien en condition opérationnelle : sauvegardes, migration de console, mises à jour, journalisation et automatisation en lecture seule. Il complète la conception, le pare-feu, le Wi-Fi et l’accès distant.
La partie API s’appuie sur la référence officielle UniFi Network API 10.6.106 publiée sur developer.ui.com. Ubiquiti indique que la documentation locale de l’API, propre à votre version, est consultable dans UniFi Network > Integrations : c’est elle qui fait foi pour votre console.
02 / Procédure
Sauvegardes, restauration et migration
UniFi distingue deux familles de sauvegardes :
| Type | Contenu | Où | Usage |
|---|---|---|---|
| Sauvegarde système (System Config Backup) | OS, applications et configuration des équipements | Settings > Control Plane > Backups | Cas général sur Cloud Gateway et CloudKey ; seule méthode pour transférer la gestion vers une autre console sans réinitialiser les équipements. |
| Sauvegarde automatique cloud | Idem, stockée sur le compte UI du propriétaire | Option « System Backups » | Chaque semaine et avant chaque mise à jour majeure ; gérée par le seul propriétaire. |
| Sauvegarde locale hors ligne | Fichier téléchargé | Settings > Control Plane > Backups | Copie externe, conservée hors de la console et hors du compte UI. |
| Sauvegarde Network seule (.unf) | Réglages Network et configuration des équipements | Application Network | Serveurs auto-hébergés et anciennes installations, migration vers UniFi OS Server. |
Politique recommandée
- Activez la sauvegarde cloud automatique et téléchargez une sauvegarde locale après chaque changement significatif. Rangez-la dans votre stockage de sauvegarde, chiffrée, avec une rétention d’au moins 90 jours.
- Les sauvegardes cloud dépendent du compte propriétaire : un compte d’entreprise sous MFA, jamais le compte personnel d’un technicien.
- Testez une restauration une fois par an sur une console de laboratoire, en restauration partielle si besoin (option « Restore All Applications and Settings » décochée).
Migrer vers une nouvelle console
- 01
Sur l’ancienne console : sauvegarde locale téléchargée (Settings > Control Plane > Backups).
- 02
Remplacez la console en laissant le réseau en aval inchangé. Pour un autre modèle, la nouvelle console doit être en UniFi OS 3.1 ou plus récent.
- 03
Restaurez la sauvegarde pendant l’assistant d’installation ou ensuite depuis Backups.
- 04
Depuis un ancien Network Server : sauvegarde .unf, installation de UniFi OS Server (l’installeur Windows et macOS propose la migration automatique), restauration, puis « Forget » des équipements sur l’ancienne instance une fois tout en ligne. Si les équipements avaient été adoptés en couche 3 (DNS, option DHCP 43), activez « Override Inform Host » sur l’ancienne application avec l’IP de la nouvelle.
03 / Exploitation
Politique de mise à jour
Les mises à jour se pilotent depuis l’Update Manager de Site Manager ou, console par console, dans Settings > Control Plane > Updates : canal (Official ou Early Access) et mises à jour automatiques. Les firmwares des équipements se règlent dans l’application Network. Ubiquiti recommande d’activer les mises à jour automatiques ; en environnement professionnel, nous les encadrons ainsi :
| Composant | Canal | Mode | Fenêtre |
|---|---|---|---|
| UniFi OS (console) | Official | Manuel, après validation sur un site pilote | Mensuelle, hors heures ouvrées |
| Application Network | Official | Manuel, décalé de 2 à 4 semaines après publication | Idem, après lecture de la note de version |
| Firmwares AP et switchs | Official | Automatique planifié la nuit, ou manuel par lots | Hebdomadaire ou mensuelle |
| Site pilote ou labo | Official (Early Access réservé au labo) | Manuel | Dès publication |
- Lisez la note de version avant chaque mise à jour majeure. Exemple concret : Network 11.0.97 exige UniFi OS 6.0, retire les USG et Network Server, migre de force vers le pare-feu par zones et efface l’historique des statistiques. Selon l’équipe UI sur la note de version, UniFi OS 6.0 est déjà en canal stable sur les Cloud Keys et suivra sur les autres consoles.
- Early Access s’active d’abord sur le compte UI, puis par site : à réserver au laboratoire, jamais en production.
- Mise à jour par SSH : Ubiquiti précise que ce n’est pas un processus officiellement supporté et qu’il ne doit être utilisé qu’à la demande du support.
- Échec de mise à jour : vérifiez l’accès Internet de la console, le DNS et les ports UDP 53 et 123.
- Network Server auto-hébergé : ses mises à jour se lancent toujours à la main, raison de plus pour migrer vers UniFi OS Server.
04 / Supervision
Journaux, SIEM et CEF
UniFi produit deux types de traces : les journaux système (connexions de clients, WAN, PoE, sécurité, actions d’administration) et les Traffic Flows (sessions passées par la passerelle).
Journaux système vers le SIEM
- 01
Dans Integration > System Logging / SIEM, choisissez SIEM Server comme destination.
- 02
Sélectionnez les catégories : Security (pare-feu, honeypot, IPS) et System (activité des administrateurs, équipements, VPN) au minimum ; Monitoring si vous suivez les connexions des clients.
- 03
Saisissez l’adresse IP et le port du collecteur syslog ou du SIEM. Tous les journaux sont exportés au format CEF.
- 04
Activez en parallèle l’Alarm Manager (push, e-mail, webhook GET ou POST) pour les événements qui exigent une réaction immédiate : WAN en panne, équipement hors ligne, détection IPS.
Format documenté par Ubiquiti : CEF:Version|Device Vendor|Device Product|Device Version|Device Event Class ID|Name|Severity|[Extension]. Exemple tiré de la documentation (événement d’accès administrateur) :
CEF:0|Ubiquiti|UniFi Network|9.3.33|544|Admin Accessed UniFi Network|1|UNIFIcategory=System UNIFIsubCategory=Admin UNIFIhost=Office UDM Pro UNIFIaccessMethod=web UNIFIadmin=Craig src=105.5.138.59 msg=Craig accessed UniFi Network using the web. Source IP: 105.5.138.59Côté SIEM, les champs UNIFIcategory, UNIFIadmin et src suffisent pour une première règle de corrélation : connexion administrateur hors heures ouvrées ou depuis une IP inconnue.
Traffic Flows
Les Traffic Flows s’exportent en CSV (Insights > Flows) ou en NetFlow (IPFIX) échantillonné vers un collecteur (Settings > CyberSecure > Traffic Logging). Ubiquiti indique que l’export des journaux de trafic vers un SIEM arrivera dans une version future : à ce jour, seuls les journaux système partent en CEF. La rétention locale est limitée (de l’ordre de 10 000 flux sur un UDM Pro ou un UCG Max sans stockage ajouté, 500 000 sur un UDM SE, 10 millions sur un EFG) : pour une exigence de conservation, l’export est indispensable. Network 11.0 ajoute une option « Flows Logging » directement dans les politiques de pare-feu.
05 / Automatisation
L’API UniFi Network
L’API UniFi Network officielle (dite « Integration API ») est servie par l’application Network elle-même. La référence 10.6.106 publie deux URL de base :
| Mode | URL de base | Clé d’API |
|---|---|---|
| Local | https://<console>/proxy/network/integration | Créée sur la console : section Integrations, « Create New API Key » |
| Distant (Cloud Connector) | https://api.ui.com/v1/connector/consoles/<consoleId>/proxy/network/integration | Créée dans Site Manager : Settings > API Keys |
- Authentification : la clé passe dans l’en-tête
X-API-KEY(l’exemple officiel l’écritX-API-Key, les noms d’en-tête HTTP ne tenant pas compte de la casse). La clé n’est affichée qu’une fois et reste liée au compte ou à l’organisation qui l’a créée. - Lecture :
GET /v1/info(version de l’application),GET /v1/sites(sites, dont l’ID sert à tous les autres appels),GET /v1/sites/{siteId}/devices,/clients(appareils et connexions VPN actives),/networks,/firewall/zones,/firewall/policies. - Pagination :
offset(0 par défaut) etlimit(25 par défaut, 200 au maximum). La réponse portecountettotalCount. - Filtrage : paramètre
filteravec une syntaxe structurée, par exemplename.like('guest*'). - Erreurs : objet JSON avec
statusCode,statusName,code(par exempleapi.authentication.missing-credentials) etmessage.
Premier test en lecture seule, sous PowerShell 7 (console à certificat auto-signé) :
# Read-only: returns the UniFi Network application version
$key = Read-Host -AsSecureString -Prompt 'UniFi API key'
$plain = [System.Net.NetworkCredential]::new('', $key).Password
Invoke-RestMethod -Uri 'https://192.168.1.1/proxy/network/integration/v1/info' `
-Headers @{ 'X-API-Key' = $plain; 'Accept' = 'application/json' } `
-SkipCertificateCheck
Remove-Variable plainMicrosoft rappelle que -SkipCertificateCheck (disponible depuis PowerShell 6.0.0) désactive toute validation de certificat et n’est destiné qu’aux hôtes connus à certificat auto-signé. La bonne pratique reste d’installer sur la console un certificat émis par votre PKI interne ; Ubiquiti permet d’importer un certificat dans les réglages de la console (Control Plane > Console > Certificates sur UniFi OS Server).
06 / Script
Inventaire en lecture seule : Get-UniFiInventory.ps1
Le script Get-UniFiInventory.ps1 produit un inventaire CSV des sites, équipements (modèle, état, IP, firmware, mise à jour disponible), clients connectés, réseaux et, en option, zones et politiques de pare-feu. Il n’envoie que des requêtes GET vers les points d’accès documentés, suit la pagination jusqu’au totalCount, réessaie sur une réponse HTTP 429 et fonctionne en local comme via le Cloud Connector.
- Compatible PowerShell 7 et Windows PowerShell 5.1. Sous PowerShell 7,
-SkipCertificateCheckest passé àInvoke-RestMethod; sous 5.1, le script installe temporairement un rappel de validation de certificat .NET et restaure l’ancien à la fin. - La clé est lue en
SecureString(paramètre, variable d’environnementUNIFI_API_KEYou saisie), jamais écrite sur disque ni affichée. - Un fichier CSV par type d’objet, horodaté, en UTF-8.
<#
.SYNOPSIS
Read-only inventory of a UniFi Network application through the official
UniFi Network Integration API (sites, devices, clients, networks and,
optionally, firewall zones and policies). Exports one CSV per object type.
.DESCRIPTION
The script only sends HTTP GET requests to the documented endpoints of the
UniFi Network API (developer.ui.com, Network API v10.6.106):
GET /v1/info
GET /v1/sites
GET /v1/sites/{siteId}/devices
GET /v1/sites/{siteId}/clients
GET /v1/sites/{siteId}/networks
GET /v1/sites/{siteId}/firewall/zones (with -IncludeFirewall)
GET /v1/sites/{siteId}/firewall/policies (with -IncludeFirewall)
It never creates, updates or deletes anything on the console.
Two connection modes are supported, matching the two server URLs published
in the official OpenAPI specification:
- Local : https://<ConsoleHost>/proxy/network/integration
- Remote : https://api.ui.com/v1/connector/consoles/<ConsoleId>/proxy/network/integration
Authentication uses an API key sent in the X-API-Key header. For the local
mode, create the key in the Integrations section of the local UniFi Network
application; for the remote mode, use a key created in UniFi Site Manager.
Results are paginated by the API (offset/limit, limit max 200); the script
follows totalCount until every item has been read.
.PARAMETER ConsoleHost
IP address or FQDN of the UniFi console for the local mode, optionally with
a port (for example 192.168.1.1 or unifi.example.local:443).
.PARAMETER ConsoleId
Console ID for the remote mode through the Site Manager Cloud Connector.
.PARAMETER ApiKey
API key as a SecureString. If omitted, the script reads the environment
variable UNIFI_API_KEY, then prompts for the key.
.PARAMETER OutputDirectory
Folder for the CSV files. Created if missing. Defaults to the current folder.
.PARAMETER PageSize
Number of items requested per page (1 to 200). Defaults to 200.
.PARAMETER IncludeFirewall
Also exports firewall zones and firewall policies (read-only GET calls).
.PARAMETER SkipCertificateCheck
Accepts the self-signed certificate of a local console. Use only on a
trusted management network. On PowerShell 7 this maps to the
-SkipCertificateCheck parameter of Invoke-RestMethod; on Windows
PowerShell 5.1 a temporary certificate validation callback is used and the
previous callback is restored when the script ends.
.EXAMPLE
$key = Read-Host -AsSecureString -Prompt 'UniFi API key'
.\Get-UniFiInventory.ps1 -ConsoleHost 192.168.1.1 -ApiKey $key -SkipCertificateCheck -OutputDirectory C:\Audit\UniFi
.EXAMPLE
$env:UNIFI_API_KEY = '<key>' # session only, do not store in scripts
.\Get-UniFiInventory.ps1 -ConsoleId '<console-id>' -IncludeFirewall
.NOTES
Version : 1.0 (2026-10-26)
Target : UniFi Network API as documented for UniFi Network 10.6.106 on developer.ui.com
Runtime : Windows PowerShell 5.1 and PowerShell 7.x
Status : parsed and checked with PSScriptAnalyzer; not executed against a
UniFi console by the author. Test it on a lab site first.
Read-only: GET requests only.
Source: ANYSYS ICT, https://www.anysys.be/articles/
#>
[CmdletBinding(DefaultParameterSetName = 'Local')]
param(
[Parameter(Mandatory = $true, ParameterSetName = 'Local')]
[ValidateNotNullOrEmpty()]
[string]$ConsoleHost,
[Parameter(Mandatory = $true, ParameterSetName = 'Remote')]
[ValidateNotNullOrEmpty()]
[string]$ConsoleId,
[System.Security.SecureString]$ApiKey,
[string]$OutputDirectory = (Get-Location).Path,
[ValidateRange(1, 200)]
[int]$PageSize = 200,
[switch]$IncludeFirewall,
[switch]$SkipCertificateCheck
)
Set-StrictMode -Version 2.0
$ErrorActionPreference = 'Stop'
# ---------------------------------------------------------------------------
# Resolve the API key (parameter, then environment variable, then prompt)
# ---------------------------------------------------------------------------
if (-not $ApiKey) {
if ($env:UNIFI_API_KEY) {
$ApiKey = New-Object System.Security.SecureString
foreach ($ch in $env:UNIFI_API_KEY.ToCharArray()) { $ApiKey.AppendChar($ch) }
$ApiKey.MakeReadOnly()
}
else {
$ApiKey = Read-Host -AsSecureString -Prompt 'UniFi API key'
}
}
function ConvertTo-PlainText {
param([Parameter(Mandatory = $true)][System.Security.SecureString]$Secure)
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Secure)
try { return [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) }
finally { [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) }
}
# ---------------------------------------------------------------------------
# Base URL (both forms come from the "servers" section of the OpenAPI spec)
# ---------------------------------------------------------------------------
if ($PSCmdlet.ParameterSetName -eq 'Local') {
$baseUrl = 'https://{0}/proxy/network/integration' -f $ConsoleHost.TrimEnd('/')
$target = $ConsoleHost
}
else {
$baseUrl = 'https://api.ui.com/v1/connector/consoles/{0}/proxy/network/integration' -f $ConsoleId
$target = "console $ConsoleId (Cloud Connector)"
}
$isCore = $PSVersionTable.PSEdition -eq 'Core'
$pageLimit = $PageSize
$previousCallback = $null
$previousProtocol = $null
if (-not $isCore) {
# Windows PowerShell 5.1: make sure TLS 1.2 is offered
$previousProtocol = [System.Net.ServicePointManager]::SecurityProtocol
[System.Net.ServicePointManager]::SecurityProtocol = $previousProtocol -bor [System.Net.SecurityProtocolType]::Tls12
if ($SkipCertificateCheck) {
$previousCallback = [System.Net.ServicePointManager]::ServerCertificateValidationCallback
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
}
}
function Invoke-UniFiGet {
<# Sends one GET request with the API key header; retries on HTTP 429. #>
param(
[Parameter(Mandatory = $true)][string]$Uri,
[Parameter(Mandatory = $true)][hashtable]$Headers
)
$params = @{ Uri = $Uri; Method = 'Get'; Headers = $Headers; ErrorAction = 'Stop' }
if ($isCore -and $SkipCertificateCheck) { $params['SkipCertificateCheck'] = $true }
for ($attempt = 1; $attempt -le 3; $attempt++) {
try {
return Invoke-RestMethod @params
}
catch {
$status = $null
$retryAfter = 5
$response = Get-PropertyValue $_.Exception 'Response'
if ($response) {
$status = [int]$response.StatusCode
try {
if ($isCore) {
# HttpResponseMessage (PowerShell 7)
$delta = $response.Headers.RetryAfter.Delta
if ($delta) { $retryAfter = [int][Math]::Ceiling($delta.TotalSeconds) }
}
else {
# HttpWebResponse (Windows PowerShell 5.1)
$ra = $response.Headers['Retry-After']
if ($ra) { $retryAfter = [int]("$ra".Trim()) }
}
}
catch { Write-Verbose 'No usable Retry-After header.' }
}
if ($status -eq 429 -and $attempt -lt 3) {
Write-Warning "HTTP 429 on $Uri, waiting $retryAfter s (attempt $attempt of 3)."
Start-Sleep -Seconds $retryAfter
continue
}
$hint = switch ($status) {
401 { 'API key missing or invalid.' }
403 { 'API key valid but not allowed for this resource.' }
404 { 'Endpoint not found: check the console address, the connection mode and the Network version.' }
default { 'See the error message below.' }
}
throw "GET $Uri failed (HTTP $status). $hint $($_.Exception.Message)"
}
}
}
function Get-UniFiPagedItem {
<# Reads every page of a list endpoint (offset/limit/totalCount). #>
param(
[Parameter(Mandatory = $true)][string]$Path,
[Parameter(Mandatory = $true)][hashtable]$Headers
)
$items = New-Object System.Collections.Generic.List[object]
$offset = 0
do {
$uri = '{0}{1}?offset={2}&limit={3}' -f $baseUrl, $Path, $offset, $pageLimit
$page = Invoke-UniFiGet -Uri $uri -Headers $Headers
foreach ($item in @($page.data)) { $items.Add($item) }
$count = [int]$page.count
$total = [int64]$page.totalCount
$offset += $count
Write-Verbose ("{0}: {1}/{2}" -f $Path, $offset, $total)
} while ($count -gt 0 -and $offset -lt $total)
return , $items.ToArray()
}
function Get-PropertyValue {
<# Returns a property value or $null when the property is absent (StrictMode safe). #>
param($InputObject, [Parameter(Mandatory = $true)][string]$Name)
if ($null -eq $InputObject) { return $null }
$prop = $InputObject.PSObject.Properties[$Name]
if ($prop) { return $prop.Value }
return $null
}
function ConvertTo-IsoText {
<# PowerShell 7 turns ISO 8601 strings into DateTime; keep a stable ISO text in the CSV. #>
param($Value)
if ($Value -is [datetime]) { return $Value.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') }
return $Value
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
$plainKey = ConvertTo-PlainText -Secure $ApiKey
$headers = @{ 'X-API-Key' = $plainKey; 'Accept' = 'application/json' }
try {
if (-not (Test-Path -LiteralPath $OutputDirectory)) {
New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null
}
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$info = Invoke-UniFiGet -Uri ($baseUrl + '/v1/info') -Headers $headers
$appVersion = Get-PropertyValue $info 'applicationVersion'
Write-Host ("UniFi Network application {0} on {1}" -f $appVersion, $target)
$sites = Get-UniFiPagedItem -Path '/v1/sites' -Headers $headers
$siteRows = New-Object System.Collections.Generic.List[object]
$deviceRows = New-Object System.Collections.Generic.List[object]
$clientRows = New-Object System.Collections.Generic.List[object]
$networkRows = New-Object System.Collections.Generic.List[object]
$zoneRows = New-Object System.Collections.Generic.List[object]
$policyRows = New-Object System.Collections.Generic.List[object]
foreach ($site in $sites) {
$siteId = $site.id
$siteName = $site.name
Write-Host "Site: $siteName ($siteId)"
$devices = Get-UniFiPagedItem -Path "/v1/sites/$siteId/devices" -Headers $headers
$deviceNames = @{}
foreach ($d in $devices) {
$deviceNames[[string]$d.id] = $d.name
$deviceRows.Add([pscustomobject]@{
Site = $siteName
Name = $d.name
Model = $d.model
State = $d.state
IPAddress = Get-PropertyValue $d 'ipAddress'
MACAddress = Get-PropertyValue $d 'macAddress'
FirmwareVersion = Get-PropertyValue $d 'firmwareVersion'
FirmwareUpdatable = Get-PropertyValue $d 'firmwareUpdatable'
Features = (@(Get-PropertyValue $d 'features') -join ';')
Supported = Get-PropertyValue $d 'supported'
DeviceId = $d.id
})
}
$clients = Get-UniFiPagedItem -Path "/v1/sites/$siteId/clients" -Headers $headers
foreach ($c in $clients) {
$uplinkId = [string](Get-PropertyValue $c 'uplinkDeviceId')
$uplinkName = $null
if ($uplinkId -and $deviceNames.ContainsKey($uplinkId)) { $uplinkName = $deviceNames[$uplinkId] }
$clientRows.Add([pscustomobject]@{
Site = $siteName
Name = Get-PropertyValue $c 'name'
Type = Get-PropertyValue $c 'type'
IPAddress = Get-PropertyValue $c 'ipAddress'
MACAddress = Get-PropertyValue $c 'macAddress'
ConnectedAt = ConvertTo-IsoText (Get-PropertyValue $c 'connectedAt')
UplinkName = $uplinkName
UplinkId = $uplinkId
ClientId = $c.id
})
}
$networks = Get-UniFiPagedItem -Path "/v1/sites/$siteId/networks" -Headers $headers
foreach ($n in $networks) {
$networkRows.Add([pscustomobject]@{
Site = $siteName
Name = $n.name
VlanId = Get-PropertyValue $n 'vlanId'
Management = Get-PropertyValue $n 'management'
Enabled = Get-PropertyValue $n 'enabled'
Default = Get-PropertyValue $n 'default'
ZoneId = Get-PropertyValue $n 'zoneId'
NetworkId = $n.id
})
}
if ($IncludeFirewall) {
$zones = Get-UniFiPagedItem -Path "/v1/sites/$siteId/firewall/zones" -Headers $headers
$zoneNames = @{}
foreach ($z in $zones) {
$zoneNames[[string]$z.id] = $z.name
$zoneRows.Add([pscustomobject]@{
Site = $siteName
Zone = $z.name
Origin = Get-PropertyValue (Get-PropertyValue $z 'metadata') 'origin'
NetworkIds = (@(Get-PropertyValue $z 'networkIds') -join ';')
ZoneId = $z.id
})
}
$policies = Get-UniFiPagedItem -Path "/v1/sites/$siteId/firewall/policies" -Headers $headers
foreach ($p in $policies) {
$srcZone = [string](Get-PropertyValue (Get-PropertyValue $p 'source') 'zoneId')
$dstZone = [string](Get-PropertyValue (Get-PropertyValue $p 'destination') 'zoneId')
$policyRows.Add([pscustomobject]@{
Site = $siteName
Index = Get-PropertyValue $p 'index'
Name = Get-PropertyValue $p 'name'
Enabled = Get-PropertyValue $p 'enabled'
Action = Get-PropertyValue (Get-PropertyValue $p 'action') 'type'
SourceZone = $(if ($zoneNames.ContainsKey($srcZone)) { $zoneNames[$srcZone] } else { $srcZone })
DestinationZone = $(if ($zoneNames.ContainsKey($dstZone)) { $zoneNames[$dstZone] } else { $dstZone })
LoggingEnabled = Get-PropertyValue $p 'loggingEnabled'
Origin = Get-PropertyValue (Get-PropertyValue $p 'metadata') 'origin'
PolicyId = $p.id
})
}
}
$siteRows.Add([pscustomobject]@{
Site = $siteName
InternalReference = Get-PropertyValue $site 'internalReference'
Devices = @($devices).Count
DevicesOffline = @($devices | Where-Object { $_.state -ne 'ONLINE' }).Count
FirmwareUpdatable = @($devices | Where-Object { (Get-PropertyValue $_ 'firmwareUpdatable') -eq $true }).Count
ConnectedClients = @($clients).Count
Networks = @($networks).Count
ApplicationVersion = $appVersion
SiteId = $siteId
})
}
$exports = [ordered]@{
'sites' = $siteRows
'devices' = $deviceRows
'clients' = $clientRows
'networks' = $networkRows
}
if ($IncludeFirewall) {
$exports['firewall-zones'] = $zoneRows
$exports['firewall-policies'] = $policyRows
}
foreach ($name in $exports.Keys) {
$file = Join-Path $OutputDirectory ("unifi-{0}-{1}.csv" -f $name, $stamp)
$rows = $exports[$name].ToArray()
$rows | Export-Csv -LiteralPath $file -NoTypeInformation -Encoding UTF8
Write-Host ("{0,-18} {1,6} rows -> {2}" -f $name, $rows.Length, $file)
}
$siteRows | Format-Table Site, Devices, DevicesOffline, FirmwareUpdatable, ConnectedClients, Networks -AutoSize
}
finally {
$plainKey = $null
$headers = $null
if (-not $isCore) {
if ($SkipCertificateCheck) {
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $previousCallback
}
if ($null -ne $previousProtocol) {
[System.Net.ServicePointManager]::SecurityProtocol = $previousProtocol
}
}
}# Read-only inventory of a local console with a self-signed certificate
$key = Read-Host -AsSecureString -Prompt 'UniFi API key'
.\Get-UniFiInventory.ps1 -ConsoleHost 192.168.1.1 -ApiKey $key -SkipCertificateCheck `
-IncludeFirewall -OutputDirectory 'D:\Audit\UniFi'
# Same through the Site Manager Cloud Connector (key created in Site Manager)
.\Get-UniFiInventory.ps1 -ConsoleId '<console-id>' -ApiKey $key -OutputDirectory 'D:\Audit\UniFi'Exemple de sortie (illustratif) :
UniFi Network application 10.6.109 on 192.168.1.1
Site: Siege (5f1c...)
sites 1 rows -> D:\Audit\UniFi\unifi-sites-20261026-101500.csv
devices 24 rows -> D:\Audit\UniFi\unifi-devices-20261026-101500.csv
clients 187 rows -> D:\Audit\UniFi\unifi-clients-20261026-101500.csv
networks 7 rows -> D:\Audit\UniFi\unifi-networks-20261026-101500.csvUsages typiques : rapport mensuel des équipements hors ligne ou en attente de firmware, inventaire pour l’assurance cyber, comparaison des réseaux et des zones avec la documentation de conception.
07 / Pièges
Pièges
- Sauvegarde jamais restaurée : une sauvegarde non testée n’est qu’une hypothèse. Planifiez un test annuel.
- Compte propriétaire unique : il porte les sauvegardes cloud, le SD-WAN et les abonnements. Sa perte bloque tout : compte d’entreprise, MFA, procédure de récupération documentée.
- Mise à jour majeure en production le jour de sa sortie : la 11.0.97 a été publiée en déploiement progressif et exige un UniFi OS 6.0 pas encore stable sur toutes les consoles. Attendez, testez, puis déployez.
- Clé d’API dans un script ou une tâche planifiée en clair : utilisez un coffre (SecretManagement, Credential Manager, coffre de mots de passe) et un compte de service dédié.
- Port de l’API sur UniFi OS Server : l’URL locale documentée ne précise pas de port ; si votre instance écoute sur un port non standard, indiquez-le dans
-ConsoleHost(hôte:port). À vérifier dans la documentation locale de votre version (Integrations). - SIEM incomplet : les journaux de trafic ne partent pas encore en CEF ; si vous en avez besoin, NetFlow/IPFIX ou l’export CSV sont les seules voies documentées.
08 / Contrôle
Vérification
- 01
Sauvegarde cloud automatique active et dernière sauvegarde datée de moins de 7 jours ; sauvegarde locale présente dans le stockage de sauvegarde.
- 02
Restauration testée sur une console de laboratoire, avec procès-verbal.
- 03
Canaux de mise à jour sur Official, mises à jour automatiques conformes à la politique, site pilote identifié.
- 04
SIEM : réception d’un événement CEF de test (connexion administrateur), règle d’alerte déclenchée.
- 05
Script d’inventaire : exécuté avec succès, CSV archivés, écarts avec la documentation traités.
09 / Références
Sources
- Ubiquiti : sauvegardes et migration
- Ubiquiti : mises à jour UniFi
- Ubiquiti : Early Access
- Ubiquiti : guide de mise à jour avancée
- Ubiquiti : journaux système, SIEM et CEF
- Ubiquiti : Traffic Flows
- Ubiquiti : démarrer avec l’API officielle
- Ubiquiti Developer : Network API 10.6.106, démarrage
- Ubiquiti Developer : spécification OpenAPI 10.6.106
- Ubiquiti Developer : filtrage
- Ubiquiti Developer : gestion des erreurs
- Ubiquiti : note de version UniFi Network 11.0.97
- Microsoft : Invoke-RestMethod
- Microsoft : Export-Csv