mirror of
https://github.com/fleetdm/fleet
synced 2026-05-02 19:07:38 +00:00
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42492 Includes changes from running ingestions on all FMAs # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] 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. - [ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [ ] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - [ ] 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
91 lines
2.8 KiB
Go
91 lines
2.8 KiB
Go
package patch_policy
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
)
|
|
|
|
type PolicyData struct {
|
|
Name string
|
|
Platform string
|
|
Description string
|
|
Resolution string
|
|
Query string
|
|
ExistsQuery string
|
|
Version string
|
|
}
|
|
|
|
const (
|
|
templateStart = "SELECT 1 WHERE NOT EXISTS ("
|
|
templateEndDarwin = " AND version_compare(bundle_short_version, '%s') < 0);"
|
|
templateEndWindows = " AND version_compare(version, '%s') < 0);"
|
|
)
|
|
|
|
var (
|
|
ErrWrongPlatform = errors.New("platform should be darwin or windows")
|
|
ErrNoExistsQuery = errors.New("exists query was not provided")
|
|
)
|
|
|
|
// GenerateQueryForManifest wraps the "exists" query to create a patch policy query
|
|
func GenerateQueryForManifest(p PolicyData) (string, error) {
|
|
if p.ExistsQuery == "" {
|
|
return "", ErrNoExistsQuery
|
|
}
|
|
before, _ := strings.CutSuffix(p.ExistsQuery, ";")
|
|
|
|
switch p.Platform {
|
|
case "darwin":
|
|
return fmt.Sprintf(templateStart+before+templateEndDarwin, p.Version), nil
|
|
case "windows":
|
|
return fmt.Sprintf(templateStart+before+templateEndWindows, p.Version), nil
|
|
}
|
|
return "", ErrWrongPlatform
|
|
}
|
|
|
|
// GenerateFromInstaller creates a patch policy with all fields from an installer
|
|
func GenerateFromInstaller(p PolicyData, installer *fleet.SoftwareInstaller) (*PolicyData, error) {
|
|
// use the patch policy query from the app manifest if available
|
|
query := installer.PatchQuery
|
|
|
|
if p.Description == "" {
|
|
p.Description = "Outdated software might introduce security vulnerabilities or compatibility issues."
|
|
}
|
|
|
|
if p.Resolution == "" {
|
|
p.Resolution = "Install the latest version from self-service."
|
|
}
|
|
|
|
switch installer.Platform {
|
|
case "darwin":
|
|
if p.Name == "" {
|
|
p.Name = fmt.Sprintf("macOS - %s up to date", installer.SoftwareTitle)
|
|
}
|
|
if installer.PatchQuery == "" {
|
|
query = defaultMacOSQuery(installer.BundleIdentifier, installer.Version)
|
|
}
|
|
case "windows":
|
|
if p.Name == "" {
|
|
p.Name = fmt.Sprintf("Windows - %s up to date", installer.SoftwareTitle)
|
|
}
|
|
if installer.PatchQuery == "" {
|
|
query = defaultWindowsQuery(installer.SoftwareTitle, installer.Version)
|
|
}
|
|
default:
|
|
return nil, ErrWrongPlatform
|
|
}
|
|
|
|
return &PolicyData{Query: query, Platform: installer.Platform, Name: p.Name, Description: p.Description, Resolution: p.Resolution}, nil
|
|
}
|
|
|
|
func defaultMacOSQuery(bundleIdentifier string, version string) string {
|
|
patchTemplate := "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = '%s' AND version_compare(bundle_short_version, '%s') < 0);"
|
|
return fmt.Sprintf(patchTemplate, bundleIdentifier, version)
|
|
}
|
|
|
|
func defaultWindowsQuery(softwareTitle string, version string) string {
|
|
patchTemplate := "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = '%s' AND version_compare(version, '%s') < 0);"
|
|
return fmt.Sprintf(patchTemplate, softwareTitle, version)
|
|
}
|