Adapter für Assetexport und Veeam
Handbuch · API und Verfügbarkeit · Datenquellen einrichten · Ingest-Referenz
Die hier beschriebenen Push-Adapter gehören zur Erweiterung nach v1.25.0. Auf einer Instanz mit dieser Erweiterung unter Einstellungen > API-Zugänge das Adapter-Paket herunterladen (/settings/api-keys/adapters.zip). Enthalten sind push.mjs, asset-export.mjs, Export-VeeamSessions.ps1 und Anleitungen auf Deutsch und Englisch. Vor dem ersten Versand Quelle, Schlüssel und Zuordnungen einrichten.
Welches Werkzeug wofür?
| Werkzeug | Aufgabe und Grenze |
|---|---|
| Windows Inventory Collector | Erfasst den einzelnen Rechner, auf dem er gestartet wird, ergänzt Angaben über ein lokales Formular und schreibt Inventory-JSON. Keine Netzwerk-Discovery und kein regelmäßiger Push-Dienst. |
asset-export.mjs |
Wandelt einen normalisierten Assetexport in einen Ingest-Batch um. Fragt Checkmk, Jamf oder andere Hersteller nicht selbst ab. |
Export-VeeamSessions.ps1 |
Liest abgeschlossene VM-Backup-Sitzungen über Get-VBRBackupSession und erzeugt einen Delta-Batch. |
push.mjs |
Sendet einen gespeicherten Batch per HTTPS mit Adapter-Schlüssel und schreibt eine Quittung. |
Windows Inventory Collector
Der Collector ist unter Assets > Rechner inventarisieren und Einstellungen > API-Zugänge erhältlich. Auf dem Zielrechner ausführen. Er liest Betriebssystem, Hardware, Netzwerk, installierte Software, Dienste, offene Ports und Sicherheitsstatus. Ohne erhöhte Rechte bleiben beispielsweise BitLocker- und Secure-Boot-Angaben unvollständig.
Das Skript überträgt keine Daten an ISMS Lite. Seine JSON-Datei dient der geführten Asset-Anlage über einen API-/MCP-Client. Die Struktur ist nicht dieselbe wie der normalisierte Mehrgeräteexport für asset-export.mjs. Für laufende Synchronisation aus einem vorhandenen Inventarsystem den folgenden Ablauf verwenden.
Normalisierten Assetexport vorbereiten
Auf dem Adapter-Rechner wird Node.js 22 oder neuer benötigt; für die beiden .mjs-Beispiele sind keine zusätzlichen npm-Pakete erforderlich. Eine kundenseitige Abfrage liest den vereinbarten Bestand aus dem Quellsystem und schreibt beispielsweise export.json:
{
"observedAt": "2026-09-19T08:00:00Z",
"coverage": "site-a-managed-assets",
"complete": true,
"assets": [
{
"externalId": "device-123",
"name": "srv-01",
"location": "Standort A",
"ip_address": "10.0.0.10",
"os_platform": "Linux"
}
]
}
observedAt durch den tatsächlichen Erhebungszeitpunkt ersetzen. externalId muss bei Umbenennung oder IP-Wechsel gleich bleiben. coverage muss exakt zur eingerichteten Quelle passen. complete: true ergibt einen Vollabgleich; erst nach vollständigem erfolgreichen Abruf aller Seiten setzen. Mit false entsteht ein Delta-Batch.
node ./asset-export.mjs export.json pending.json 1
Die letzte Zahl ist die aktuelle Quellenrevision. Der Generator erzeugt eine Batch-ID und überschreibt keine vorhandene Ausgabedatei. Er überträgt die technischen Assetfelder, keine fachlichen Entscheidungen über Eigentümer, Kritikalität oder RPO. Seine Assetlieferungen enthalten keine Compliance-Beobachtungen; diese muss ein eigener Adapter nach dem Ingest-Vertrag ergänzen.
Batch versenden
$env:ISMS_URL = 'https://isms.example.org'
$env:ISMS_SOURCE_ID = 'UUID-DER-QUELLE'
# ISMS_API_KEY stammt aus der geschützten Umgebung des Tasks.
node ./push.mjs pending.json
ISMS_URL muss den HTTPS-Origin der Instanz ohne API-Pfad, Benutzerinformationen oder Query enthalten. Der Sender folgt keinen Weiterleitungen. Bei Erfolg entsteht pending.json.receipt.json mit der Serverantwort. Erst danach die Eingabedatei archivieren und einen neuen Batch erzeugen.
Bei einer verlorenen Antwort dieselbe Datei erneut senden. Nicht jedes Mal Export und Batch-ID neu erzeugen: Nur die Wiederholung derselben ID mit demselben Inhalt ist wiederholbar. Der Sender versucht bei Transportfehlern, 429 und Serverfehlern höchstens fünfmal zu senden, mit Wartezeit und 30 Sekunden Zeitlimit pro Versuch. Andere Fehler müssen behoben werden. Die Fehlerreferenz erklärt typische Konflikte.
JSON-Dateien und Quittungen enthalten Betriebsdaten. Zugriff auf den Task-Benutzer beschränken, Schlüssel nicht in Dateien eintragen, überlappende Tasks verhindern und erledigte Dateien nach der festgelegten lokalen Aufbewahrungsfrist entfernen. Die entfernte Nachweishistorie bleibt davon unberührt.
Veeam-Sitzungen exportieren
Das Skript setzt PowerShell 5.1 oder neuer und die zur Veeam-Installation passende PowerShell-Umgebung voraus.
Das Beispiel verwendet Get-VBRBackupSession in einer bereits authentifizierten Veeam-PowerShell-Sitzung im Kundennetz. Die Veeam-Cmdlet-Referenz beschreibt VM-Backup-Sitzungen. Die verwendete Veeam-Produktvariante, Version, Cmdlet-Verfügbarkeit, Rechte und Rückgabefelder vor Einsatz prüfen. Das mit Testdaten geprüfte Beispiel ist keine zugesagte Kompatibilität mit jeder Veeam-Installation. Andere Workloads und Veeam für Microsoft 365 benötigen eigene Zuordnungen.
- Eine Quelle mit
objectKind: "backup_job"undcreateAssets: nulleinrichten. - ISMS-Backup-Aufträge anlegen und deren IDs mit den stabilen Veeam-Job-IDs verbinden;
managedFields: []verwenden. - Für Fehlerauswertung in der Quelle
rules.backupFailuresfestlegen, beispielsweise2für zwei aufeinanderfolgende Fehler. - Mit einem lesenden Veeam-Zugang exportieren. Im Beispiel Job-ID, Coverage und Revision ersetzen.
./Export-VeeamSessions.ps1 -JobIds 'UUID-DES-VEEAM-JOBS' `
-Coverage 'veeam-vm-jobs' -SourceRevision 1 -OutputPath pending.json
node ./push.mjs pending.json
Vor dem Versand die Umgebungsvariablen wie oben setzen. Export und Versand können auf unterschiedlichen Rechnern laufen; dann benötigt der Veeam-Rechner kein Node.js. Die Datei geschützt zum Versand-Rechner übertragen.
| Veeam-Daten | Ingest-Bedeutung |
|---|---|
Nur Sitzung mit State: Stopped |
Abgeschlossene Sitzung wird berücksichtigt |
Result: Success |
backup_run mit passed |
Result: Failed |
backup_run mit failed |
| Warnung oder anderes Ergebnis | unknown |
| Sitzungs-ID | Stabile Ereignis-ID |
| Sitzungsende | Erhebungszeitpunkt des Ergebnisses |
Standardmäßig liest das Beispiel sieben Tage überlappend (LookbackHours: 168); ein Ergebnis gilt bis 48 Stunden nach Sitzungsende (ValidHours: 48). Diese Werte passend zur Backup-Frequenz wählen. Bereits gelieferte Ereignisse dürfen nicht durch geänderte Gültigkeit unter derselben Ereignis-ID umgeschrieben werden.
Mehr als 20 Sitzungen je Job führen zu einem Fehler, nicht zu stiller Kürzung. Das Zeitfenster muss verspätete Sitzungen erfassen. Bei größeren Historien einen eigenen Adapter mit mehreren Delta-Batches verwenden. Der Veeam-Export sendet immer Delta und erkennt damit keine verschwundenen Jobs.
Vollständiges PowerShell-Beispiel
Der folgende Code entspricht Export-VeeamSessions.ps1 aus dem Adapter-Paket. Unter diesem Namen als UTF-8-Datei speichern und mit dem oben gezeigten Aufruf ausführen. Voraussetzung bleibt eine bereits authentifizierte Veeam-PowerShell-Sitzung. Der Export schreibt nur pending.json; den HTTPS-Versand übernimmt anschließend push.mjs aus demselben Paket.
#requires -Version 5.1
[CmdletBinding()]
param(
[Parameter(Mandatory)][guid[]]$JobIds,
[Parameter(Mandatory)][string]$Coverage,
[Parameter(Mandatory)][ValidateRange(1, 2147483647)][int]$SourceRevision,
[Parameter(Mandatory)][string]$OutputPath,
[ValidateRange(1, 8760)][int]$ValidHours = 48,
[ValidateRange(1, 8760)][int]$LookbackHours = 168,
[string]$SessionsJson
)
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
if (Test-Path -LiteralPath $OutputPath) { throw 'Output exists. Deliver or resolve the pending batch before exporting again.' }
if ($JobIds.Count -gt 500) { throw 'At most 500 configured jobs are supported per source.' }
$observedAt = [DateTime]::UtcNow
if ($SessionsJson) {
$sessions = @(Get-Content -LiteralPath $SessionsJson -Raw | ConvertFrom-Json)
} else {
# Run inside an authenticated Veeam PowerShell session in the customer network.
$sessions = @(Get-VBRBackupSession -ErrorAction Stop)
}
$objects = @()
foreach ($jobId in ($JobIds | Select-Object -Unique)) {
$runs = @($sessions | Where-Object { [guid]$_.JobId -eq $jobId -and [string]$_.State -eq 'Stopped' } | Sort-Object EndTimeUTC -Descending)
$observations = @()
foreach ($run in $runs) {
# EndTimeUTC is explicitly UTC, including when Veeam returns DateTimeKind.Unspecified.
$end = [DateTime]::SpecifyKind([DateTime]$run.EndTimeUTC, [DateTimeKind]::Utc)
if ($end -lt $observedAt.AddHours(-$LookbackHours)) { continue }
if ($end -gt $observedAt) { throw 'Session timestamp is in the future.' }
$result = switch ([string]$run.Result) { 'Success' { 'passed' } 'Failed' { 'failed' } default { 'unknown' } }
$sessionId = ([guid]$run.Id).ToString()
$observations += @{
eventId = $sessionId; checkType = 'backup_run'; result = $result
observedAt = $end.ToString('o'); validUntil = $end.AddHours($ValidHours).ToString('o')
evidence = @{ summary = "Veeam session=$sessionId; result=$($run.Result)" }
}
}
# Never truncate history silently: split a large export into explicit delta batches.
if ($observations.Count -gt 20) { throw 'More than 20 sessions per job. Use a shorter overlap window or implement delta paging.' }
$objects += @{ externalId = $jobId.ToString(); observations = @($observations) }
}
if (($objects | ForEach-Object { $_.observations.Count } | Measure-Object -Sum).Sum -gt 1000) { throw 'More than 1000 observations. Split into delta batches.' }
$payload = @{
schemaVersion = 1; batchId = [guid]::NewGuid().ToString(); sourceRevision = $SourceRevision
coverage = $Coverage; mode = 'delta'; observedAt = $observedAt.ToString('o')
totalObjects = $objects.Count; objects = @($objects)
} | ConvertTo-Json -Depth 8
if ([Text.Encoding]::UTF8.GetByteCount($payload) -gt 1MB) { throw 'Batch exceeds 1 MiB.' }
$stream = [IO.File]::Open([IO.Path]::GetFullPath($OutputPath), [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
try {
$bytes = [Text.UTF8Encoding]::new($false).GetBytes($payload)
$stream.Write($bytes, 0, $bytes.Length)
} finally { $stream.Dispose() }
SessionsJson dient ausschließlich dem Offline-Test mit zuvor erstellten Testdaten. Im echten Veeam-Betrieb diesen Parameter weglassen, damit Get-VBRBackupSession verwendet wird.
RPO und SureBackup gesondert zuordnen
Ein erfolgreicher Job beweist weder einen verwendbaren Restore-Punkt noch einen erfolgreichen Wiederherstellungstest.
- RPO: Eine Assetquelle benötigt
backup_pointmitpassed, dem tatsächlich gemeldeten verwendbarenrestorePointAtund einer begründeten Gültigkeit. Das RPO wird am ISMS-Asset fachlich festgelegt. Eine Jobquelle allein liefert diese Assetbewertung nicht. - Restore/SureBackup: Einen tatsächlichen Testbericht als
restore_testmit Ergebnis und Gültigkeit liefern. Fehlende oder abgelaufene Nachweise bleibenunknown. - Fachliche Läufe und Testabschlüsse: Dafür die Backup-Fach-API verwenden. Ingest-Beobachtungen schließen diese Abläufe nicht automatisch ab.
Diese zusätzlichen Herstellerzuordnungen müssen anhand der eingesetzten Version und tatsächlicher Daten entwickelt und im Pilot geprüft werden; sie sind nicht Bestandteil des Sitzungsbeispiels.
Weitere Hersteller und Verzeichnisse
| Quelle | Möglicher Adapter-Inhalt |
|---|---|
| Checkmk, Jamf | Stabile Geräte-IDs und ausgewählte Assetdaten; ausdrücklich bewertete Compliance als device_compliance |
| Portnox | Zugeordneter Gerätestatus bzw. begründete Compliance-Beobachtungen |
| Unimus | Ergebnis und Referenz einer Konfigurationssicherung als config_backup, ohne Konfigurationsdatei oder Geheimnisse |
| Microsoft Entra ID / Microsoft 365 | Ausgewählte Asset-/Compliance-Nachweise aus einer kundenseitigen Abfrage, sofern einem unterstützten Zielobjekt zugeordnet |
Diese Tabelle beschreibt mögliche Zuordnungen, keine mitgelieferten Direktkonnektoren. Herstellerabruf, Rechte, Paging und Bewertung müssen im kundenseitigen Adapter implementiert werden. Unbekannte Ergebnisse als unknown liefern, nicht als Erfolg.
Die eingebaute Entra-Anmeldung und AD-/Entra-Gruppenanbindung sind davon getrennte Funktionen; siehe Gruppen und Einstellungen. Der Push-Kanal provisioniert keine Benutzer oder Gruppen und ersetzt keine Verzeichnis-Konfiguration.