Initial OfficeCom Sentinel client and deployment assets

This commit is contained in:
OfficeCom Codex
2026-07-17 00:39:28 +02:00
commit 7cdc0395c4
58 changed files with 6199 additions and 0 deletions

View 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