From ffecc34be990b8650379d5e99dedbfebff1488d9 Mon Sep 17 00:00:00 2001 From: Allen Houchins <32207388+allenhouchins@users.noreply.github.com> Date: Mon, 23 Feb 2026 09:29:50 -0600 Subject: [PATCH] Add Okta Verify as a Windows FMA (#40281) This pull request adds support for managing the Okta Verify app on Windows via the maintained apps system. It introduces new ingestion logic for handling WiX Burn installers, adds input and output definitions for Okta Verify, and provides install/uninstall scripts tailored for EXE-based (Burn) installers. The changes also ensure Okta Verify is properly listed and categorized in the maintained apps outputs. **Okta Verify Windows app support:** * Added a new input definition for Okta Verify on Windows, including installer details and categorization in `ee/maintained-apps/inputs/winget/okta-verify.json`. * Added install (`okta_verify_install.ps1`) and uninstall (`okta_verify_uninstall.ps1`) PowerShell scripts for Okta Verify, supporting silent installation/uninstallation for EXE/Burn installers. [[1]](diffhunk://#diff-fa86938dc330e2678c50210585ea8885283546dc370017fd6f3996f12af284b9R1-R27) [[2]](diffhunk://#diff-944cc7275484b5010c66369e563c3d09a618d67295da5221e945aebc42b033dcR1-R96) * Added Okta Verify Windows app entry to the maintained apps output (`apps.json`) and created a detailed output file with version, installer URL, scripts, and detection query in `outputs/okta-verify/windows.json`. [[1]](diffhunk://#diff-4c1446cfc02c6bb0bda874481e333c65b84e184fcea52f656b49a6489f73c9c2R1145-R1151) [[2]](diffhunk://#diff-0c852c8b0817f497526b3eb76c2074cece7ed002f5ffa6a2ea7771affdd90f52R1-R21) **Improvements to installer ingestion logic:** * Updated the Winget ingester to recognize "burn" (WiX Burn bootstrapper) as an installer type and normalize it to "exe" for processing, ensuring correct handling of Burn-based installers. [[1]](diffhunk://#diff-eb6c4ae7be41e61a2292c4240de750809d40c0686fb01f80f52df056ebc9c2a8R488) [[2]](diffhunk://#diff-eb6c4ae7be41e61a2292c4240de750809d40c0686fb01f80f52df056ebc9c2a8R223-R227) --- .../ingesters/winget/ingester.go | 6 ++ .../inputs/winget/okta-verify.json | 12 +++ .../winget/scripts/okta_verify_install.ps1 | 27 ++++++ .../winget/scripts/okta_verify_uninstall.ps1 | 96 +++++++++++++++++++ ee/maintained-apps/outputs/apps.json | 7 ++ .../outputs/okta-verify/windows.json | 21 ++++ 6 files changed, 169 insertions(+) create mode 100644 ee/maintained-apps/inputs/winget/okta-verify.json create mode 100644 ee/maintained-apps/inputs/winget/scripts/okta_verify_install.ps1 create mode 100644 ee/maintained-apps/inputs/winget/scripts/okta_verify_uninstall.ps1 create mode 100644 ee/maintained-apps/outputs/okta-verify/windows.json diff --git a/ee/maintained-apps/ingesters/winget/ingester.go b/ee/maintained-apps/ingesters/winget/ingester.go index d205503c9f..386383c1b5 100644 --- a/ee/maintained-apps/ingesters/winget/ingester.go +++ b/ee/maintained-apps/ingesters/winget/ingester.go @@ -219,6 +219,11 @@ func (i *wingetIngester) ingestOne(ctx context.Context, input inputApp) (*mainta installerType = installerTypeMSI } + // Normalize burn (WiX Burn bootstrapper) to exe since burn produces EXE bundles + if installerType == installerTypeBurn { + installerType = installerTypeExe + } + scope := m.Scope if scope == "" { scope = installer.Scope @@ -479,6 +484,7 @@ const ( installerTypeWix = "wix" installerTypeNullSoft = "nullsoft" installerTypeInno = "inno" + installerTypeBurn = "burn" arch64Bit = "x64" arch32Bit = "x86" ) diff --git a/ee/maintained-apps/inputs/winget/okta-verify.json b/ee/maintained-apps/inputs/winget/okta-verify.json new file mode 100644 index 0000000000..2cbae1677a --- /dev/null +++ b/ee/maintained-apps/inputs/winget/okta-verify.json @@ -0,0 +1,12 @@ +{ + "name": "Okta Verify", + "slug": "okta-verify/windows", + "package_identifier": "Okta.OktaVerify", + "unique_identifier": "Okta Verify", + "install_script_path": "ee/maintained-apps/inputs/winget/scripts/okta_verify_install.ps1", + "uninstall_script_path": "ee/maintained-apps/inputs/winget/scripts/okta_verify_uninstall.ps1", + "installer_arch": "x86", + "installer_type": "exe", + "installer_scope": "machine", + "default_categories": ["Productivity"] +} diff --git a/ee/maintained-apps/inputs/winget/scripts/okta_verify_install.ps1 b/ee/maintained-apps/inputs/winget/scripts/okta_verify_install.ps1 new file mode 100644 index 0000000000..3bb090659c --- /dev/null +++ b/ee/maintained-apps/inputs/winget/scripts/okta_verify_install.ps1 @@ -0,0 +1,27 @@ +# Learn more about .exe install scripts: +# http://fleetdm.com/learn-more-about/exe-install-scripts + +$exeFilePath = "${env:INSTALLER_PATH}" + +try { + +# WiX Burn bootstrapper uses /quiet for silent installation +$processOptions = @{ + FilePath = "$exeFilePath" + ArgumentList = "/quiet /norestart" + PassThru = $true + Wait = $true +} + +# Start process and track exit code +$process = Start-Process @processOptions +$exitCode = $process.ExitCode + +# Prints the exit code +Write-Host "Install exit code: $exitCode" +Exit $exitCode + +} catch { + Write-Host "Error: $_" + Exit 1 +} diff --git a/ee/maintained-apps/inputs/winget/scripts/okta_verify_uninstall.ps1 b/ee/maintained-apps/inputs/winget/scripts/okta_verify_uninstall.ps1 new file mode 100644 index 0000000000..faf25b164f --- /dev/null +++ b/ee/maintained-apps/inputs/winget/scripts/okta_verify_uninstall.ps1 @@ -0,0 +1,96 @@ +# Fleet extracts name from installer (EXE) and saves it to PACKAGE_ID +# variable +$softwareName = $PACKAGE_ID + +# It is recommended to use exact software name here if possible to avoid +# uninstalling unintended software. +$softwareNameLike = "*Okta Verify*" + +# WiX Burn bootstrapper uses /quiet for silent uninstall +$uninstallArgs = "/quiet /norestart" + +$paths = @( + 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', + 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' +) + +$exitCode = 0 + +try { + +[array]$uninstallKeys = Get-ChildItem ` + -Path $paths ` + -ErrorAction SilentlyContinue | + ForEach-Object { Get-ItemProperty $_.PSPath } + +$foundUninstaller = $false +foreach ($key in $uninstallKeys) { + # If needed, add -notlike to the comparison to exclude certain similar + # software + if ($key.DisplayName -like $softwareNameLike) { + $foundUninstaller = $true + # Get the uninstall command. Some uninstallers do not include + # 'QuietUninstallString' and require a flag to run silently. + $uninstallCommand = if ($key.QuietUninstallString) { + $key.QuietUninstallString + } else { + $key.UninstallString + } + + # The uninstall command may contain command and args, like: + # "C:\Program Files\Software\uninstall.exe" /quiet + # Split the command and args + $splitArgs = $uninstallCommand.Split('"') + if ($splitArgs.Length -gt 1) { + if ($splitArgs.Length -eq 3) { + $existingArgs = $splitArgs[2].Trim() + if ($existingArgs -notmatch '/quiet') { + $uninstallArgs = "$existingArgs /quiet /norestart".Trim() + } else { + $uninstallArgs = $existingArgs + } + } elseif ($splitArgs.Length -gt 3) { + Throw ` + "Uninstall command contains multiple quoted strings. " + + "Please update the uninstall script.`n" + + "Uninstall command: $uninstallCommand" + } + $uninstallCommand = $splitArgs[1] + } else { + if ($uninstallCommand -notmatch '/quiet') { + $uninstallArgs = "/quiet /norestart" + } else { + $uninstallArgs = "" + } + } + Write-Host "Uninstall command: $uninstallCommand" + Write-Host "Uninstall args: $uninstallArgs" + + $processOptions = @{ + FilePath = $uninstallCommand + PassThru = $true + Wait = $true + } + + if ($uninstallArgs -ne '') { + $processOptions.ArgumentList = $uninstallArgs + } + + $process = Start-Process @processOptions + $exitCode = $process.ExitCode + Write-Host "Uninstall exit code: $exitCode" + break + } +} + +if (-not $foundUninstaller) { + Write-Host "Uninstall entry not found for $softwareNameLike" + Exit 0 +} + +Exit $exitCode + +} catch { + Write-Host "Error: $_" + Exit 1 +} diff --git a/ee/maintained-apps/outputs/apps.json b/ee/maintained-apps/outputs/apps.json index ccb5d85571..905f8b9ce4 100644 --- a/ee/maintained-apps/outputs/apps.json +++ b/ee/maintained-apps/outputs/apps.json @@ -1142,6 +1142,13 @@ "unique_identifier": "com.okta.mobile", "description": "Okta Verify is a multi-factor authentication app that provides secure identity verification and passwordless sign-in for users accessing Okta-protected applications." }, + { + "name": "Okta Verify", + "slug": "okta-verify/windows", + "platform": "windows", + "unique_identifier": "Okta Verify", + "description": "Okta Verify is a multi-factor authentication app that provides secure identity verification and passwordless sign-in for users accessing Okta-protected applications." + }, { "name": "OmniGraffle", "slug": "omnigraffle/darwin", diff --git a/ee/maintained-apps/outputs/okta-verify/windows.json b/ee/maintained-apps/outputs/okta-verify/windows.json new file mode 100644 index 0000000000..a4f724b9e0 --- /dev/null +++ b/ee/maintained-apps/outputs/okta-verify/windows.json @@ -0,0 +1,21 @@ +{ + "versions": [ + { + "version": "6.6.2.0", + "queries": { + "exists": "SELECT 1 FROM programs WHERE name = 'Okta Verify' AND publisher = 'Okta, Inc.';" + }, + "installer_url": "https://altana-ai.okta.com/api/v1/artifacts/WINDOWS_OKTA_VERIFY/download?releaseChannel=GA&packageType=EXE", + "install_script_ref": "7aad0ea1", + "uninstall_script_ref": "a2c97606", + "sha256": "4e21d4c33a7684f77c75acd4d81f7495ea961bfab1bc77c4d27c503419407a42", + "default_categories": [ + "Productivity" + ] + } + ], + "refs": { + "7aad0ea1": "# Learn more about .exe install scripts:\n# http://fleetdm.com/learn-more-about/exe-install-scripts\n\n$exeFilePath = \"${env:INSTALLER_PATH}\"\n\ntry {\n\n# WiX Burn bootstrapper uses /quiet for silent installation\n$processOptions = @{\n FilePath = \"$exeFilePath\"\n ArgumentList = \"/quiet /norestart\"\n PassThru = $true\n Wait = $true\n}\n\n# Start process and track exit code\n$process = Start-Process @processOptions\n$exitCode = $process.ExitCode\n\n# Prints the exit code\nWrite-Host \"Install exit code: $exitCode\"\nExit $exitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n", + "a2c97606": "# Fleet extracts name from installer (EXE) and saves it to PACKAGE_ID\n# variable\n$softwareName = \"\"\n\n# It is recommended to use exact software name here if possible to avoid\n# uninstalling unintended software.\n$softwareNameLike = \"*Okta Verify*\"\n\n# WiX Burn bootstrapper uses /quiet for silent uninstall\n$uninstallArgs = \"/quiet /norestart\"\n\n$paths = @(\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall',\n 'HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall'\n)\n\n$exitCode = 0\n\ntry {\n\n[array]$uninstallKeys = Get-ChildItem `\n -Path $paths `\n -ErrorAction SilentlyContinue |\n ForEach-Object { Get-ItemProperty $_.PSPath }\n\n$foundUninstaller = $false\nforeach ($key in $uninstallKeys) {\n # If needed, add -notlike to the comparison to exclude certain similar\n # software\n if ($key.DisplayName -like $softwareNameLike) {\n $foundUninstaller = $true\n # Get the uninstall command. Some uninstallers do not include\n # 'QuietUninstallString' and require a flag to run silently.\n $uninstallCommand = if ($key.QuietUninstallString) {\n $key.QuietUninstallString\n } else {\n $key.UninstallString\n }\n\n # The uninstall command may contain command and args, like:\n # \"C:\\Program Files\\Software\\uninstall.exe\" /quiet\n # Split the command and args\n $splitArgs = $uninstallCommand.Split('\"')\n if ($splitArgs.Length -gt 1) {\n if ($splitArgs.Length -eq 3) {\n $existingArgs = $splitArgs[2].Trim()\n if ($existingArgs -notmatch '/quiet') {\n $uninstallArgs = \"$existingArgs /quiet /norestart\".Trim()\n } else {\n $uninstallArgs = $existingArgs\n }\n } elseif ($splitArgs.Length -gt 3) {\n Throw `\n \"Uninstall command contains multiple quoted strings. \" +\n \"Please update the uninstall script.`n\" +\n \"Uninstall command: $uninstallCommand\"\n }\n $uninstallCommand = $splitArgs[1]\n } else {\n if ($uninstallCommand -notmatch '/quiet') {\n $uninstallArgs = \"/quiet /norestart\"\n } else {\n $uninstallArgs = \"\"\n }\n }\n Write-Host \"Uninstall command: $uninstallCommand\"\n Write-Host \"Uninstall args: $uninstallArgs\"\n\n $processOptions = @{\n FilePath = $uninstallCommand\n PassThru = $true\n Wait = $true\n }\n\n if ($uninstallArgs -ne '') {\n $processOptions.ArgumentList = $uninstallArgs\n }\n\n $process = Start-Process @processOptions\n $exitCode = $process.ExitCode\n Write-Host \"Uninstall exit code: $exitCode\"\n break\n }\n}\n\nif (-not $foundUninstaller) {\n Write-Host \"Uninstall entry not found for $softwareNameLike\"\n Exit 0\n}\n\nExit $exitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n" + } +}