Files
oc-sentinel/docs/attacktracer-ninja-v2-architecture.md
2026-07-17 00:39:28 +02:00

12 KiB

AttackTracer Ninja V2 Architecture

Goal

Build a lightweight but robust endpoint agent that:

  • runs on every monitored Windows device
  • reads local attack telemetry and optional local vulnerability exports
  • writes device-level NinjaOne custom fields locally
  • uploads signed JSON reports to a central n8n ingestion workflow
  • receives updates through NinjaOne tasks from GitLab-hosted releases

This design replaces:

  • the shared-folder aggregation model
  • the dedicated AttackTracerNinjaServer
  • organization-level field processing on an endpoint

Organization-wide correlation and NinjaOne organization API updates move to n8n.

Core principles

  1. Endpoint collection is local, central correlation is remote.
  2. Device custom field writes stay local through NinjaOne-supported endpoint mechanisms.
  3. Organization logic never depends on one central Windows server.
  4. Update delivery is controlled by NinjaOne, with release artifacts hosted in GitLab.
  5. Endpoint uploads are authenticated and tamper-evident.
  6. The central pipeline treats endpoint data as useful but never fully trusted.

1. Endpoint agent

Use a compiled Windows agent written in C#.

Responsibilities:

  • scan Windows Security/Application logs
  • parse supported local logs such as FTP/FileZilla
  • optionally ingest local exported vulnerability data
  • build normalized JSON report
  • print Ninja-style key/value status lines
  • expose a command for device-local execution from NinjaOne
  • upload signed report to n8n

Why compiled instead of PowerShell-only:

  • harder to casually tamper with than plain scripts
  • easier to sign
  • easier to version and hash-verify
  • simpler to protect internal protocol logic such as signing and replay prevention

2. Thin PowerShell deployment wrapper

Use PowerShell only for:

  • install
  • uninstall
  • update
  • scheduled execution wrapper
  • NinjaOne field publishing wrapper when needed

This keeps operational flexibility while protecting core collection logic inside a signed binary.

3. GitLab release channel

GitLab hosts:

  • release ZIP or installer
  • version manifest
  • SHA-256 checksum file
  • optional detached signature

Recommended files per release:

  • AttackTracerNinjaClient-win-x64.zip
  • version.json
  • AttackTracerNinjaClient-win-x64.zip.sha256
  • release-notes.md

4. n8n ingestion pipeline

n8n receives endpoint JSON through an authenticated webhook and performs:

  • signature validation
  • timestamp and replay validation
  • schema validation
  • persistence to Postgres
  • organization aggregation
  • NinjaOne organization field updates
  • optional notifications

5. Postgres as primary store

Postgres should be the system of record for incoming reports.

Recommended tables:

  • devices
  • device_reports
  • device_findings
  • device_vulnerability_findings
  • organization_rollups
  • ingestion_events

6. Optional Nextcloud archive

Nextcloud can be used for:

  • archived JSON bundles
  • generated HTML reports
  • long-term human-readable reports

Do not use it as the primary operational datastore.

Endpoint security model

Threat assumptions

Assume an attacker may:

  • modify files under the install directory
  • stop scheduled tasks or Ninja jobs
  • alter local logs
  • replay older JSON uploads
  • inspect locally stored configuration

Assume an attacker with full local admin or SYSTEM access can eventually subvert the endpoint. The architecture therefore aims to:

  • raise the effort of tampering
  • make tampering detectable
  • reduce blast radius of stolen secrets
  • preserve central evidence of missing or suspicious reporting

Required protections

Signed binaries

  • Sign the compiled agent executable.
  • Optionally sign the deployment PowerShell scripts.
  • The updater must verify Authenticode signature and expected hash before replacing files.

Protected local secrets

Do not embed one global master secret in all clients.

Use one of these approaches:

  • per-tenant ingest token wrapped with DPAPI on each machine
  • per-device secret provisioned during install and stored encrypted with DPAPI
  • short-lived signed enrollment flow if you later want stronger provisioning

