107 lines
4.4 KiB
PowerShell
107 lines
4.4 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[string]$ManifestUrl = "https://gitea.officecom.cloud/officecom/oc-sentinel/raw/main/release/stable/version.json",
|
|
[string]$WebhookUrl = "",
|
|
[string]$SecretValue = ""
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$ProgressPreference = "SilentlyContinue"
|
|
|
|
function Initialize-OCSentinelTls {
|
|
$protocols = [Net.SecurityProtocolType]::Tls12
|
|
if ([Enum]::GetNames([Net.SecurityProtocolType]) -contains "Tls13") {
|
|
$protocols = $protocols -bor [Net.SecurityProtocolType]::Tls13
|
|
}
|
|
|
|
[Net.ServicePointManager]::SecurityProtocol = $protocols
|
|
[Net.ServicePointManager]::Expect100Continue = $false
|
|
}
|
|
|
|
function Get-OCSentinelManifest {
|
|
param([Parameter(Mandatory)][string]$Uri)
|
|
|
|
$parameters = @{ Method = "Get"; Uri = $Uri; TimeoutSec = 60 }
|
|
if ((Get-Command Invoke-RestMethod).Parameters.ContainsKey("UseBasicParsing")) {
|
|
$parameters.UseBasicParsing = $true
|
|
}
|
|
|
|
for ($attempt = 1; $attempt -le 3; $attempt++) {
|
|
try {
|
|
return Invoke-RestMethod @parameters
|
|
}
|
|
catch {
|
|
if ($attempt -eq 3) {
|
|
throw "Could not retrieve the OCSentinel release manifest after 3 attempts. Verify that the device can reach gitea.officecom.cloud with TLS 1.2 or newer. Last error: $($_.Exception.Message)"
|
|
}
|
|
Start-Sleep -Seconds (3 * $attempt)
|
|
}
|
|
}
|
|
}
|
|
|
|
Initialize-OCSentinelTls
|
|
|
|
function Get-NinjaValue {
|
|
param([Parameter(Mandatory)][string]$Name)
|
|
|
|
$value = [Environment]::GetEnvironmentVariable($Name, "Process")
|
|
if ($null -eq $value) {
|
|
return ""
|
|
}
|
|
|
|
return $value.Trim()
|
|
}
|
|
|
|
if ([string]::IsNullOrWhiteSpace($WebhookUrl)) { $WebhookUrl = Get-NinjaValue -Name "webhookurl" }
|
|
if ([string]::IsNullOrWhiteSpace($SecretValue)) { $SecretValue = Get-NinjaValue -Name "secretvalue" }
|
|
if ([string]::IsNullOrWhiteSpace($WebhookUrl) -or [string]::IsNullOrWhiteSpace($SecretValue)) {
|
|
throw "WebhookUrl and SecretValue must be set as NinjaOne script variables."
|
|
}
|
|
|
|
$manifest = Get-OCSentinelManifest -Uri $ManifestUrl
|
|
if ([string]::IsNullOrWhiteSpace($manifest.artifactUrl) -or [string]::IsNullOrWhiteSpace($manifest.sha256)) {
|
|
throw "The release manifest is incomplete."
|
|
}
|
|
|
|
$downloadRoot = Join-Path $env:ProgramData ("OCSentinel\\install-" + [Guid]::NewGuid().ToString("N"))
|
|
$zipPath = Join-Path $downloadRoot "OCSentinelClient.zip"
|
|
$extractPath = Join-Path $downloadRoot "payload"
|
|
|
|
try {
|
|
New-Item -ItemType Directory -Force -Path $extractPath | Out-Null
|
|
Write-Host "Downloading OCSentinel $($manifest.version)."
|
|
Invoke-WebRequest -Uri $manifest.artifactUrl -OutFile $zipPath -TimeoutSec 300
|
|
$actualHash = (Get-FileHash -LiteralPath $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
|
|
if ($actualHash -ne ([string]$manifest.sha256).ToLowerInvariant()) {
|
|
throw "Release package SHA-256 validation failed."
|
|
}
|
|
|
|
Expand-Archive -LiteralPath $zipPath -DestinationPath $extractPath -Force
|
|
$installer = Get-ChildItem -Path $extractPath -Recurse -Filter "install-ocsentinel.ps1" | Select-Object -First 1
|
|
if ($null -eq $installer) { throw "The release package does not contain the installer." }
|
|
|
|
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $installer.FullName
|
|
if ($LASTEXITCODE -ne 0) { throw "Installer failed with code $LASTEXITCODE" }
|
|
}
|
|
finally {
|
|
if (Test-Path -LiteralPath $downloadRoot) { Remove-Item -LiteralPath $downloadRoot -Recurse -Force }
|
|
}
|
|
|
|
$installRoot = Join-Path $env:ProgramFiles "OCSentinel"
|
|
$configPath = Join-Path $installRoot "config\ocsentinel-client.json"
|
|
$secretScript = Join-Path $installRoot "scripts\protect-ocsentinel-secret.ps1"
|
|
$monitorScript = Join-Path $installRoot "scripts\run-ocsentinel-monitor.ps1"
|
|
$secretPath = "C:\ProgramData\OCSentinel\secrets\ocsentinel-upload-secret.dat"
|
|
|
|
$config = Get-Content -LiteralPath $configPath -Raw | ConvertFrom-Json
|
|
$config.n8nWebhookUrl = $WebhookUrl
|
|
$config.environment = "production"
|
|
$config | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath $configPath -Encoding UTF8
|
|
|
|
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $secretScript -SecretValue $SecretValue
|
|
if ($LASTEXITCODE -ne 0) { throw "Writing the protected upload secret failed with code $LASTEXITCODE" }
|
|
|
|
Write-Host "Running initial signed scan and upload."
|
|
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $monitorScript -Mode status -ClientConfigPath $configPath -SecretPath $secretPath -UploadMode required
|
|
exit $LASTEXITCODE
|