2 Commits

Author SHA1 Message Date
OfficeCom Codex
2a780cd52f Add time-bounded burst scans
Some checks failed
OfficeCom Sentinel Client / validate-client (push) Successful in 23s
OfficeCom Sentinel Client / build-client-windows (push) Failing after 18s
2026-07-26 21:13:49 +02:00
OfficeCom Codex
daa494fade Publish stable client version 1.3.3
Some checks failed
OfficeCom Sentinel Client / validate-client (push) Successful in 23s
OfficeCom Sentinel Client / build-client-windows (push) Failing after 19s
2026-07-26 20:26:37 +02:00
5 changed files with 163 additions and 22 deletions

View File

@@ -39,12 +39,21 @@ The installer creates two Windows Scheduled Tasks running as `SYSTEM`:
`04:00` and `06:59`, derived from its Windows `MachineGuid`. This distributes `04:00` and `06:59`, derived from its Windows `MachineGuid`. This distributes
a fleet rollout instead of sending all reports at the same time. a fleet rollout instead of sending all reports at the same time.
- `OCSentinel Burst Check`: runs every five minutes. It performs no scan unless - `OCSentinel Burst Check`: runs every five minutes. It performs no scan unless
the NinjaOne device custom field `ocsentinelburst` is enabled. 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 Create `ocsentinelburst` as a device-level `Checkbox` custom field and allow
automation read access. Set it to `true` for a device to begin the five-minute automation read and write access. Set it to `true` for a device to begin the
burst scans; clear it to stop them. The normal daily scan continues regardless five-minute burst scans; clear it to stop them early. The normal daily scan
of the checkbox. 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 ## Upload Reliability And Client Health

View File