Minimum recommendation:

  • store an n8n upload secret encrypted via DPAPI in a local config file readable only by SYSTEM/Administrators

Signed report uploads

Each report upload should include:

  • device identifier
  • report timestamp in UTC
  • monotonic nonce or GUID
  • client version
  • payload hash
  • HMAC signature over canonicalized request fields

Suggested headers:

  • X-ATN-Device
  • X-ATN-Timestamp
  • X-ATN-Nonce
  • X-ATN-Version
  • X-ATN-Signature

n8n must reject:

  • stale timestamps outside tolerance
  • duplicate nonce values
  • invalid HMAC signatures

Tamper evidence

The endpoint should include in its report:

  • installed client version
  • scanner execution start/end UTC
  • whether upload succeeded
  • hash of produced JSON payload
  • optional configuration version

n8n should track:

  • expected reporting cadence per device
  • missing devices
  • repeated version lag
  • repeated upload failures
  • sudden disappearance of formerly noisy devices

Least-privilege local behavior

  • install under C:\Program Files\AttackTracerNinja
  • write mutable state under C:\ProgramData\AttackTracerNinja
  • restrict config/log/state ACLs to SYSTEM and Administrators
  • avoid storing writable binaries under user-controlled locations

Update architecture

Distribution model

NinjaOne remains the deployment engine.

Recommended flow:

  1. Build signed release in CI.
  2. Publish release artifact to GitLab.
  3. Publish version.json with latest version metadata.
  4. NinjaOne scheduled update task runs on endpoints.
  5. Update task checks local version against GitLab manifest.
  6. If newer, download artifact, verify hash/signature, install, and record result.

Version manifest

Example version.json:

{
  "channel": "stable",
  "version": "2.0.0",
  "publishedAtUtc": "2026-07-16T18:00:00Z",
  "artifactUrl": "https://gitlab.example.com/group/project/-/releases/v2.0.0/downloads/AttackTracerNinjaClient-win-x64.zip",
  "sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
  "minUpdaterVersion": "1.0.0"
}

Endpoint update task

The NinjaOne update task should:

  • run as SYSTEM
  • read installed version
  • fetch version.json
  • compare versions
  • download ZIP to a temporary directory
  • verify SHA-256
  • verify Authenticode signature on executable
  • stop running agent if needed
  • replace files atomically
  • write update result to a local log

The update task should never install unsigned or hash-mismatched artifacts.

Runtime execution model

Recommended commands:

  • AttackTracerNinjaCli.exe scan
  • AttackTracerNinjaCli.exe scan --ninja-output
  • AttackTracerNinjaCli.exe upload --report <path>
  • AttackTracerNinjaCli.exe scan-and-upload

The PowerShell wrapper invoked by NinjaOne should typically run:

& "C:\Program Files\AttackTracerNinja\app\AttackTracerNinjaCli.exe" scan-and-upload --ninja-output

Wrapper responsibilities:

  • ensure paths exist
  • capture stdout/stderr to log
  • set NinjaOne device custom fields from the produced status
  • return a useful exit code for monitoring

Suggested data flow

  1. Endpoint agent scans local data.
  2. Agent writes a JSON report locally.
  3. Wrapper publishes device custom fields to NinjaOne.
  4. Agent signs and uploads the JSON report to n8n.
  5. n8n validates authenticity and freshness.
  6. n8n stores raw and normalized data in Postgres.
  7. n8n computes organization-level summaries.
  8. n8n updates NinjaOne organization fields through the API.
  9. Optional HTML and long-form artifacts are generated centrally.

n8n workflow design

Workflow A: ingest-device-report

Trigger:

  • Webhook

Steps:

  1. Validate required headers.
  2. Validate timestamp tolerance.
  3. Check nonce replay in Postgres.
  4. Recompute HMAC and compare.
  5. Validate JSON schema.
  6. Upsert device metadata.
  7. Insert raw report row.
  8. Insert findings rows.
  9. Mark ingestion success.

