From f9941b08079d20ff41083f14ded10901344076b0 Mon Sep 17 00:00:00 2001 From: OfficeCom Codex Date: Mon, 27 Jul 2026 00:34:48 +0200 Subject: [PATCH] Harden release downloads for TLS failures --- installer/update-ocsentinel.ps1 | 35 +++++++++++++++++++++- scripts/bootstrap-ocsentinel-ninja.ps1 | 36 +++++++++++++++++++++-- scripts/install-ocsentinel-ninja-once.ps1 | 36 +++++++++++++++++++++-- src/OCSentinelCli/OCSentinelCli.csproj | 8 ++--- 4 files changed, 106 insertions(+), 9 deletions(-) diff --git a/installer/update-ocsentinel.ps1 b/installer/update-ocsentinel.ps1 index 30573c3..66c7ec8 100644 --- a/installer/update-ocsentinel.ps1 +++ b/installer/update-ocsentinel.ps1 @@ -7,6 +7,39 @@ param( $ErrorActionPreference = "Stop" +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 + $installRoot = Join-Path ${env:ProgramFiles} "OCSentinel" $appExe = Join-Path $installRoot "app\OCSentinelCli.exe" $installScript = Join-Path $installRoot "scripts\install-ocsentinel.ps1" @@ -66,7 +99,7 @@ if ([string]::IsNullOrWhiteSpace($ManifestUrl)) { $resolvedManifestUrl = Resolve-ManifestUrl -ManifestUrl $ManifestUrl -Channel $Channel Write-Host "Checking update manifest: $resolvedManifestUrl" -$manifest = Invoke-RestMethod -Method Get -Uri $resolvedManifestUrl -TimeoutSec 60 +$manifest = Get-OCSentinelManifest -Uri $resolvedManifestUrl if (-not $manifest.version -or -not $manifest.artifactUrl -or -not $manifest.sha256) { throw "Update manifest is missing required fields: version, artifactUrl, sha256." } diff --git a/scripts/bootstrap-ocsentinel-ninja.ps1 b/scripts/bootstrap-ocsentinel-ninja.ps1 index 9e71c99..834c465 100644 --- a/scripts/bootstrap-ocsentinel-ninja.ps1 +++ b/scripts/bootstrap-ocsentinel-ninja.ps1 @@ -8,7 +8,39 @@ param( $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +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 $installRoot = Join-Path $env:ProgramFiles "OCSentinel" $updaterPath = Join-Path $installRoot "scripts\update-ocsentinel.ps1" @@ -54,7 +86,7 @@ if (Test-Path -LiteralPath $updaterPath) { } else { Write-Host "Reading OCSentinel release manifest: $ManifestUrl" - $manifest = Invoke-RestMethod -Method Get -Uri $ManifestUrl -TimeoutSec 60 + $manifest = Get-OCSentinelManifest -Uri $ManifestUrl if ([string]::IsNullOrWhiteSpace($manifest.version) -or [string]::IsNullOrWhiteSpace($manifest.artifactUrl) -or [string]::IsNullOrWhiteSpace($manifest.sha256)) { throw "Release manifest is missing version, artifactUrl, or sha256." } diff --git a/scripts/install-ocsentinel-ninja-once.ps1 b/scripts/install-ocsentinel-ninja-once.ps1 index f9dcd74..befdbec 100644 --- a/scripts/install-ocsentinel-ninja-once.ps1 +++ b/scripts/install-ocsentinel-ninja-once.ps1 @@ -7,7 +7,39 @@ param( $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + +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) @@ -26,7 +58,7 @@ if ([string]::IsNullOrWhiteSpace($WebhookUrl) -or [string]::IsNullOrWhiteSpace($ throw "WebhookUrl and SecretValue must be set as NinjaOne script variables." } -$manifest = Invoke-RestMethod -Method Get -Uri $ManifestUrl -TimeoutSec 60 +$manifest = Get-OCSentinelManifest -Uri $ManifestUrl if ([string]::IsNullOrWhiteSpace($manifest.artifactUrl) -or [string]::IsNullOrWhiteSpace($manifest.sha256)) { throw "The release manifest is incomplete." } diff --git a/src/OCSentinelCli/OCSentinelCli.csproj b/src/OCSentinelCli/OCSentinelCli.csproj index 5cbf053..441d0b9 100644 --- a/src/OCSentinelCli/OCSentinelCli.csproj +++ b/src/OCSentinelCli/OCSentinelCli.csproj @@ -9,10 +9,10 @@ OCSentinelCli OfficeCom Sentinel OfficeCom - 1.3.4 - 1.3.4.0 - 1.3.4.0 - 1.3.4 + 1.3.5 + 1.3.5.0 + 1.3.5.0 + 1.3.5