175 lines
6.7 KiB
Markdown
175 lines
6.7 KiB
Markdown
# OfficeCom Sentinel Deployment
|
|
|
|
## Goal
|
|
|
|
Deploy and update the endpoint client through NinjaOne while hosting release artifacts in Gitea.
|
|
|
|
## Release Assets
|
|
|
|
Each Gitea release should publish:
|
|
|
|
- `OCSentinelClient-win-x64.zip`
|
|
- `OCSentinelClient-win-x64.zip.sha256`
|
|
- `version.json`
|
|
|
|
Build these locally with:
|
|
|
|
```powershell
|
|
powershell -ExecutionPolicy Bypass -File .\build\build-client-package.ps1
|
|
powershell -ExecutionPolicy Bypass -File .\build\build-release-manifest.ps1 `
|
|
-ArtifactUrl "https://gitea.officecom.cloud/officecom/oc-sentinel/releases/download/v1.2.3/OCSentinelClient-win-x64.zip"
|
|
```
|
|
|
|
## Installed Layout
|
|
|
|
- `app\OCSentinelCli.exe`
|
|
- `scripts\run-ocsentinel.ps1`
|
|
- `scripts\run-ocsentinel-monitor.ps1`
|
|
- `scripts\update-ocsentinel.ps1`
|
|
- `scripts\protect-ocsentinel-secret.ps1`
|
|
- `config\ocsentinel-settings.json`
|
|
- `config\ocsentinel-client.json`
|
|
|
|
## Local Schedule And Burst Mode
|
|
|
|
During a NinjaOne installation or update, OCSentinel stores the device's
|
|
NinjaOne organization, location, and device identifiers in its local client
|
|
configuration. Scheduled `SYSTEM` scans restore that context before creating a
|
|
report, so their uploads remain assigned to the correct organization.
|
|
|
|
The installer creates two Windows Scheduled Tasks running as `SYSTEM`:
|
|
|
|
- `OCSentinel Daily Scan`: runs once per day and uploads one signed report.
|
|
The installer deterministically assigns each device a stable slot between
|
|
`04:00` and `06:59`, derived from its Windows `MachineGuid`. This distributes
|
|
a fleet rollout instead of sending all reports at the same time.
|
|
- `OCSentinel Burst Check`: runs every five minutes. It performs no scan unless
|
|
the NinjaOne device custom field `ocsentinelburst` is enabled. Once enabled,
|
|
it scans for two hours and then disables itself automatically.
|
|
|
|
Create `ocsentinelburst` as a device-level `Checkbox` custom field and allow
|
|
automation read and write access. Set it to `true` for a device to begin the
|
|
five-minute burst scans; clear it to stop them early. The normal daily scan
|
|
continues regardless of the checkbox.
|
|
|
|
Create these accompanying device custom fields and allow automation write
|
|
access:
|
|
|
|
| Field name | Type | Purpose |
|
|
| --- | --- | --- |
|
|
| `ocsentinelburstuntilutc` | Date/Time | UTC time at which the active burst ends |
|
|
| `ocsentinelburststatus` | Text | `idle`, `active until ...`, or `completed` |
|
|
|
|
## Upload Reliability And Client Health
|
|
|
|
If the upload endpoint is temporarily unavailable, the client stores up to 100
|
|
signed report payloads locally under `C:\ProgramData\OCSentinel\upload-queue`.
|
|
The next scheduled run sends queued payloads before its new report. The local
|
|
health state is stored under `C:\ProgramData\OCSentinel\state`.
|
|
|
|
Create these additional device custom fields in NinjaOne and allow automation
|
|
write access:
|
|
|
|
| Field name | Type | Purpose |
|
|
| --- | --- | --- |
|
|
| `ocsentineluploadstatus` | Text | `ok`, `queued`, or `unknown` upload state |
|
|
| `ocsentinelqueuedreports` | Integer | Reports waiting for delivery |
|
|
| `ocsentinellastuploadutc` | Date/Time | Last successful upload time |
|
|
| `ocsentinellasterror` | Text | Last upload error, if any |
|
|
|
|
## NinjaOne Tasks
|
|
|
|
Create a PowerShell script in NinjaOne named `OCSentinel - Installieren oder aktualisieren`.
|
|
Run it as `SYSTEM` in 64-bit PowerShell and copy the content of
|
|
`scripts/bootstrap-ocsentinel-ninja.ps1` into the NinjaOne script editor.
|
|
It is idempotent: new devices install the current package, while installed devices
|
|
only update when a newer manifest version is published.
|
|
|
|
Use it for the one-time rollout and, later, as the monthly update task. For an
|
|
initial validation scan, add `-RunInitialStatusScan` to the script parameters.
|
|
|
|
Installed-client update only:
|
|
|
|
```powershell
|
|
& "C:\Program Files\OCSentinel\scripts\update-ocsentinel.ps1" `
|
|
-ManifestUrl "https://gitea.officecom.cloud/officecom/oc-sentinel/raw/main/release/stable/version.json" `
|
|
-Force
|
|
```
|
|
|
|
Routine update:
|
|
|
|
```powershell
|
|
& "C:\Program Files\OCSentinel\scripts\update-ocsentinel.ps1" `
|
|
-ManifestUrl "https://gitea.officecom.cloud/officecom/oc-sentinel/raw/main/release/stable/version.json"
|
|
```
|
|
|
|
Runtime:
|
|
|
|
```powershell
|
|
& "C:\Program Files\OCSentinel\scripts\run-ocsentinel-monitor.ps1" `
|
|
-Mode status `
|
|
-OutputPath "..\reports\ocsentinel-summary.json"
|
|
```
|
|
|
|
## Repair Missing NinjaOne Context
|
|
|
|
NinjaOne exposes `NINJA_ORGANIZATION_ID`, `NINJA_ORGANIZATION_NAME`,
|
|
`NINJA_AGENT_MACHINE_ID`, and location values only while an automation runs.
|
|
The scheduled OCSentinel task runs later as `SYSTEM`, so those values must be
|
|
persisted during an actual NinjaOne automation.
|
|
|
|
If the console shows `Organisation unbekannt`, create a temporary NinjaOne
|
|
PowerShell automation named `OCSentinel - NinjaOne Kontext aktualisieren` and
|
|
copy `scripts/refresh-ocsentinel-ninja-context.ps1` into the editor. Run it as
|
|
`SYSTEM` in 64-bit PowerShell once against the affected devices or policy.
|
|
|
|
The script has no script variables and does the following safely:
|
|
|
|
1. updates the installed client through the stable, version-independent manifest;
|
|
2. stores the current NinjaOne organization, location, node, and machine values;
|
|
3. starts one signed status scan and upload using that stored context.
|
|
|
|
Expected output includes `OCSENTINEL_NINJA_CONTEXT=updated`; this is emitted
|
|
only after the immediate upload succeeds. Do not run this script from an
|
|
interactive PowerShell session, because NinjaOne does not expose the required
|
|
environment values there.
|
|
|
|
## Secret Bootstrap
|
|
|
|
```powershell
|
|
& "C:\Program Files\OCSentinel\scripts\protect-ocsentinel-secret.ps1" `
|
|
-SecretValue "<shared-ingest-secret>"
|
|
```
|
|
|
|
This writes:
|
|
|
|
- `C:\ProgramData\OCSentinel\secrets\ocsentinel-upload-secret.dat`
|
|
|
|
## Development Upload
|
|
|
|
For the internal development environment, copy
|
|
`config/ocsentinel-client.dev.example.json` to the installed client config
|
|
path and use its HTTP webhook URL. Production clients must use the HTTPS
|
|
configuration with the public Sentinel domain instead.
|
|
|
|
## Current Manual Release State
|
|
|
|
As of July 16, 2026, the first manual release is already published:
|
|
|
|
- tag: `v1.2.3`
|
|
- release URL: `https://gitea.officecom.cloud/officecom/oc-sentinel/releases/tag/v1.2.3`
|
|
- stable manifest URL: `https://gitea.officecom.cloud/officecom/oc-sentinel/raw/main/release/stable/version.json`
|
|
|
|
The manifest is intentionally version-independent for NinjaOne. Only the JSON content changes per release; the NinjaOne task URL stays the same.
|
|
|
|
This means NinjaOne rollout can start immediately without waiting for a Gitea runner.
|
|
|
|
## Later Automation
|
|
|
|
When a Gitea runner is added later, the usual next step is:
|
|
|
|
1. connect to the runner host through SSH or RDP, depending on the server type
|
|
2. install and register the Gitea runner
|
|
3. let `.gitea/workflows/client-build.yml` publish future release artifacts automatically
|
|
4. update `release/stable/version.json` automatically as part of the release flow
|