Files
pulse/scripts/installtests/install_ps1_test.go
T
rcourtman 2541e4b6a7 Run the Windows installer TLS callback off a compiled type
install.ps1 set ServicePointManager's certificate callback to a
PowerShell scriptblock. ServicePointManager can invoke that callback on
a worker thread that has no runspace, where a scriptblock delegate
fails closed, so agent downloads died with a TLS error even though the
certificate policy would have accepted them (hit by an rc.6 tester with
Skip TLS verification enabled). The copied install command already
migrated to a compiled validator for exactly this reason in rc.6; the
downloaded script now does the same. Validation policy is unchanged,
with fingerprint pinning first, then insecure, then clean chains, then
the custom CA. Verified with pwsh covering all four policy branches
plus the callback running on a runspace-free worker thread.

Contract-Neutral: installer TLS callback implementation moved to a compiled type; same validation policy, no payload or endpoint change
2026-08-02 13:12:17 +01:00

542 lines
20 KiB
Go

package installtests
import (
"os"
"os/exec"
"strings"
"testing"
)
func TestInstallPS1ParsesWithPowerShell(t *testing.T) {
pwsh, err := exec.LookPath("pwsh")
if err != nil {
t.Skip("pwsh not installed")
}
scriptPath := repoFile("scripts", "install.ps1")
cmd := exec.Command(pwsh,
"-NoLogo",
"-NoProfile",
"-NonInteractive",
"-Command",
`$errors = $null; [System.Management.Automation.Language.Parser]::ParseFile($env:PULSE_INSTALL_PS1_PATH, [ref]$null, [ref]$errors) > $null; if ($errors.Count) { $errors | ForEach-Object { Write-Error $_.ToString() }; exit 1 }`,
)
cmd.Env = append(os.Environ(), "PULSE_INSTALL_PS1_PATH="+scriptPath)
if output, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("install.ps1 failed PowerShell parser check: %v\n%s", err, output)
}
}
func TestInstallPS1KeepsTLS13OptionalOnLegacyWindowsPowerShell(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
tls12Fallback := `[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12`
optionalTLS13 := `[Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13`
tls12Index := strings.Index(script, tls12Fallback)
tls13Index := strings.Index(script, optionalTLS13)
if tls12Index == -1 {
t.Fatal("install.ps1 must establish TLS 1.2 before probing optional TLS 1.3 support")
}
if tls13Index == -1 {
t.Fatal("install.ps1 must enable TLS 1.3 when the runtime exposes it")
}
if tls12Index >= tls13Index {
t.Fatal("install.ps1 must establish the TLS 1.2 fallback before referencing the optional TLS 1.3 enum")
}
compatibilityBlock := script[tls12Index:tls13Index]
if !strings.Contains(compatibilityBlock, "try {") {
t.Fatal("install.ps1 must guard the optional TLS 1.3 enum behind a compatibility try block")
}
if !strings.Contains(script[tls13Index:], "} catch {") {
t.Fatal("install.ps1 must retain TLS 1.2 when the optional TLS 1.3 enum is unavailable")
}
}
func TestWindowsAgentLifecycleHarnessParsesWithPowerShell(t *testing.T) {
pwsh, err := exec.LookPath("pwsh")
if err != nil {
t.Skip("pwsh not installed")
}
scriptPath := repoFile("scripts", "installtests", "windows_agent_lifecycle.ps1")
cmd := exec.Command(pwsh,
"-NoLogo",
"-NoProfile",
"-NonInteractive",
"-Command",
`$errors = $null; [System.Management.Automation.Language.Parser]::ParseFile($env:PULSE_WINDOWS_LIFECYCLE_PATH, [ref]$null, [ref]$errors) > $null; if ($errors.Count) { $errors | ForEach-Object { Write-Error $_.ToString() }; exit 1 }`,
)
cmd.Env = append(os.Environ(), "PULSE_WINDOWS_LIFECYCLE_PATH="+scriptPath)
if output, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("Windows lifecycle harness failed PowerShell parser check: %v\n%s", err, output)
}
}
func TestWindowsAgentLifecycleHarnessPinsCompleteServiceProof(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "installtests", "windows_agent_lifecycle.ps1"))
if err != nil {
t.Fatalf("read Windows lifecycle harness: %v", err)
}
script := string(content)
required := []string{
`[ValidateSet('Full', 'InstallUpdate', 'PostRebootUninstall')]`,
`Pass -ConfirmLifecycleMutation`,
`-PreflightOnly ` + "`" + `$true`,
`Assert-AgentRuntime -ExpectedVersion $versionV1`,
`Assert-AgentRuntime -ExpectedVersion $versionV2`,
`Assert-CrashRecovery -ExpectedVersion $versionV2`,
`Post-reboot persistence and uninstall proof passed.`,
`PulseAgent service still exists after uninstall.`,
`Pulse Agent state directory still exists after uninstall.`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("Windows lifecycle harness missing proof contract: %s", needle)
}
}
}
func TestNativeWindowsSelfTestDoesNotPreseedLifecycleState(t *testing.T) {
content, err := os.ReadFile(repoFile(".github", "workflows", "unified-agent-native.yml"))
if err != nil {
t.Fatalf("read native agent workflow: %v", err)
}
workflow := string(content)
required := []string{
`$selfTestStateDir = Join-Path $env:RUNNER_TEMP 'pulse-agent-self-test'`,
`$selfTestLogFile = Join-Path $selfTestStateDir 'pulse-agent.log'`,
`--self-test --state-dir $selfTestStateDir --log-file $selfTestLogFile`,
`Get-Service -Name 'PulseAgent' -ErrorAction SilentlyContinue`,
`$lifecycleStateDir = Join-Path $env:ProgramData 'Pulse'`,
`Remove-Item -Path $lifecycleStateDir -Recurse -Force`,
}
for _, needle := range required {
if !strings.Contains(workflow, needle) {
t.Fatalf("native Windows self-test must keep lifecycle state isolated: %s", needle)
}
}
}
func TestNativeWindowsExecutesGeneratedInstallCommand(t *testing.T) {
content, err := os.ReadFile(repoFile(".github", "workflows", "unified-agent-native.yml"))
if err != nil {
t.Fatalf("read native agent workflow: %v", err)
}
workflow := string(content)
for _, needle := range []string{
`frontend-modern/src/utils/agentInstallCommand.ts`,
`Execute generated command with Windows PowerShell 5.1`,
`agentInstallCommand.windows.test.ts`,
} {
if !strings.Contains(workflow, needle) {
t.Fatalf("native Windows workflow missing generated install-command proof: %s", needle)
}
}
}
func TestInstallPS1OwnsWindowsServiceLoggingAndRecovery(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`$ServiceArgs += @("--log-file", "` + "`" + `"$LogFile` + "`" + `"")`,
`"--state-dir", "` + "`" + `"$StateDir` + "`" + `"`,
`$scOutput = sc.exe failure $AgentName reset= 86400 actions= restart/5000/restart/5000/restart/5000`,
`Show-Error "Failed to configure service recovery actions: $scOutput"`,
`$scOutput = sc.exe failureflag $AgentName 1`,
`Show-Error "Failed to enable service recovery for non-crash failures: $scOutput"`,
`$logReady = (Test-Path $LogFile) -and ((Get-Item $LogFile).Length -gt 0)`,
`if ($response.StatusCode -eq 200 -and $logReady)`,
`Installation did not reach a healthy, logged runtime.`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing Windows service logging/recovery contract: %s", needle)
}
}
}
func TestInstallPS1DockerModeDefaultsHostOff(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`if ($EnableDocker -and -not $PSBoundParameters.ContainsKey('EnableHost') -and [string]::IsNullOrWhiteSpace($env:PULSE_ENABLE_HOST)) {`,
`$EnableHost = $false`,
`if ($EnableHost) { $ServiceArgs += "--enable-host" } else { $ServiceArgs += "--enable-host=false" }`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing docker/host parity guard: %s", needle)
}
}
}
func TestInstallPS1PersistsAndVerifiesServerFingerprint(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`[string]$ServerFingerprint = $env:PULSE_SERVER_FINGERPRINT,`,
`sha256.ComputeHash(certificate.GetRawCertData())`,
`$lines += "PULSE_SERVER_FINGERPRINT='$ServerFingerprint'"`,
`$ServerFingerprint = Get-ConnectionStateValue "PULSE_SERVER_FINGERPRINT"`,
`$ServiceArgs += @("--server-fingerprint", "` + "`" + `"$ServerFingerprint` + "`" + `"")`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing server-fingerprint lifecycle contract: %s", needle)
}
}
}
func TestInstallPS1PreservesObserverDestinationConfig(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`[string]$ObserversFile = $env:PULSE_OBSERVERS_FILE,`,
`$lines += "PULSE_OBSERVERS_FILE='$ObserversFile'"`,
`[System.IO.Path]::IsPathRooted($ObserversFile)`,
`Test-Path $ObserversFile -PathType Leaf`,
`$ServiceArgs += @("--observers-file", "` + "`" + `"$ObserversFile` + "`" + `"")`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing observer-config lifecycle contract: %s", needle)
}
}
}
func TestInstallPS1AllowsMissingTokenForOptionalAuth(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`[string]$TokenFile = $env:PULSE_TOKEN_FILE,`,
`if (-not [string]::IsNullOrWhiteSpace($Token) -and -not (Test-ValidToken $Token)) {`,
`if ([string]::IsNullOrWhiteSpace($Token) -and -not [string]::IsNullOrWhiteSpace($TokenFile)) {`,
`$Token = (Get-Content -Path $resolvedTokenFile -Raw -ErrorAction Stop).Trim()`,
`function Write-RuntimeTokenFile {`,
`if (-not [string]::IsNullOrWhiteSpace($Token)) { $ServiceArgs += @("--token-file", "` + "`" + `"$TokenFilePath` + "`" + `"") }`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing optional-token handling: %s", needle)
}
}
}
func TestInstallPS1AgentDownloadIsServerVersionAware(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`Invoke-WebRequest -Uri "$Url/api/version"`,
`$versionInfo = $versionResponse.Content | ConvertFrom-Json`,
`$ServerVersion = [string]$versionInfo.version`,
`$escapedServerVersion = [Uri]::EscapeDataString($ServerVersion)`,
`$DownloadUrl = "$DownloadUrl&serverVersion=$escapedServerVersion"`,
`downloaded agent version ($DownloadedVersion) does not match Pulse server version ($ServerVersion)`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing version-aware agent download behavior: %s", needle)
}
}
}
func TestInstallPS1AllowsOptionalAuthUninstallWithoutToken(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`if (-not [string]::IsNullOrWhiteSpace($Url)) {`,
`$invokeArgs = @{`,
`if (-not [string]::IsNullOrWhiteSpace($Token)) {`,
`$invokeArgs.Headers = @{ "X-API-Token" = $Token }`,
`Invoke-RestMethod @invokeArgs | Out-Null`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing optional-auth uninstall handling: %s", needle)
}
}
}
func TestInstallPS1PreservesProxmoxProfileParity(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`[bool]$EnableProxmox = $false,`,
`[string]$ProxmoxType = "",`,
`if (-not $PSBoundParameters.ContainsKey('EnableProxmox') -and -not [string]::IsNullOrWhiteSpace($env:PULSE_ENABLE_PROXMOX)) {`,
`$EnableProxmox = Parse-Bool $env:PULSE_ENABLE_PROXMOX $EnableProxmox`,
`if (-not $PSBoundParameters.ContainsKey('ProxmoxType') -and -not [string]::IsNullOrWhiteSpace($env:PULSE_PROXMOX_TYPE)) {`,
`$ProxmoxType = $env:PULSE_PROXMOX_TYPE`,
`if ($EnableProxmox) { $ServiceArgs += "--enable-proxmox" }`,
`if (-not [string]::IsNullOrWhiteSpace($NormalizedProxmoxType)) { $ServiceArgs += @("--proxmox-type", "` + "`" + `"$NormalizedProxmoxType` + "`" + `"") }`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing proxmox profile parity: %s", needle)
}
}
}
func TestInstallPS1PreservesCommandExecutionParity(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`[bool]$EnableCommands = $false,`,
`if (-not $PSBoundParameters.ContainsKey('EnableCommands') -and -not [string]::IsNullOrWhiteSpace($env:PULSE_ENABLE_COMMANDS)) {`,
`$EnableCommands = Parse-Bool $env:PULSE_ENABLE_COMMANDS $EnableCommands`,
`if ($EnableCommands) { $ServiceArgs += "--enable-commands" }`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing command-execution parity: %s", needle)
}
}
}
func TestInstallPS1UsesInsecureTlsForRuntimeTransport(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`function Invoke-WithOptionalInsecureTls {`,
`$needsCallback = $AllowInsecure -or $null -ne $CustomCaCertificate -or -not [string]::IsNullOrWhiteSpace($ServerFingerprint)`,
// The callback must be a compiled delegate, not a scriptblock:
// ServicePointManager can invoke it on a worker thread with no
// PowerShell runspace, where a scriptblock fails closed.
`[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [PulseAgentInstallTlsValidator]::Callback`,
`[PulseAgentInstallTlsValidator]::AllowInsecure = $AllowInsecure`,
`if ($Url.ToLowerInvariant().StartsWith("http://") -and -not $Insecure) {`,
`Plain HTTP Pulse URL detected; enabling insecure mode for persisted agent update checks.`,
`Invoke-WithOptionalInsecureTls -AllowInsecure $Insecure -CustomCaCertificate $CustomCaCertificate -Action {`,
`Invoke-RestMethod @invokeArgs | Out-Null`,
`$downloadTask = $webClient.DownloadFileTaskAsync($DownloadUrl, $TempPath)`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing insecure runtime transport handling: %s", needle)
}
}
}
func TestInstallPS1SupportsDownloadPreflightBeforeAdministratorInstall(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`[bool]$PreflightOnly = $false,`,
`[string]$Output = $env:PULSE_OUTPUT,`,
`[bool]$NonInteractive = $false`,
`if (-not $isAdmin -and -not $PreflightOnly) {`,
`function Write-InstallerEvent {`,
`function Get-ResponseHeaderValue {`,
`function Invoke-AgentDownloadPreflight {`,
`Invoke-WebRequest -Uri $Uri -Method Head -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop`,
`$checksum = Get-ResponseHeaderValue -Headers $preflightResponse.Headers -Name "X-Checksum-Sha256"`,
`$downloadPreflightResponse = Invoke-WithOptionalInsecureTls -AllowInsecure $Insecure -CustomCaCertificate $CustomCaCertificate -Action {`,
`Invoke-WebRequest -Uri $DownloadUrl -Method Head -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop`,
`$serverChecksum = Get-ResponseHeaderValue -Headers $downloadPreflightResponse.Headers -Name "X-Checksum-Sha256"`,
`$downloadMetadata = Invoke-WithOptionalInsecureTls -AllowInsecure $Insecure -CustomCaCertificate $CustomCaCertificate -Action {`,
`$downloadChecksum = Get-ResponseHeaderValue -Headers $webClient.ResponseHeaders -Name "X-Checksum-Sha256"`,
`agent_download_checksum_missing`,
`agent_download_available`,
`agent_download_unavailable`,
`if ($PreflightOnly) {`,
`Invoke-AgentDownloadPreflight $DownloadUrl`,
`if (-not $NonInteractive) {`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing download preflight handling: %s", needle)
}
}
}
func TestInstallPS1ReadsAgentIdentityFromEnvironment(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`[string]$AgentId = $env:PULSE_AGENT_ID,`,
`[string]$Hostname = $env:PULSE_HOSTNAME`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing agent identity env handling: %s", needle)
}
}
}
func TestInstallPS1UsesHostnameLookupForUninstallFallback(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`$lookupHostname = $Hostname`,
`$lookupHostname = $env:COMPUTERNAME`,
`Uri = "$Url/api/agents/agent/lookup?hostname=$([System.Uri]::EscapeDataString($lookupHostname))"`,
`$lookupResult = Invoke-WithOptionalInsecureTls -AllowInsecure $Insecure -CustomCaCertificate $customCaCertificate -Action {`,
`Invoke-RestMethod @lookupArgs`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing uninstall hostname lookup fallback: %s", needle)
}
}
}
func TestInstallPS1PersistsAndRecoversConnectionIdentity(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`$ConnectionStatePath = "$StateDir\connection.env"`,
`$TokenFilePath = "$StateDir\token"`,
`Set-Content -Path $ConnectionStatePath -Value ($lines -join "` + "`n" + `") -Encoding UTF8`,
`$lines += "PULSE_TOKEN_FILE='$TokenFilePath'"`,
`$Url = Get-ConnectionStateValue "PULSE_URL"`,
`$Token = Get-ConnectionStateValue "PULSE_TOKEN"`,
`$savedTokenFile = Get-ConnectionStateValue "PULSE_TOKEN_FILE"`,
`$AgentId = Get-ConnectionStateValue "PULSE_AGENT_ID"`,
`$Hostname = Get-ConnectionStateValue "PULSE_HOSTNAME"`,
`$Insecure = Parse-Bool (Get-ConnectionStateValue "PULSE_INSECURE_SKIP_VERIFY") $Insecure`,
`$CACertPath = Get-ConnectionStateValue "PULSE_CACERT"`,
`$lines += "PULSE_INSECURE_SKIP_VERIFY='true'"`,
`$lines += "PULSE_CACERT='$CACertPath'"`,
`Write-RuntimeTokenFile`,
`Save-ConnectionState`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing persisted connection identity handling: %s", needle)
}
}
}
func TestInstallPS1SupportsCustomCATransport(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`[string]$CACertPath = $env:PULSE_CACERT,`,
`function Load-CustomCaCertificate {`,
`return [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($resolvedPath)`,
`public static class PulseAgentInstallTlsValidator`,
`candidateChain.ChainPolicy.ExtraStore.Add(CustomCa);`,
`Invoke-WithOptionalInsecureTls -AllowInsecure $Insecure -CustomCaCertificate $CustomCaCertificate -Action {`,
`Show-Error "Invalid CA certificate path. File does not exist.`,
`Show-Error "Invalid CA certificate file. Provide a PEM, CRT, or CER certificate.`,
`if (-not [string]::IsNullOrWhiteSpace($CACertPath)) { $ServiceArgs += @("--cacert", "` + "`" + `"$CACertPath` + "`" + `"") }`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing custom CA transport handling: %s", needle)
}
}
}
func TestInstallPS1ClearsPersistedStateAfterUninstall(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`if (Test-Path $StateDir) {`,
`Remove-Item $StateDir -Recurse -Force -ErrorAction SilentlyContinue`,
`Write-Host "Uninstallation complete." -ForegroundColor Green`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing persisted state cleanup after uninstall: %s", needle)
}
}
}
func TestInstallPS1RequiresPinnedSignatureVerificationForReleaseDownloads(t *testing.T) {
content, err := os.ReadFile(repoFile("scripts", "install.ps1"))
if err != nil {
t.Fatalf("read install.ps1: %v", err)
}
script := string(content)
required := []string{
`$PinnedInstallerSshPublicKey = "__PULSE_INSTALLER_SSH_PUBLIC_KEY__"`,
`function Test-HasPinnedInstallerSignatureKey {`,
`function Invoke-InstallerSignatureVerification {`,
`Get-Command ssh-keygen.exe -ErrorAction SilentlyContinue`,
`$serverSshSignature = Get-ResponseHeaderValue -Headers $downloadPreflightResponse.Headers -Name $InstallerSignatureHeaderName`,
`Show-Error "Server did not provide checksum header; refusing signed install."`,
`Show-Error "Server did not provide SSH signature header; refusing signed install."`,
`Invoke-InstallerSignatureVerification -FilePath $TempPath -SignatureHeader $serverSshSignature`,
`-Y verify -f`,
}
for _, needle := range required {
if !strings.Contains(script, needle) {
t.Fatalf("install.ps1 missing signed-download verification contract: %s", needle)
}
}
}