Asset export and Veeam adapters
Manual · API and availability · Set up data sources · Ingest reference
These push adapters belong to the extension after v1.25.0. On an instance with this extension, download the adapter package under Settings > API access (/settings/api-keys/adapters.zip). It contains push.mjs, asset-export.mjs, Export-VeeamSessions.ps1 and German and English guides. Configure the source, keys and bindings before sending data.
Which tool does what?
| Tool | Purpose and limits |
|---|---|
| Windows Inventory Collector | Reads the individual computer on which it runs, collects additional details through a local form and writes inventory JSON. No network discovery or recurring push service. |
asset-export.mjs |
Converts a normalised asset export into an ingest batch. Does not query Checkmk, Jamf or other vendors itself. |
Export-VeeamSessions.ps1 |
Reads completed VM backup sessions using Get-VBRBackupSession and creates a delta batch. |
push.mjs |
Sends a persisted batch over HTTPS with an adapter key and writes a receipt. |
Windows Inventory Collector
Download the collector under Assets > Inventory computer or Settings > API access and run it on the target computer. It reads OS, hardware, networking, installed software, services, open ports and security status. Without elevated permissions, details such as BitLocker and Secure Boot remain incomplete.
The script does not transmit data to ISMS Lite. Its JSON file supports guided asset creation through an API/MCP client. Its structure differs from the normalised multi-device export accepted by asset-export.mjs. For recurring synchronisation from an existing inventory system, use the following workflow.
Prepare a normalised asset export
The adapter machine needs Node.js 22 or later; the two .mjs examples require no additional npm packages. A customer-side query reads the agreed coverage from the source and writes, for example, export.json:
{
"observedAt": "2026-09-19T08:00:00Z",
"coverage": "site-a-managed-assets",
"complete": true,
"assets": [
{
"externalId": "device-123",
"name": "srv-01",
"location": "Site A",
"ip_address": "10.0.0.10",
"os_platform": "Linux"
}
]
}
Replace observedAt with the actual collection time. Keep externalId stable across renaming and IP changes. coverage must exactly match the configured source. complete: true creates a full snapshot; use it only after successfully reading every page. false creates a delta batch.
node ./asset-export.mjs export.json pending.json 1
The final number is the current source revision. The generator creates a batch ID and refuses to overwrite an existing output file. It transfers technical asset fields, not domain decisions about ownership, criticality or RPO. Its asset deliveries contain no compliance observations; a custom adapter must add them according to the ingest contract.
Send a batch
$env:ISMS_URL = 'https://isms.example.org'
$env:ISMS_SOURCE_ID = 'UUID-OF-SOURCE'
# ISMS_API_KEY comes from the task's protected environment.
node ./push.mjs pending.json
ISMS_URL must be the instance's HTTPS origin without an API path, user information or query. The sender does not follow redirects. Success creates pending.json.receipt.json with the server response. Only then archive the input file and generate a new batch.
After a lost response, resend the same file. Do not regenerate the export and batch ID every time: only the same ID and content can be retried idempotently. The sender makes at most five attempts on transport errors, 429 and server errors, with delays and a 30-second timeout per attempt. Other errors require correction. The error reference explains typical conflicts.
JSON files and receipts contain operational data. Restrict access to the task user, keep keys out of files, prevent overlapping tasks and remove completed files according to local retention policy. This does not remove remote evidence history.
Export Veeam sessions
The script requires PowerShell 5.1 or later and a PowerShell environment appropriate to the Veeam installation.
The example uses Get-VBRBackupSession in an already authenticated Veeam PowerShell session inside the customer network. The Veeam cmdlet reference describes VM backup sessions. Check product variant, version, cmdlet availability, permissions and returned fields before use. The example was checked with fixtures; compatibility with every Veeam installation is not guaranteed. Other workloads and Veeam for Microsoft 365 need their own mappings.
- Configure a source with
objectKind: "backup_job"andcreateAssets: null. - Create ISMS backup jobs and bind their IDs to stable Veeam job IDs, using
managedFields: []. - Set
rules.backupFailuresfor failure evaluation, for example2for two consecutive failures. - Export with read-only Veeam access. Replace job ID, coverage and revision in the example.
./Export-VeeamSessions.ps1 -JobIds 'UUID-OF-VEEAM-JOB' `
-Coverage 'veeam-vm-jobs' -SourceRevision 1 -OutputPath pending.json
node ./push.mjs pending.json
Set the environment variables as above before sending. Export and delivery may run on separate computers; the Veeam machine then does not need Node.js. Transfer the file securely to the delivery machine.
| Veeam data | Ingest meaning |
|---|---|
Only sessions with State: Stopped |
Completed session is included |
Result: Success |
backup_run with passed |
Result: Failed |
backup_run with failed |
| Warning or another result | unknown |
| Session ID | Stable event ID |
| Session end | Observation time of the result |
By default the example reads an overlapping seven-day window (LookbackHours: 168); a result remains valid until 48 hours after session end (ValidHours: 48). Choose these values for the backup frequency. Do not change the validity of an already delivered event while retaining its event ID.
More than 20 sessions per job produces an error rather than silent truncation. The window must cover late sessions. For larger histories, implement a custom adapter with several delta batches. The Veeam export always sends delta and therefore does not detect disappeared jobs.
Complete PowerShell example
The following code matches Export-VeeamSessions.ps1 from the adapter package. Save it as a UTF-8 file under that name and run it using the command above. An already authenticated Veeam PowerShell session is still required. The export writes only pending.json; push.mjs from the same package then handles HTTPS delivery.
#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 is only for offline testing with prepared fixtures. Omit it when using Veeam so the script calls Get-VBRBackupSession.
Map RPO and SureBackup separately
A successful job proves neither a usable restore point nor a successful recovery test.
- RPO: An asset source needs
backup_pointwithpassed, the actually reported usablerestorePointAtand a justified validity period. Configure the RPO on the ISMS asset. A job source alone cannot provide this asset assessment. - Restore/SureBackup: Deliver an actual test report as
restore_testwith result and validity. Missing or expired evidence remainsunknown. - Domain runs and test completion: Use the backup domain API. Ingest observations do not automatically complete these workflows.
These additional vendor mappings must be developed against the installed version and actual data, then checked in a pilot. They are not part of the session example.
Other vendors and directories
| Source | Possible adapter content |
|---|---|
| Checkmk, Jamf | Stable device IDs and selected asset fields; explicitly assessed compliance as device_compliance |
| Portnox | Mapped device status or substantiated compliance observations |
| Unimus | Configuration backup result and reference as config_backup, excluding configuration files and secrets |
| Microsoft Entra ID / Microsoft 365 | Selected asset/compliance evidence from a customer-side query, when mapped to a supported target record |
These are possible mappings, not supplied direct connectors. Implement vendor retrieval, permissions, pagination and assessment in the customer-side adapter. Report unknown results as unknown, not success.
Built-in Entra sign-in and AD/Entra group integration are separate features; see Groups and Settings. The push channel does not provision users or groups and does not replace directory configuration.