mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Allow icon in team level yaml for script-only packages (#43783)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #43142 Since script-only packages have to be specified as a path, add some logic to allow icon to be set as a path in that situation. # 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. - [ ] 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. - [ ] Timeouts are implemented and retries are limited to avoid infinite loops - [ ] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [x] Added/updated automated tests - `TestSoftwarePackagesPathWithInline` checks custom package yml path so there is no regression, added `TestScriptOnlyPackagesPathWithInline` to test script-only package path. - [ ] 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 - Tested .sh and .ps1 script-only packages with icon path specified in the team level yaml. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed custom icon handling for script-only packages (e.g., .sh and .ps1), allowing icons to be set and resolved correctly for packages referenced by path. * **Tests** * Added test coverage validating custom icon functionality and path resolution for script-only packages; included a sample script used by the test. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
308e5f3dc8
commit
7d9c134942
4 changed files with 51 additions and 5 deletions
1
changes/43142-script-package-icon-gitops
Normal file
1
changes/43142-script-package-icon-gitops
Normal file
|
|
@ -0,0 +1 @@
|
|||
- Fixed an issue where adding a custom icon for a script-only package was not allowed in GitOps.
|
||||
|
|
@ -275,12 +275,19 @@ type SoftwarePackage struct {
|
|||
fleet.SoftwarePackageSpec
|
||||
}
|
||||
|
||||
func (spec SoftwarePackage) HydrateToPackageLevel(packageLevel fleet.SoftwarePackageSpec) (fleet.SoftwarePackageSpec, error) {
|
||||
if spec.Icon.Path != "" || spec.InstallScript.Path != "" || spec.UninstallScript.Path != "" ||
|
||||
func (spec SoftwarePackage) HydrateToPackageLevel(packageLevel fleet.SoftwarePackageSpec, ext string) (fleet.SoftwarePackageSpec, error) {
|
||||
if spec.InstallScript.Path != "" || spec.UninstallScript.Path != "" ||
|
||||
spec.PostInstallScript.Path != "" || spec.URL != "" || spec.SHA256 != "" || spec.PreInstallQuery.Path != "" {
|
||||
return packageLevel, fmt.Errorf("the software package defined in %s must not have icons, scripts, queries, URL, or hash specified at the team level", *spec.Path)
|
||||
}
|
||||
|
||||
// Icon should be allowed at the team level yaml for script packages which must be specified as a path
|
||||
if spec.Icon.Path != "" {
|
||||
if ext != ".sh" && ext != ".ps1" {
|
||||
return packageLevel, fmt.Errorf("the software package defined in %s must not have icons, scripts, queries, URL, or hash specified at the team level", *spec.Path)
|
||||
}
|
||||
}
|
||||
|
||||
packageLevel.Categories = spec.Categories
|
||||
packageLevel.LabelsIncludeAny = spec.LabelsIncludeAny
|
||||
packageLevel.LabelsExcludeAny = spec.LabelsExcludeAny
|
||||
|
|
@ -1877,10 +1884,15 @@ func parseSoftware(top map[string]json.RawMessage, result *GitOps, baseDir strin
|
|||
}
|
||||
// Script file becomes the install script for a script-only package
|
||||
scriptSpec := fleet.SoftwarePackageSpec{
|
||||
InstallScript: fleet.TeamSpecSoftwareAsset{Path: resolvedPath},
|
||||
ReferencedYamlPath: resolvedPath,
|
||||
Icon: teamLevelPackage.Icon,
|
||||
}
|
||||
scriptSpec, err = teamLevelPackage.HydrateToPackageLevel(scriptSpec)
|
||||
// Icon path needs to be resolved, but since this function will set
|
||||
// the install script it needs to be set to the correct path again.
|
||||
scriptSpec = scriptSpec.ResolveSoftwarePackagePaths(baseDir)
|
||||
scriptSpec.InstallScript.Path = resolvedPath
|
||||
|
||||
scriptSpec, err = teamLevelPackage.HydrateToPackageLevel(scriptSpec, ext)
|
||||
if err != nil {
|
||||
multiError = multierror.Append(multiError, err)
|
||||
continue
|
||||
|
|
@ -1922,7 +1934,7 @@ func parseSoftware(top map[string]json.RawMessage, result *GitOps, baseDir strin
|
|||
|
||||
for i, spec := range softwarePackageSpecs {
|
||||
softwarePackageSpec := spec.ResolveSoftwarePackagePaths(filepath.Dir(spec.ReferencedYamlPath))
|
||||
softwarePackageSpec, err = teamLevelPackage.HydrateToPackageLevel(softwarePackageSpec)
|
||||
softwarePackageSpec, err = teamLevelPackage.HydrateToPackageLevel(softwarePackageSpec, ext)
|
||||
if err != nil {
|
||||
multiError = multierror.Append(multiError, err)
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -1524,6 +1524,36 @@ software:
|
|||
assert.ErrorContains(t, err, "the software package defined in software/single-package.yml must not have icons, scripts, queries, URL, or hash specified at the team level")
|
||||
}
|
||||
|
||||
func TestScriptOnlyPackagesPathWithInline(t *testing.T) {
|
||||
t.Parallel()
|
||||
config := getTeamConfig([]string{"software"})
|
||||
config += `
|
||||
software:
|
||||
packages:
|
||||
- path: software/script-only.sh
|
||||
icon:
|
||||
path: ./foo/bar.png
|
||||
`
|
||||
|
||||
path, basePath := createTempFile(t, "", config)
|
||||
|
||||
err := file.Copy(
|
||||
filepath.Join("testdata", "software", "script-only.sh"),
|
||||
filepath.Join(basePath, "software", "script-only.sh"),
|
||||
os.FileMode(0o755),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
appConfig := fleet.EnrichedAppConfig{}
|
||||
appConfig.License = &fleet.LicenseInfo{
|
||||
Tier: fleet.TierPremium,
|
||||
}
|
||||
gitops, err := GitOpsFromFile(path, basePath, &appConfig, nopLogf)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, gitops.Software.Packages, 1)
|
||||
assert.Equal(t, filepath.Join(basePath, "foo", "bar.png"), gitops.Software.Packages[0].Icon.Path)
|
||||
}
|
||||
|
||||
func TestIllegalFleetSecret(t *testing.T) {
|
||||
t.Parallel()
|
||||
config := getGlobalConfig([]string{"policies"})
|
||||
|
|
|
|||
3
pkg/spec/testdata/software/script-only.sh
vendored
Normal file
3
pkg/spec/testdata/software/script-only.sh
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "hello world"
|
||||
Loading…
Reference in a new issue