mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 00:49:03 +00:00
use auto-generated scripts for non-exe installers if not included in gitops payload (#28680)
> For #28561 # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [x] Manual QA for all new/changed functionality - [x] For unreleased bug fixes in a release candidate, confirmed that the fix is not expected to adversely impact load test results or alerted the release DRI if additional load testing is needed.
This commit is contained in:
parent
95b80482ba
commit
671ef75476
4 changed files with 102 additions and 10 deletions
|
|
@ -1739,6 +1739,7 @@ func (svc *Service) softwareBatchUpload(
|
|||
installer.BundleIdentifier = *foundInstaller.BundleIdentifier
|
||||
}
|
||||
installer.Title = foundInstaller.Title
|
||||
installer.PackageIDs = foundInstaller.PackageIDs
|
||||
case !ok && len(teamIDs) > 0:
|
||||
// Installer exists, but for another team. We should copy it over to this team
|
||||
// (if we have access to the other team).
|
||||
|
|
@ -1770,6 +1771,7 @@ func (svc *Service) softwareBatchUpload(
|
|||
}
|
||||
installer.Title = i.Title
|
||||
installer.StorageID = p.SHA256
|
||||
installer.PackageIDs = i.PackageIDs
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -1814,6 +1816,17 @@ func (svc *Service) softwareBatchUpload(
|
|||
}
|
||||
}
|
||||
|
||||
// custom scripts only for exe installers
|
||||
if installer.Extension != "exe" {
|
||||
if installer.InstallScript == "" {
|
||||
installer.InstallScript = file.GetInstallScript(installer.Extension)
|
||||
}
|
||||
|
||||
if installer.UninstallScript == "" {
|
||||
installer.UninstallScript = file.GetUninstallScript(installer.Extension)
|
||||
}
|
||||
}
|
||||
|
||||
// Update $PACKAGE_ID in uninstall script
|
||||
preProcessUninstallScript(installer)
|
||||
|
||||
|
|
|
|||
|
|
@ -2329,7 +2329,8 @@ SELECT
|
|||
si.platform AS platform,
|
||||
st.source AS source,
|
||||
st.bundle_identifier AS bundle_identifier,
|
||||
st.name AS title
|
||||
st.name AS title,
|
||||
si.package_ids AS package_ids
|
||||
FROM
|
||||
software_installers si
|
||||
JOIN software_titles st ON si.title_id = st.id
|
||||
|
|
@ -2359,6 +2360,9 @@ WHERE
|
|||
if _, ok := set[tmID]; ok {
|
||||
return nil, ctxerr.New(ctx, fmt.Sprintf("cannot have multiple installers with the same hash %q on one team", sha256))
|
||||
}
|
||||
if installer.PackageIDList != "" {
|
||||
installer.PackageIDs = strings.Split(installer.PackageIDList, ",")
|
||||
}
|
||||
set[tmID] = installer
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -383,15 +383,17 @@ type UploadSoftwareInstallerPayload struct {
|
|||
}
|
||||
|
||||
type ExistingSoftwareInstaller struct {
|
||||
InstallerID uint `db:"installer_id"`
|
||||
TeamID *uint `db:"team_id"`
|
||||
Filename string `db:"filename"`
|
||||
Extension string `db:"extension"`
|
||||
Version string `db:"version"`
|
||||
Platform string `db:"platform"`
|
||||
Source string `db:"source"`
|
||||
BundleIdentifier *string `db:"bundle_identifier"`
|
||||
Title string `db:"title"`
|
||||
InstallerID uint `db:"installer_id"`
|
||||
TeamID *uint `db:"team_id"`
|
||||
Filename string `db:"filename"`
|
||||
Extension string `db:"extension"`
|
||||
Version string `db:"version"`
|
||||
Platform string `db:"platform"`
|
||||
Source string `db:"source"`
|
||||
BundleIdentifier *string `db:"bundle_identifier"`
|
||||
Title string `db:"title"`
|
||||
PackageIDList string `db:"package_ids"`
|
||||
PackageIDs []string ``
|
||||
}
|
||||
|
||||
type UpdateSoftwareInstallerPayload struct {
|
||||
|
|
|
|||
|
|
@ -17199,6 +17199,13 @@ func (s *integrationEnterpriseTestSuite) TestBatchSoftwareUploadWithSHAs() {
|
|||
w.Header().Set("Content-Type", "application/vnd.microsoft.portable-executable")
|
||||
_, err = io.Copy(w, file)
|
||||
require.NoError(t, err)
|
||||
case "/app.pkg":
|
||||
file, err := os.Open(filepath.Join("testdata", "software-installers", "dummy_installer.pkg"))
|
||||
require.NoError(t, err)
|
||||
defer file.Close()
|
||||
w.Header().Set("Content-Type", "application/x-newton-compatible-pkg")
|
||||
_, err = io.Copy(w, file)
|
||||
require.NoError(t, err)
|
||||
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
|
|
@ -17389,4 +17396,70 @@ func (s *integrationEnterpriseTestSuite) TestBatchSoftwareUploadWithSHAs() {
|
|||
s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: softwareToInstall}, http.StatusAccepted, &batchResponse, "team_name", team2.Name)
|
||||
errMsg = waitBatchSetSoftwareInstallersFailed(t, s, team2.Name, batchResponse.RequestUUID)
|
||||
require.Contains(t, errMsg, "Couldn't edit. Uninstall script is required for .exe packages.")
|
||||
|
||||
// add both scripts to get a success
|
||||
softwareToInstall[1].InstallScript = "echo install 2"
|
||||
softwareToInstall[1].UninstallScript = "echo uninstall 2"
|
||||
softwareToInstall[1].SHA256 = exeHash
|
||||
|
||||
// add the pkg installer with some custom scripts
|
||||
pkgURL := srv.URL + "/app.pkg"
|
||||
softwareToInstall = append(softwareToInstall, &fleet.SoftwareInstallerPayload{
|
||||
URL: pkgURL,
|
||||
InstallScript: "some install script",
|
||||
UninstallScript: "some uninstall script",
|
||||
})
|
||||
|
||||
s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: softwareToInstall}, http.StatusAccepted, &batchResponse, "team_name", team2.Name)
|
||||
packages = waitBatchSetSoftwareInstallersCompleted(t, s, team2.Name, batchResponse.RequestUUID)
|
||||
require.Len(t, packages, 3)
|
||||
pkgTitleID := packages[2].TitleID
|
||||
require.NotNil(t, pkgTitleID)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/software/titles/%d", *pkgTitleID), getSoftwareTitleRequest{}, http.StatusOK, &stResp, "team_id", fmt.Sprint(team2.ID))
|
||||
require.NotNil(t, stResp.SoftwareTitle.SoftwarePackage)
|
||||
require.Equal(t, "DummyApp.app", stResp.SoftwareTitle.Name)
|
||||
require.Equal(t, pkgURL, stResp.SoftwareTitle.SoftwarePackage.URL)
|
||||
require.Equal(t, softwareToInstall[2].InstallScript, stResp.SoftwareTitle.SoftwarePackage.InstallScript)
|
||||
require.Equal(t, softwareToInstall[2].UninstallScript, stResp.SoftwareTitle.SoftwarePackage.UninstallScript)
|
||||
|
||||
expectedUninstallScript := `#!/bin/sh
|
||||
|
||||
# Fleet extracts and saves package IDs.
|
||||
pkg_ids=(
|
||||
"com.example.dummy"
|
||||
)
|
||||
|
||||
# For each package id, get all .app folders associated with the package and remove them.
|
||||
for pkg_id in "${pkg_ids[@]}"
|
||||
do
|
||||
# Get volume and location of the package.
|
||||
volume=$(pkgutil --pkg-info "$pkg_id" | grep -i "volume" | awk '{if (NF>1) print $NF}')
|
||||
location=$(pkgutil --pkg-info "$pkg_id" | grep -i "location" | awk '{if (NF>1) print $NF}')
|
||||
# Check if this package id corresponds to a valid/installed package
|
||||
if [[ ! -z "$volume" ]]; then
|
||||
# Remove individual directories that end with ".app" belonging to the package.
|
||||
# Only process directories that end with ".app" to prevent Fleet from removing top level directories.
|
||||
pkgutil --only-dirs --files "$pkg_id" | grep "\.app$" | sed -e 's@^@'"$volume""$location"'/@' | tr '\n' '\0' | xargs -n 1 -0 rm -rf
|
||||
# Remove receipts
|
||||
pkgutil --forget "$pkg_id"
|
||||
else
|
||||
echo "WARNING: volume is empty for package ID $pkg_id"
|
||||
fi
|
||||
done
|
||||
`
|
||||
|
||||
// remove the custom scripts from the .pkg. We should get back the auto-generated ones.
|
||||
softwareToInstall[2].InstallScript = ""
|
||||
softwareToInstall[2].UninstallScript = ""
|
||||
s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: softwareToInstall}, http.StatusAccepted, &batchResponse, "team_name", team2.Name)
|
||||
packages = waitBatchSetSoftwareInstallersCompleted(t, s, team2.Name, batchResponse.RequestUUID)
|
||||
require.Len(t, packages, 3)
|
||||
pkgTitleID = packages[2].TitleID
|
||||
require.NotNil(t, pkgTitleID)
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/software/titles/%d", *pkgTitleID), getSoftwareTitleRequest{}, http.StatusOK, &stResp, "team_id", fmt.Sprint(team2.ID))
|
||||
require.NotNil(t, stResp.SoftwareTitle.SoftwarePackage)
|
||||
require.Equal(t, "DummyApp.app", stResp.SoftwareTitle.Name)
|
||||
require.Equal(t, pkgURL, stResp.SoftwareTitle.SoftwarePackage.URL)
|
||||
require.Equal(t, file.GetInstallScript("pkg"), stResp.SoftwareTitle.SoftwarePackage.InstallScript)
|
||||
require.Equal(t, expectedUninstallScript, stResp.SoftwareTitle.SoftwarePackage.UninstallScript)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue