Initial OfficeCom Sentinel client and deployment assets
This commit is contained in:
469
docs/attacktracer-ninja-v2-architecture.md
Normal file
469
docs/attacktracer-ninja-v2-architecture.md
Normal file
@@ -0,0 +1,469 @@
|
||||
# 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.
|
||||
|
||||
## Recommended component split
|
||||
|
||||
### 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`:
|
||||
|
||||
```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:
|
||||
|
||||
```powershell
|
||||
& "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
|
||||
|
||||
## Recommended report contract
|
||||
|
||||
Each JSON report should include:
|
||||
|
||||
```json
|
||||
{
|
||||
"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:
|
||||
|
||||
```text
|
||||
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
|
||||
Reference in New Issue
Block a user