From 2cf3281b4d3881d38c270ec868b6d36ad57e7884 Mon Sep 17 00:00:00 2001 From: OfficeCom Codex Date: Mon, 27 Jul 2026 11:13:48 +0200 Subject: [PATCH] Retry interrupted client package downloads --- installer/update-ocsentinel.ps1 | 35 ++++++++++++++++- scripts/bootstrap-ocsentinel-ninja.ps1 | 52 +++++++++++++++++++++++--- src/OCSentinelCli/OCSentinelCli.csproj | 8 ++-- 3 files changed, 85 insertions(+), 10 deletions(-) diff --git a/installer/update-ocsentinel.ps1 b/installer/update-ocsentinel.ps1 index 66c7ec8..84db752 100644 --- a/installer/update-ocsentinel.ps1 +++ b/installer/update-ocsentinel.ps1 @@ -38,6 +38,39 @@ function Get-OCSentinelManifest { } } +function Get-OCSentinelArtifact { + param( + [Parameter(Mandatory)][string]$Uri, + [Parameter(Mandatory)][string]$DestinationPath + ) + + $parameters = @{ Uri = $Uri; OutFile = $DestinationPath; TimeoutSec = 300 } + if ((Get-Command Invoke-WebRequest).Parameters.ContainsKey("UseBasicParsing")) { + $parameters.UseBasicParsing = $true + } + + for ($attempt = 1; $attempt -le 3; $attempt++) { + try { + Remove-Item -LiteralPath $DestinationPath -Force -ErrorAction SilentlyContinue + Invoke-WebRequest @parameters + + if (-not (Test-Path -LiteralPath $DestinationPath) -or (Get-Item -LiteralPath $DestinationPath).Length -eq 0) { + throw "The downloaded artifact is empty." + } + + return + } + catch { + if ($attempt -eq 3) { + throw "Could not download the OCSentinel package after 3 attempts. Last error: $($_.Exception.Message)" + } + + Write-Warning "Package download attempt $attempt failed. Retrying." + Start-Sleep -Seconds (5 * $attempt) + } + } +} + Initialize-OCSentinelTls $installRoot = Join-Path ${env:ProgramFiles} "OCSentinel" @@ -122,7 +155,7 @@ $extractRoot = Join-Path $downloadRoot "payload" New-Item -ItemType Directory -Force -Path $downloadRoot, $extractRoot | Out-Null Write-Host "Downloading artifact: $($manifest.artifactUrl)" -Invoke-WebRequest -Uri ([string]$manifest.artifactUrl) -OutFile $zipPath -TimeoutSec 300 +Get-OCSentinelArtifact -Uri ([string]$manifest.artifactUrl) -DestinationPath $zipPath $actualHash = Get-Sha256Hex -Path $zipPath $expectedHash = ([string]$manifest.sha256).ToLowerInvariant() diff --git a/scripts/bootstrap-ocsentinel-ninja.ps1 b/scripts/bootstrap-ocsentinel-ninja.ps1 index 5372e4e..bec84e8 100644 --- a/scripts/bootstrap-ocsentinel-ninja.ps1 +++ b/scripts/bootstrap-ocsentinel-ninja.ps1 @@ -61,10 +61,52 @@ if ([Enum]::GetNames([Net.SecurityProtocolType]) -contains 'Tls13') { exit `$LASTEXITCODE "@ - & powershell.exe -NoProfile -ExecutionPolicy Bypass -Command $command - $exitCode = $LASTEXITCODE - if ($exitCode -ne 0) { - throw "OCSentinel updater exited with code $exitCode" + for ($attempt = 1; $attempt -le 3; $attempt++) { + & powershell.exe -NoProfile -ExecutionPolicy Bypass -Command $command | ForEach-Object { Write-Host $_ } + $exitCode = $LASTEXITCODE + if ($exitCode -eq 0) { + return + } + + if ($attempt -lt 3) { + Write-Warning "OCSentinel update attempt $attempt failed. Retrying." + Start-Sleep -Seconds (5 * $attempt) + } + } + + throw "OCSentinel updater exited with code $exitCode after 3 attempts." +} + +function Get-OCSentinelArtifact { + param( + [Parameter(Mandatory)][string]$Uri, + [Parameter(Mandatory)][string]$DestinationPath + ) + + $parameters = @{ Uri = $Uri; OutFile = $DestinationPath; TimeoutSec = 300 } + if ((Get-Command Invoke-WebRequest).Parameters.ContainsKey("UseBasicParsing")) { + $parameters.UseBasicParsing = $true + } + + for ($attempt = 1; $attempt -le 3; $attempt++) { + try { + Remove-Item -LiteralPath $DestinationPath -Force -ErrorAction SilentlyContinue + Invoke-WebRequest @parameters + + if (-not (Test-Path -LiteralPath $DestinationPath) -or (Get-Item -LiteralPath $DestinationPath).Length -eq 0) { + throw "The downloaded artifact is empty." + } + + return + } + catch { + if ($attempt -eq 3) { + throw "Could not download the OCSentinel package after 3 attempts. Last error: $($_.Exception.Message)" + } + + Write-Warning "Package download attempt $attempt failed. Retrying." + Start-Sleep -Seconds (5 * $attempt) + } } } @@ -123,7 +165,7 @@ else { try { New-Item -ItemType Directory -Force -Path $extractRoot | Out-Null Write-Host "Downloading OCSentinel $($manifest.version)" - Invoke-WebRequest -Uri ([string]$manifest.artifactUrl) -OutFile $zipPath -TimeoutSec 300 + Get-OCSentinelArtifact -Uri ([string]$manifest.artifactUrl) -DestinationPath $zipPath $actualHash = (Get-FileHash -LiteralPath $zipPath -Algorithm SHA256).Hash.ToLowerInvariant() $expectedHash = ([string]$manifest.sha256).ToLowerInvariant() diff --git a/src/OCSentinelCli/OCSentinelCli.csproj b/src/OCSentinelCli/OCSentinelCli.csproj index e63f5a6..0cbc088 100644 --- a/src/OCSentinelCli/OCSentinelCli.csproj +++ b/src/OCSentinelCli/OCSentinelCli.csproj @@ -9,10 +9,10 @@ OCSentinelCli OfficeCom Sentinel OfficeCom - 1.3.6 - 1.3.6.0 - 1.3.6.0 - 1.3.6 + 1.3.7 + 1.3.7.0 + 1.3.7.0 + 1.3.7