Failure handling:

  • log validation error
  • store rejected attempt metadata
  • optionally alert on repeated bad signatures

Workflow B: organization-rollup

Trigger:

  • Cron every 5 or 15 minutes

Steps:

  1. Query latest accepted report per device.
  2. Compute org status and summary.
  3. Detect stale devices and missing submissions.
  4. Update NinjaOne organization fields:
    • attacktracerorgstatus
    • attacktracerorgsummary
    • attacktracerorglastupdate
  5. Optionally generate HTML and archive it

Workflow C: stale-device-alerting

Trigger:

  • Cron

Logic:

  • find devices with no valid upload within expected interval
  • raise notification or ticket

Each JSON report should include:

{
  "schemaVersion": "2.0",
  "machineName": "WSUS",
  "deviceIdHint": "",
  "organizationHint": "",
  "generatedAtUtc": "2026-07-16T18:42:11Z",
  "clientVersion": "2.0.0",
  "lookbackDays": 7,
  "baseStatus": "ok",
  "alertState": "ok",
  "totalEvents": 0,
  "uniqueIpCount": 0,
  "errorCount": 0,
  "attackFindings": [],
  "vulnerabilityCorrelation": {
    "totalCount": 0,
    "criticalCount": 0,
    "highCvssCount": 0
  },
  "runtime": {
    "startedAtUtc": "2026-07-16T18:42:09Z",
    "finishedAtUtc": "2026-07-16T18:42:11Z",
    "uploadAttempted": true
  }
}

Authentication metadata should travel in headers, not inside the JSON body.

Packaging recommendation

Use a ZIP-based package for GitLab delivery and NinjaOne installation.

Recommended layout:

AttackTracerNinjaClient-win-x64.zip
  app/
    AttackTracerNinjaCli.exe
    AttackTracerNinjaCli.dll
  scripts/
    install-attacktracer-ninja.ps1
    uninstall-attacktracer-ninja.ps1
    update-attacktracer-ninja.ps1
    run-attacktracer-ninja.ps1
  config/
    attacktracer-settings.example.json
  VERSION.txt

This avoids the operational overhead of a heavy GUI installer while staying easy to deploy from NinjaOne.

Hardening recommendations

  • enable script and binary code signing where possible
  • set strict ACLs on Program Files and ProgramData content
  • log every update attempt locally
  • include a watchdog check for missing executions
  • keep secrets out of command-line parameters where possible
  • prefer HTTPS with certificate validation for all uploads
  • optionally pin the server certificate thumbprint if your environment allows it

Migration plan

Phase 1: define v2 contract

  • freeze current JSON model and derive schemaVersion 2.0
  • define n8n webhook contract
  • define version manifest format

Phase 2: build central pipeline

  • create Postgres schema
  • create n8n ingest workflow
  • create n8n rollup workflow
  • test NinjaOne org field updates from n8n

Phase 3: refactor endpoint client

  • remove share mirroring logic
  • remove organization/server logic from endpoint package
  • add signed upload path
  • add DPAPI-backed local secret storage

Phase 4: implement update channel

  • publish GitLab release artifacts
  • implement version manifest check
  • implement hash/signature validation
  • implement NinjaOne update task

Phase 5: controlled rollout

  • pilot on a small device group
  • validate upload cadence and rollups
  • compare with old system
  • then roll out to all devices

Phase 6: retire old architecture

  • stop AttackTracerNinjaServer
  • remove share-based reporting dependency
  • deprecate old org-report scripts

Recommendation summary

Recommended final direction:

  • keep a compiled endpoint agent
  • use PowerShell only as thin install/update/run wrapper
  • distribute and update through NinjaOne
  • host signed release artifacts in GitLab
  • upload signed JSON reports to n8n
  • store operational data in Postgres
  • perform organization-level NinjaOne API writes only from n8n

This gives the best balance of:

  • endpoint robustness
  • easier rollout
  • central visibility
  • reduced single-point-of-failure risk
  • maintainable future growth