diff --git a/changes/50408-steam-patch-policy-bundle-version b/changes/50408-steam-patch-policy-bundle-version new file mode 100644 index 0000000000..cf04fc2849 --- /dev/null +++ b/changes/50408-steam-patch-policy-bundle-version @@ -0,0 +1 @@ +* Fixed the macOS "Steam up to date" patch policy always failing on hosts that have the current version of Steam installed. Steam.app ships without a `CFBundleShortVersionString`, so the generated policy now compares `CFBundleVersion`, which agrees with the version Fleet reports in software inventory. diff --git a/ee/maintained-apps/ingesters/homebrew/ingester.go b/ee/maintained-apps/ingesters/homebrew/ingester.go index 03d098d4c2..dc4b8fb048 100644 --- a/ee/maintained-apps/ingesters/homebrew/ingester.go +++ b/ee/maintained-apps/ingesters/homebrew/ingester.go @@ -250,6 +250,18 @@ func (i *brewIngester) ingestOne(ctx context.Context, input inputApp) (*maintain out.UniqueIdentifier, out.Version, ) } + if input.Token == "steam" { + // Steam.app ships without a CFBundleShortVersionString, so osquery's + // bundle_short_version is empty and version_compare('', '') < 0 is + // always true — the default patch policy can never pass on a host that has + // Steam installed. Compare bundle_version (CFBundleVersion, "6.0", which the + // cask version tracks); that's also the value software inventory falls back + // to, so patch status and inventory agree. + out.Queries.Patched = fmt.Sprintf( + "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = '%s' AND version_compare(bundle_version, '%s') < 0);", + out.UniqueIdentifier, out.Version, + ) + } if input.Token == "firefox@developer-edition" { // The bundle reports only the base version ("153.0") for cask version // "153.0b13", so compare CFBundleVersion (encodes the build date, resolved diff --git a/ee/maintained-apps/ingesters/homebrew/ingester_test.go b/ee/maintained-apps/ingesters/homebrew/ingester_test.go index d701c70ef6..f258f8521a 100644 --- a/ee/maintained-apps/ingesters/homebrew/ingester_test.go +++ b/ee/maintained-apps/ingesters/homebrew/ingester_test.go @@ -87,7 +87,7 @@ func TestIngestValidations(t *testing.T) { Version: "1.0", } - case "ok", "docker-desktop", "swiftdialog", "install_script_path", "uninstall_script_path", "uninstall_script_path_with_pre", "uninstall_script_path_with_post", "patch_policy_path": + case "ok", "docker-desktop", "steam", "swiftdialog", "install_script_path", "uninstall_script_path", "uninstall_script_path_with_pre", "uninstall_script_path_with_post", "patch_policy_path": cask = brewCask{ Token: appToken, Name: []string{appToken}, @@ -145,6 +145,7 @@ func TestIngestValidations(t *testing.T) { {"", inputApp{Token: "docker-desktop", UniqueIdentifier: "com.electron.dockerdesktop", InstallerFormat: "dmg", Name: "Docker Desktop", Slug: "docker-desktop/darwin"}}, {"", inputApp{Token: "firefox@developer-edition", UniqueIdentifier: "org.mozilla.firefoxdeveloperedition", InstallerFormat: "dmg", Name: "Mozilla Firefox Developer Edition", Slug: "firefox@developer-edition/darwin"}}, {"", inputApp{Token: "firefox@nightly", UniqueIdentifier: "org.mozilla.nightly", InstallerFormat: "dmg", Name: "Mozilla Firefox Nightly", Slug: "firefox@nightly/darwin"}}, + {"", inputApp{Token: "steam", UniqueIdentifier: "com.valvesoftware.steam", InstallerFormat: "dmg", Name: "Steam", Slug: "steam/darwin"}}, {"", inputApp{Token: "swiftdialog", UniqueIdentifier: "au.csiro.dialog", InstallerFormat: "pkg", Name: "swiftDialog", Slug: "swiftdialog/darwin"}}, {"", inputApp{Token: "install_script_path", UniqueIdentifier: "abc", InstallerFormat: "pkg", InstallScriptPath: path.Join(tempDir, "install_script.sh")}}, {"", inputApp{Token: "uninstall_script_path", UniqueIdentifier: "abc", InstallerFormat: "pkg", UninstallScriptPath: path.Join(tempDir, "uninstall_script.sh")}}, @@ -200,6 +201,15 @@ func TestIngestValidations(t *testing.T) { "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'org.mozilla.nightly' AND version_compare(bundle_version, '15426.7.17') < 0);", out.Queries.Patched, ) + case "steam": + // Steam.app has no CFBundleShortVersionString, so the patched query + // compares CFBundleVersion; the exists query is unaffected because it + // only matches on bundle identifier. + require.Equal(t, "SELECT 1 FROM apps WHERE bundle_identifier = 'com.valvesoftware.steam';", out.Queries.Exists) + require.Equal(t, + "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.valvesoftware.steam' AND version_compare(bundle_version, '1.0') < 0);", + out.Queries.Patched, + ) case "swiftdialog": require.Equal(t, "SELECT 1 FROM apps WHERE bundle_identifier = 'au.csiro.dialog' AND path != '/opt/orbit/bin/swiftDialog/macos/stable/Dialog.app';", out.Queries.Exists) require.Equal(t, diff --git a/ee/maintained-apps/outputs/steam/darwin.json b/ee/maintained-apps/outputs/steam/darwin.json index f604c5f535..2f2c8460bc 100644 --- a/ee/maintained-apps/outputs/steam/darwin.json +++ b/ee/maintained-apps/outputs/steam/darwin.json @@ -4,7 +4,7 @@ "version": "6.0", "queries": { "exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.valvesoftware.steam';", - "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.valvesoftware.steam' AND version_compare(bundle_short_version, '6.0') < 0);" + "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.valvesoftware.steam' AND version_compare(bundle_version, '6.0') < 0);" }, "installer_url": "https://cdn.cloudflare.steamstatic.com/client/installer/steam.dmg", "install_script_ref": "45a6174b",