@@ -1,7 +1,9 @@
[CmdletBinding()] [CmdletBinding()]
param( param(
[ValidateSet("daily", "burst")] [ValidateSet("daily", "burst")]
[string]$Kind = "daily" [string]$Kind = "daily",
[ValidateRange(15, 480)]
[int]$BurstDurationMinutes = 120
) )
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
@@ -25,9 +27,69 @@ function Get-NinjaBurstEnabled {
return $false return $false
} }
if ($Kind -eq "burst" -and -not (Get-NinjaBurstEnabled)) { function Get-NinjaValue {
Write-Host "OfficeCom Sentinel burst check: disabled." param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$Type)
exit 0
try {
if (Get-Command -Name "Get-NinjaProperty" -ErrorAction SilentlyContinue) {
return Get-NinjaProperty -Name $Name -Type $Type
}
if (Get-Command -Name "Ninja-Property-Get" -ErrorAction SilentlyContinue) {
return Ninja-Property-Get -Name $Name
}
}
catch {
Write-Warning "Could not read Ninja field '$Name': $($_.Exception.Message)"
}
return $null
}
function Set-NinjaValue {
param([Parameter(Mandatory)][string]$Name, [AllowEmptyString()][string]$Value, [Parameter(Mandatory)][string]$Type)
try {
if (Get-Command -Name "Set-NinjaProperty" -ErrorAction SilentlyContinue) {
Set-NinjaProperty -Name $Name -Value $Value -Type $Type -Force | Out-Null
return $true
}
if (Get-Command -Name "Ninja-Property-Set" -ErrorAction SilentlyContinue) {
Ninja-Property-Set -Name $Name -Value $Value | Out-Null
return $true
}
}
catch {
Write-Warning "Could not update Ninja field '$Name': $($_.Exception.Message)"
}
return $false
}
if ($Kind -eq "burst") {
if (-not (Get-NinjaBurstEnabled)) {
Set-NinjaValue -Name "ocsentinelburststatus" -Value "idle" -Type "Text" | Out-Null
Write-Host "OfficeCom Sentinel burst check: disabled."
exit 0
}
$now = [DateTimeOffset]::UtcNow
$untilValue = Get-NinjaValue -Name "ocsentinelburstuntilutc" -Type "DateTime"
$until = $null
if (-not [string]::IsNullOrWhiteSpace([string]$untilValue)) {
try { $until = [DateTimeOffset]$untilValue } catch { Write-Warning "Burst end time is invalid and will be restarted." }
}
if ($null -eq $until) {
$until = $now.AddMinutes($BurstDurationMinutes)
Set-NinjaValue -Name "ocsentinelburstuntilutc" -Value $until.ToString("o") -Type "DateTime" | Out-Null
Write-Host "OfficeCom Sentinel burst window started until $($until.ToString('u'))."
}
elseif ($until -le $now) {
Set-NinjaValue -Name "ocsentinelburst" -Value "false" -Type "Checkbox" | Out-Null
Set-NinjaValue -Name "ocsentinelburststatus" -Value "completed" -Type "Text" | Out-Null
Write-Host "OfficeCom Sentinel burst window completed and was disabled."
exit 0
}
Set-NinjaValue -Name "ocsentinelburststatus" -Value "active until $($until.ToUniversalTime().ToString('o'))" -Type "Text" | Out-Null
} }
$createdNew = $false $createdNew = $false
@@ -39,7 +101,11 @@ try {
} }
Write-Host "OfficeCom Sentinel scheduled $Kind scan started." Write-Host "OfficeCom Sentinel scheduled $Kind scan started."
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $monitorScript -Mode status -UploadMode required -SecretPath $secretPath -SuppressTriggerExit $monitorArgs = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $monitorScript, "-Mode", "status", "-UploadMode", "required", "-SecretPath", $secretPath, "-SuppressTriggerExit")
if ($Kind -eq "burst") {
$monitorArgs += @("-LookbackDays", "1", "-TopCount", "25")
}
& powershell.exe @monitorArgs
exit $LASTEXITCODE exit $LASTEXITCODE
} }
finally { finally {

View File

@@ -1,8 +1,8 @@
{ {
"channel": "stable", "channel": "stable",
"version": "1.3.2", "version": "1.3.3",
"publishedAtUtc": "2026-07-26T00:23:31.3024295Z", "publishedAtUtc": "2026-07-26T18:25:32.8762198Z",
"artifactUrl": "https://gitea.officecom.cloud/officecom/oc-sentinel/releases/download/v1.3.2/OCSentinelClient-win-x64.zip", "artifactUrl": "https://gitea.officecom.cloud/officecom/oc-sentinel/releases/download/v1.3.3/OCSentinelClient-win-x64.zip",
"sha256": "dbfedf0890176873cef8bc91b9f7a6d6c3c8382ffadc972324b9900bad1153cc", "sha256": "9bb2b2dc25c59bc6faf53ded6095667ac73640038cfd426a74f3bf6aca81bd86",
"minUpdaterVersion": "1.0.0" "minUpdaterVersion": "1.0.0"
} }

View File

@@ -1,7 +1,9 @@
[CmdletBinding()] [CmdletBinding()]
param( param(
[ValidateSet("daily", "burst")] [ValidateSet("daily", "burst")]
[string]$Kind = "daily" [string]$Kind = "daily",
[ValidateRange(15, 480)]
[int]$BurstDurationMinutes = 120
) )
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
@@ -25,9 +27,69 @@ function Get-NinjaBurstEnabled {
return $false return $false
} }
if ($Kind -eq "burst" -and -not (Get-NinjaBurstEnabled)) { function Get-NinjaValue {
Write-Host "OfficeCom Sentinel burst check: disabled." param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$Type)
exit 0
try {
if (Get-Command -Name "Get-NinjaProperty" -ErrorAction SilentlyContinue) {
return Get-NinjaProperty -Name $Name -Type $Type
}
if (Get-Command -Name "Ninja-Property-Get" -ErrorAction SilentlyContinue) {
return Ninja-Property-Get -Name $Name
}
}
catch {
Write-Warning "Could not read Ninja field '$Name': $($_.Exception.Message)"
}
return $null
}
function Set-NinjaValue {
param([Parameter(Mandatory)][string]$Name, [AllowEmptyString()][string]$Value, [Parameter(Mandatory)][string]$Type)
try {
if (Get-Command -Name "Set-NinjaProperty" -ErrorAction SilentlyContinue) {
Set-NinjaProperty -Name $Name -Value $Value -Type $Type -Force | Out-Null
return $true
}
if (Get-Command -Name "Ninja-Property-Set" -ErrorAction SilentlyContinue) {
Ninja-Property-Set -Name $Name -Value $Value | Out-Null
return $true
}
}
catch {
Write-Warning "Could not update Ninja field '$Name': $($_.Exception.Message)"
}
return $false
}
if ($Kind -eq "burst") {
if (-not (Get-NinjaBurstEnabled)) {
Set-NinjaValue -Name "ocsentinelburststatus" -Value "idle" -Type "Text" | Out-Null
Write-Host "OfficeCom Sentinel burst check: disabled."
exit 0
}
$now = [DateTimeOffset]::UtcNow
$untilValue = Get-NinjaValue -Name "ocsentinelburstuntilutc" -Type "DateTime"
$until = $null
if (-not [string]::IsNullOrWhiteSpace([string]$untilValue)) {
try { $until = [DateTimeOffset]$untilValue } catch { Write-Warning "Burst end time is invalid and will be restarted." }
}
if ($null -eq $until) {
$until = $now.AddMinutes($BurstDurationMinutes)
Set-NinjaValue -Name "ocsentinelburstuntilutc" -Value $until.ToString("o") -Type "DateTime" | Out-Null
Write-Host "OfficeCom Sentinel burst window started until $($until.ToString('u'))."
}
elseif ($until -le $now) {
Set-NinjaValue -Name "ocsentinelburst" -Value "false" -Type "Checkbox" | Out-Null
Set-NinjaValue -Name "ocsentinelburststatus" -Value "completed" -Type "Text" | Out-Null
Write-Host "OfficeCom Sentinel burst window completed and was disabled."
exit 0
}
Set-NinjaValue -Name "ocsentinelburststatus" -Value "active until $($until.ToUniversalTime().ToString('o'))" -Type "Text" | Out-Null
} }
$createdNew = $false $createdNew = $false
@@ -39,7 +101,11 @@ try {
} }
Write-Host "OfficeCom Sentinel scheduled $Kind scan started." Write-Host "OfficeCom Sentinel scheduled $Kind scan started."
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $monitorScript -Mode status -UploadMode required -SecretPath $secretPath -SuppressTriggerExit $monitorArgs = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $monitorScript, "-Mode", "status", "-UploadMode", "required", "-SecretPath", $secretPath, "-SuppressTriggerExit")
if ($Kind -eq "burst") {
$monitorArgs += @("-LookbackDays", "1", "-TopCount", "25")
}
& powershell.exe @monitorArgs
exit $LASTEXITCODE exit $LASTEXITCODE
} }
finally { finally {

View File

@@ -9,10 +9,10 @@
<RootNamespace>OCSentinelCli</RootNamespace> <RootNamespace>OCSentinelCli</RootNamespace>
<Product>OfficeCom Sentinel</Product> <Product>OfficeCom Sentinel</Product>
<Company>OfficeCom</Company> <Company>OfficeCom</Company>
<Version>1.3.3</Version> <Version>1.3.4</Version>
<AssemblyVersion>1.3.3.0</AssemblyVersion> <AssemblyVersion>1.3.4.0</AssemblyVersion>
<FileVersion>1.3.3.0</FileVersion> <FileVersion>1.3.4.0</FileVersion>
<InformationalVersion>1.3.3</InformationalVersion> <InformationalVersion>1.3.4</InformationalVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>