Fixed bundle identifier for privileges pkg (#33517)

**Related issue:** Resolves #32083

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)

## Testing

- [x] Added/updated automated tests
- [x] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [x] QA'd all new/changed functionality manually

## Database migrations

- [x] Checked table schema to confirm autoupdate
- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
This commit is contained in:
Konstantin Sykulev
2025-09-26 14:31:31 -05:00
committed by GitHub
parent cfbc9d8829
commit c9f693a77c
7 changed files with 321 additions and 2 deletions
+1
View File
@@ -0,0 +1 @@
* Corrected bundle identifier for privileges macos software pkg and fixed existing software installers to use corrected software title. The privileges application should show the correct status in software inventory.
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<installer-gui-script authoringTool="Packages" authoringToolVersion="1.2.10" authoringToolBuild="732" minSpecVersion="1.0">
<options hostArchitectures="x86_64,arm64"/>
<!--+==========================+
| Presentation |
+==========================+-->
<title>DISTRIBUTION_TITLE</title>
<background file="background" uti="public.png" scaling="proportional" alignment="bottomleft"/>
<background-darkAqua file="background" uti="public.png" scaling="proportional" alignment="bottomleft"/>
<!--+==========================+
| Installer |
+==========================+-->
<choices-outline>
<line choice="installer_choice_1"/>
</choices-outline>
<choice id="installer_choice_1" title="Privileges" description="">
<pkg-ref id="corp.sap.privileges.pkg"/>
</choice>
<!--+==========================+
| Package References |
+==========================+-->
<pkg-ref id="corp.sap.privileges.pkg" version="2.4.0" auth="Root" installKBytes="3905">#Privileges.pkg</pkg-ref>
</installer-gui-script>
+2
View File
@@ -329,6 +329,8 @@ var knownBadNames = map[string]struct{}{
var idTranslations = map[string]string{
"com.sentinelone.sentinel-agent": "com.sentinelone.SentinelAgent",
// This is present in Privileges.pkg/PackageInfo, however, current logic doesn't parse PackageInfo files if Distribution file is present
"corp.sap.privileges.pkg": "corp.sap.privileges",
}
// getDistributionInfo gets the name, bundle identifier and version of a PKG distribution file
+7
View File
@@ -224,6 +224,13 @@ func TestParseRealDistributionFiles(t *testing.T) {
"com.getcoldturkey.blocker-firefox-ext", "com.getcoldturkey.coldturkeyblocker",
},
},
{
file: "distribution-privileges.xml",
expectedName: "Privileges",
expectedVersion: "2.4.0",
expectedBundleID: "corp.sap.privileges",
expectedPackageIDs: []string{"corp.sap.privileges.pkg"},
},
}
for _, tt := range tests {
@@ -0,0 +1,110 @@
package tables
import (
"database/sql"
"fmt"
)
func init() {
MigrationClient.AddMigration(Up_20250926123048, Down_20250926123048)
}
func Up_20250926123048(tx *sql.Tx) error {
// Find incorrect/correct title
titleRows, err := tx.Query(`
SELECT id, bundle_identifier
FROM software_titles
WHERE bundle_identifier IN ('corp.sap.privileges.pkg', 'corp.sap.privileges')
`)
if err != nil {
return err
}
defer titleRows.Close()
bundleIdToTitleId := map[string]string{}
for titleRows.Next() {
var id, bundleIdentifier string
if err := titleRows.Scan(&id, &bundleIdentifier); err != nil {
return err
}
bundleIdToTitleId[bundleIdentifier] = id
}
if err := titleRows.Err(); err != nil {
return err
}
if len(bundleIdToTitleId) == 0 {
// No "Privileges" titles, nothing to do
return nil
}
// If the "Privileges" app has not been indexed by osquery,
// we will not have the correct title/bundle
// so we need to insert it
if _, ok := bundleIdToTitleId["corp.sap.privileges"]; !ok {
res, err := tx.Exec(`
INSERT INTO software_titles (name, source, bundle_identifier) VALUES
('Privileges', 'apps', 'corp.sap.privileges')
`)
if err != nil {
return err
}
lastInsertId, err := res.LastInsertId()
if err != nil {
return err
}
bundleIdToTitleId["corp.sap.privileges"] = fmt.Sprintf("%d", lastInsertId)
}
// Find software installers with incorrect title
installerRows, err := tx.Query(`
SELECT id
FROM software_installers
WHERE title_id = ?
AND extension = 'pkg'
`, bundleIdToTitleId["corp.sap.privileges.pkg"])
if err != nil {
return err
}
defer installerRows.Close()
var softwareInstallerIds []string
for installerRows.Next() {
var id string
if err := installerRows.Scan(&id); err != nil {
return err
}
softwareInstallerIds = append(softwareInstallerIds, id)
}
if err := installerRows.Err(); err != nil {
return err
}
// Update software installers to point to correct title
for _, softwareInstallerId := range softwareInstallerIds {
if _, err := tx.Exec(`
UPDATE software_installers
SET title_id = ?
WHERE id = ?
`, bundleIdToTitleId["corp.sap.privileges"], softwareInstallerId); err != nil {
return err
}
}
// Delete incorrect title if exists
if incorrectTitleId, ok := bundleIdToTitleId["corp.sap.privileges.pkg"]; ok {
if _, err := tx.Exec(`
DELETE FROM software_titles
WHERE id = ?
`, incorrectTitleId); err != nil {
return err
}
}
return nil
}
func Down_20250926123048(tx *sql.Tx) error {
return nil
}
@@ -0,0 +1,176 @@
package tables
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
func TestUp_20250926123048_NoPrivileges(t *testing.T) {
db := applyUpToPrev(t)
userId := execNoErrLastID(t, db, `INSERT INTO users (name, email, password, salt) VALUES (?, ?, ?, ?)`, "Alice", "alice@example.com", "password", "salt")
installScriptID := execNoErrLastID(t, db, `INSERT INTO script_contents (md5_checksum, contents) VALUES (?, ?)`, "a", "echo 'install script'")
uninstallScriptID := execNoErrLastID(t, db, `INSERT INTO script_contents (md5_checksum, contents) VALUES (?, ?)`, "b", "echo 'uninstall script'")
titleId := execNoErrLastID(t, db, `
INSERT INTO software_titles (name, source, bundle_identifier) VALUES
('Some App', 'apps', 'com.some.app')
`)
_ = execNoErrLastID(t, db, `
INSERT INTO software_installers (title_id, filename, version, platform, install_script_content_id, storage_id, user_id, user_name, user_email, url, package_ids, extension, uninstall_script_content_id, updated_at, fleet_maintained_app_id, install_during_setup, upgrade_code) VALUES
((SELECT id FROM software_titles WHERE bundle_identifier = 'com.some.app'), 'some_app_installer.pkg', '1.0.0', 'darwin', ?, 'dummysha256', ?, 'Alice', 'alice@example.com', '', 'com.some.app.pkg', 'pkg', ?, NOW(), NULL, 0, '')
`, installScriptID, userId, uninstallScriptID)
applyNext(t, db)
var count int
err := db.Get(&count, `
SELECT count(1) FROM
software_titles
WHERE bundle_identifier = 'corp.sap.privileges'
`)
require.NoError(t, err)
require.Equal(t, 0, count, "expected 'corp.sap.privileges' not to be inserted into software_titles")
err = db.Get(&count, `
SELECT count(1)
FROM software_installers
WHERE title_id = ?
`, titleId)
require.NoError(t, err)
require.Equal(t, 1, count, "expected existing software installer to remain unchanged")
}
func TestUp_20250926123048_NoIndexedPrivileges(t *testing.T) {
db := applyUpToPrev(t)
userId := execNoErrLastID(t, db, `INSERT INTO users (name, email, password, salt) VALUES (?, ?, ?, ?)`, "Alice", "alice@example.com", "password", "salt")
installScriptID := execNoErrLastID(t, db, `INSERT INTO script_contents (md5_checksum, contents) VALUES (?, ?)`, "a", "echo 'install script'")
uninstallScriptID := execNoErrLastID(t, db, `INSERT INTO script_contents (md5_checksum, contents) VALUES (?, ?)`, "b", "echo 'uninstall script'")
titleId := execNoErrLastID(t, db, `
INSERT INTO software_titles (name, source, bundle_identifier) VALUES
('Privileges', 'apps', 'corp.sap.privileges.pkg')
`)
_ = execNoErrLastID(t, db, `
INSERT INTO software_installers (title_id, filename, version, platform, install_script_content_id, storage_id, self_service, user_id, user_name, user_email, url, package_ids, extension, uninstall_script_content_id, updated_at, fleet_maintained_app_id, install_during_setup, upgrade_code) VALUES
(?, 'Privileges_2.0.0.pkg', '2.0.0', 'darwin', ?, 'e18bde3e9c86ff5161e193976c68b29fded2fe91a058ec0c336827166d962989', 1, ?, 'Alice', 'alice@example.com', '', 'corp.sap.privileges.pkg', 'pkg', ?, NOW(), NULL, 0, '')
`, titleId, installScriptID, userId, uninstallScriptID)
var count int
err := db.Get(&count, `
SELECT count(1) FROM
software_titles
WHERE bundle_identifier = 'corp.sap.privileges'
`)
require.NoError(t, err)
require.Equal(t, 0, count, "did not expect 'corp.sap.privileges' to be present into software_titles")
applyNext(t, db)
titleRows, err := db.Query(`
SELECT id, bundle_identifier
FROM software_titles
WHERE bundle_identifier IN ('corp.sap.privileges.pkg', 'corp.sap.privileges')
`)
require.NoError(t, err)
defer titleRows.Close()
bundleIdToTitleId := map[string]string{}
for titleRows.Next() {
var id int
var bundleId string
if err := titleRows.Scan(&id, &bundleId); err != nil {
require.NoError(t, err)
}
bundleIdToTitleId[bundleId] = fmt.Sprintf("%d", id)
}
require.NoError(t, titleRows.Err())
require.Contains(t, bundleIdToTitleId, "corp.sap.privileges", "expected 'corp.sap.privileges' to be inserted into software_titles")
require.NotContains(t, bundleIdToTitleId, "corp.sap.privileges.pkg", "expected 'corp.sap.privileges.pkg' to be deleted from software_titles")
installerRows, err := db.Query(`
SELECT title_id
FROM software_installers
`)
require.NoError(t, err)
defer installerRows.Close()
var softwareInstallerTitleIds []string
for installerRows.Next() {
var titleId string
if err := installerRows.Scan(&titleId); err != nil {
require.NoError(t, err)
}
softwareInstallerTitleIds = append(softwareInstallerTitleIds, titleId)
}
require.NoError(t, installerRows.Err())
require.Len(t, softwareInstallerTitleIds, 1)
require.Equal(t, bundleIdToTitleId["corp.sap.privileges"], softwareInstallerTitleIds[0], "expected existing software installer to point to correct software title")
}
func TestUp_20250926123048_IndexedPrivileges(t *testing.T) {
db := applyUpToPrev(t)
userId := execNoErrLastID(t, db, `INSERT INTO users (name, email, password, salt) VALUES (?, ?, ?, ?)`, "Alice", "alice@example.com", "password", "salt")
installScriptID := execNoErrLastID(t, db, `INSERT INTO script_contents (md5_checksum, contents) VALUES (?, ?)`, "a", "echo 'install script'")
uninstallScriptID := execNoErrLastID(t, db, `INSERT INTO script_contents (md5_checksum, contents) VALUES (?, ?)`, "b", "echo 'uninstall script'")
incorrectTitleId := execNoErrLastID(t, db, `
INSERT INTO software_titles (name, source, bundle_identifier) VALUES
('Privileges', 'apps', 'corp.sap.privileges.pkg')
`)
correctTitleId := execNoErrLastID(t, db, `
INSERT INTO software_titles (name, source, bundle_identifier) VALUES
('Privileges', 'apps', 'corp.sap.privileges')
`)
_ = execNoErrLastID(t, db, `
INSERT INTO software_installers (title_id, filename, version, platform, install_script_content_id, storage_id, self_service, user_id, user_name, user_email, url, package_ids, extension, uninstall_script_content_id, updated_at, fleet_maintained_app_id, install_during_setup, upgrade_code) VALUES
(?, 'Privileges_2.0.0.pkg', '2.0.0', 'darwin', ?, 'e18bde3e9c86ff5161e193976c68b29fded2fe91a058ec0c336827166d962989', 1, ?, 'Alice', 'alice@example.com', '', 'corp.sap.privileges.pkg', 'pkg', ?, NOW(), NULL, 0, '')
`, incorrectTitleId, installScriptID, userId, uninstallScriptID)
applyNext(t, db)
titleRows, err := db.Query(`
SELECT id, bundle_identifier
FROM software_titles
WHERE bundle_identifier IN ('corp.sap.privileges.pkg', 'corp.sap.privileges')
`)
require.NoError(t, err)
defer titleRows.Close()
bundleIdToTitleId := map[string]string{}
for titleRows.Next() {
var id int
var bundleId string
if err := titleRows.Scan(&id, &bundleId); err != nil {
require.NoError(t, err)
}
bundleIdToTitleId[bundleId] = fmt.Sprintf("%d", id)
}
require.NoError(t, titleRows.Err())
require.Contains(t, bundleIdToTitleId, "corp.sap.privileges", "expected 'corp.sap.privileges' to be in software_titles")
require.NotContains(t, bundleIdToTitleId, "corp.sap.privileges.pkg", "expected 'corp.sap.privileges.pkg' to be deleted from software_titles")
installerRows, err := db.Query(`
SELECT title_id
FROM software_installers
`)
require.NoError(t, err)
defer installerRows.Close()
var softwareInstallerTitleIds []string
for installerRows.Next() {
var titleId string
if err := installerRows.Scan(&titleId); err != nil {
require.NoError(t, err)
}
softwareInstallerTitleIds = append(softwareInstallerTitleIds, titleId)
}
require.NoError(t, installerRows.Err())
require.Len(t, softwareInstallerTitleIds, 1)
require.Equal(t, fmt.Sprintf("%d", correctTitleId), softwareInstallerTitleIds[0], "expected existing software installer to point to correct software title")
}
File diff suppressed because one or more lines are too long