Persist Ninja context for scheduled scans
This commit is contained in:
@@ -4,6 +4,12 @@
|
|||||||
"lookbackDays": 7,
|
"lookbackDays": 7,
|
||||||
"topFindings": 10,
|
"topFindings": 10,
|
||||||
"n8nWebhookUrl": "http://172.16.41.197:5678/webhook/ocsentinel-ingest",
|
"n8nWebhookUrl": "http://172.16.41.197:5678/webhook/ocsentinel-ingest",
|
||||||
|
"ninjaOrganizationId": "",
|
||||||
|
"ninjaOrganizationName": "",
|
||||||
|
"ninjaMachineId": "",
|
||||||
|
"ninjaNodeId": "",
|
||||||
|
"ninjaLocationId": "",
|
||||||
|
"ninjaLocationName": "",
|
||||||
"deviceIdentifierMode": "machineName",
|
"deviceIdentifierMode": "machineName",
|
||||||
"uploadTimeoutSeconds": 30,
|
"uploadTimeoutSeconds": 30,
|
||||||
"uploadQueueMaxReports": 100,
|
"uploadQueueMaxReports": 100,
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
"lookbackDays": 7,
|
"lookbackDays": 7,
|
||||||
"topFindings": 10,
|
"topFindings": 10,
|
||||||
"n8nWebhookUrl": "https://n8n.example.com/webhook/ocsentinel-ingest",
|
"n8nWebhookUrl": "https://n8n.example.com/webhook/ocsentinel-ingest",
|
||||||
|
"ninjaOrganizationId": "",
|
||||||
|
"ninjaOrganizationName": "",
|
||||||
|
"ninjaMachineId": "",
|
||||||
|
"ninjaNodeId": "",
|
||||||
|
"ninjaLocationId": "",
|
||||||
|
"ninjaLocationName": "",
|
||||||
"deviceIdentifierMode": "machineName",
|
"deviceIdentifierMode": "machineName",
|
||||||
"uploadTimeoutSeconds": 30,
|
"uploadTimeoutSeconds": 30,
|
||||||
"uploadQueueMaxReports": 100,
|
"uploadQueueMaxReports": 100,
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ powershell -ExecutionPolicy Bypass -File .\build\build-release-manifest.ps1 `
|
|||||||
|
|
||||||
## Local Schedule And Burst Mode
|
## 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`:
|
The installer creates two Windows Scheduled Tasks running as `SYSTEM`:
|
||||||
|
|
||||||
- `OCSentinel Daily Scan`: runs once per day and uploads one signed report.
|
- `OCSentinel Daily Scan`: runs once per day and uploads one signed report.
|
||||||
|
|||||||
@@ -39,6 +39,40 @@ function Resolve-PathLike {
|
|||||||
return [System.IO.Path]::GetFullPath((Join-Path $BasePath $PathValue))
|
return [System.IO.Path]::GetFullPath((Join-Path $BasePath $PathValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Restore-NinjaContextFromClientConfiguration {
|
||||||
|
param([Parameter(Mandatory)][string]$Path)
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $Path)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$clientConfiguration = Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json
|
||||||
|
$mappings = @(
|
||||||
|
@{ EnvironmentName = "NINJA_ORGANIZATION_ID"; PropertyName = "ninjaOrganizationId" },
|
||||||
|
@{ EnvironmentName = "NINJA_ORGANIZATION_NAME"; PropertyName = "ninjaOrganizationName" },
|
||||||
|
@{ EnvironmentName = "NINJA_AGENT_MACHINE_ID"; PropertyName = "ninjaMachineId" },
|
||||||
|
@{ EnvironmentName = "NINJA_AGENT_NODE_ID"; PropertyName = "ninjaNodeId" },
|
||||||
|
@{ EnvironmentName = "NINJA_LOCATION_ID"; PropertyName = "ninjaLocationId" },
|
||||||
|
@{ EnvironmentName = "NINJA_LOCATION_NAME"; PropertyName = "ninjaLocationName" }
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($mapping in $mappings) {
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace([Environment]::GetEnvironmentVariable($mapping.EnvironmentName, "Process"))) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = [string]$clientConfiguration.($mapping.PropertyName)
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($value)) {
|
||||||
|
[Environment]::SetEnvironmentVariable($mapping.EnvironmentName, $value, "Process")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Warning "Could not restore stored NinjaOne context: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (-not (Test-Path $appExe)) {
|
if (-not (Test-Path $appExe)) {
|
||||||
throw "Application executable not found: $appExe"
|
throw "Application executable not found: $appExe"
|
||||||
}
|
}
|
||||||
@@ -54,6 +88,8 @@ else {
|
|||||||
$secretFullPath = if ([string]::IsNullOrWhiteSpace($SecretPath)) { "" } else { Resolve-PathLike -PathValue $SecretPath -BasePath $scriptDir }
|
$secretFullPath = if ([string]::IsNullOrWhiteSpace($SecretPath)) { "" } else { Resolve-PathLike -PathValue $SecretPath -BasePath $scriptDir }
|
||||||
$canUpload = (Test-Path $clientConfigFullPath) -and (-not [string]::IsNullOrWhiteSpace($secretFullPath)) -and (Test-Path $secretFullPath)
|
$canUpload = (Test-Path $clientConfigFullPath) -and (-not [string]::IsNullOrWhiteSpace($secretFullPath)) -and (Test-Path $secretFullPath)
|
||||||
|
|
||||||
|
Restore-NinjaContextFromClientConfiguration -Path $clientConfigFullPath
|
||||||
|
|
||||||
if ($UploadMode -eq "required" -and -not $canUpload) {
|
if ($UploadMode -eq "required" -and -not $canUpload) {
|
||||||
throw "UploadMode 'required' was set, but client config or protected secret is missing."
|
throw "UploadMode 'required' was set, but client config or protected secret is missing."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,8 +164,22 @@ if (-not [string]::IsNullOrWhiteSpace($WebhookUrl)) {
|
|||||||
$clientConfig = Get-Content -LiteralPath $clientConfigPath -Raw | ConvertFrom-Json
|
$clientConfig = Get-Content -LiteralPath $clientConfigPath -Raw | ConvertFrom-Json
|
||||||
$clientConfig.n8nWebhookUrl = $WebhookUrl
|
$clientConfig.n8nWebhookUrl = $WebhookUrl
|
||||||
$clientConfig.environment = "production"
|
$clientConfig.environment = "production"
|
||||||
|
$ninjaContext = @(
|
||||||
|
@{ EnvironmentName = "NINJA_ORGANIZATION_ID"; PropertyName = "ninjaOrganizationId" },
|
||||||
|
@{ EnvironmentName = "NINJA_ORGANIZATION_NAME"; PropertyName = "ninjaOrganizationName" },
|
||||||
|
@{ EnvironmentName = "NINJA_AGENT_MACHINE_ID"; PropertyName = "ninjaMachineId" },
|
||||||
|
@{ EnvironmentName = "NINJA_AGENT_NODE_ID"; PropertyName = "ninjaNodeId" },
|
||||||
|
@{ EnvironmentName = "NINJA_LOCATION_ID"; PropertyName = "ninjaLocationId" },
|
||||||
|
@{ EnvironmentName = "NINJA_LOCATION_NAME"; PropertyName = "ninjaLocationName" }
|
||||||
|
)
|
||||||
|
foreach ($entry in $ninjaContext) {
|
||||||
|
$value = [Environment]::GetEnvironmentVariable($entry.EnvironmentName, "Process")
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($value)) {
|
||||||
|
$clientConfig | Add-Member -NotePropertyName $entry.PropertyName -NotePropertyValue $value.Trim() -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
$clientConfig | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $clientConfigPath -Encoding UTF8
|
$clientConfig | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $clientConfigPath -Encoding UTF8
|
||||||
Write-Host "Configured OCSentinel upload endpoint."
|
Write-Host "Configured OCSentinel upload endpoint and NinjaOne context."
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-not [string]::IsNullOrWhiteSpace($SecretValue)) {
|
if (-not [string]::IsNullOrWhiteSpace($SecretValue)) {
|
||||||
|
|||||||
@@ -40,6 +40,40 @@ function Resolve-PathLike {
|
|||||||
return [System.IO.Path]::GetFullPath((Join-Path $BasePath $PathValue))
|
return [System.IO.Path]::GetFullPath((Join-Path $BasePath $PathValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Restore-NinjaContextFromClientConfiguration {
|
||||||
|
param([Parameter(Mandatory)][string]$Path)
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $Path)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$clientConfiguration = Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json
|
||||||
|
$mappings = @(
|
||||||
|
@{ EnvironmentName = "NINJA_ORGANIZATION_ID"; PropertyName = "ninjaOrganizationId" },
|
||||||
|
@{ EnvironmentName = "NINJA_ORGANIZATION_NAME"; PropertyName = "ninjaOrganizationName" },
|
||||||
|
@{ EnvironmentName = "NINJA_AGENT_MACHINE_ID"; PropertyName = "ninjaMachineId" },
|
||||||
|
@{ EnvironmentName = "NINJA_AGENT_NODE_ID"; PropertyName = "ninjaNodeId" },
|
||||||
|
@{ EnvironmentName = "NINJA_LOCATION_ID"; PropertyName = "ninjaLocationId" },
|
||||||
|
@{ EnvironmentName = "NINJA_LOCATION_NAME"; PropertyName = "ninjaLocationName" }
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($mapping in $mappings) {
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace([Environment]::GetEnvironmentVariable($mapping.EnvironmentName, "Process"))) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = [string]$clientConfiguration.($mapping.PropertyName)
|
||||||
|
if (-not [string]::IsNullOrWhiteSpace($value)) {
|
||||||
|
[Environment]::SetEnvironmentVariable($mapping.EnvironmentName, $value, "Process")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Warning "Could not restore stored NinjaOne context: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$arguments = @(
|
$arguments = @(
|
||||||
$dllPath
|
$dllPath
|
||||||
)
|
)
|
||||||
@@ -53,6 +87,8 @@ else {
|
|||||||
$secretFullPath = if ([string]::IsNullOrWhiteSpace($SecretPath)) { "" } else { Resolve-PathLike -PathValue $SecretPath -BasePath $repoRoot }
|
$secretFullPath = if ([string]::IsNullOrWhiteSpace($SecretPath)) { "" } else { Resolve-PathLike -PathValue $SecretPath -BasePath $repoRoot }
|
||||||
$canUpload = (Test-Path $clientConfigFullPath) -and (-not [string]::IsNullOrWhiteSpace($secretFullPath)) -and (Test-Path $secretFullPath)
|
$canUpload = (Test-Path $clientConfigFullPath) -and (-not [string]::IsNullOrWhiteSpace($secretFullPath)) -and (Test-Path $secretFullPath)
|
||||||
|
|
||||||
|
Restore-NinjaContextFromClientConfiguration -Path $clientConfigFullPath
|
||||||
|
|
||||||
if ($UploadMode -eq "required" -and -not $canUpload) {
|
if ($UploadMode -eq "required" -and -not $canUpload) {
|
||||||
throw "UploadMode 'required' was set, but client config or protected secret is missing."
|
throw "UploadMode 'required' was set, but client config or protected secret is missing."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.5</Version>
|
<Version>1.3.6</Version>
|
||||||
<AssemblyVersion>1.3.5.0</AssemblyVersion>
|
<AssemblyVersion>1.3.6.0</AssemblyVersion>
|
||||||
<FileVersion>1.3.5.0</FileVersion>
|
<FileVersion>1.3.6.0</FileVersion>
|
||||||
<InformationalVersion>1.3.5</InformationalVersion>
|
<InformationalVersion>1.3.6</InformationalVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user