Ensure scripts set in no-team.yml can be used in run-script actions for No Team (#22809)

For #22787

Also revises the spec check to explain that scripts have to be defined
"controls" when used in policies for the same team, with an explicit
call-out for no-team.yml since this fix doesn't support pulling scripts
from the global file. This is because parsing and script-matching
happens early enough that we can't throw an error in the part of the
code where we bail when controls are defined in both no-team and default
files.

To minimize diff size, we're both "passing-by-ref" and returning the
maps-by-team of scripts and installers, though the former would be
sufficient on its own.

# 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. -->

- N/A 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/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)
- [x] Added/updated tests (sorta)
- [x] Manual QA for all new/changed functionality
This commit is contained in:
Ian Littman
2024-10-10 06:12:24 -05:00
committed by GitHub
parent 1ecdad24ad
commit 0a8a396643
6 changed files with 29 additions and 12 deletions
+5 -1
View File
@@ -90,7 +90,11 @@ func applyCommand() *cli.Command {
opts.TeamForPolicies = policiesTeamName
}
baseDir := filepath.Dir(flFilename)
_, _, _, err = fleetClient.ApplyGroup(c.Context, specs, baseDir, logf, nil, opts)
teamsSoftwareInstallers := make(map[string][]fleet.SoftwarePackageResponse)
teamsScripts := make(map[string][]fleet.ScriptResponse)
_, _, _, err = fleetClient.ApplyGroup(c.Context, specs, baseDir, logf, nil, opts, teamsSoftwareInstallers, teamsScripts)
if err != nil {
return err
}
+6 -1
View File
@@ -109,6 +109,11 @@ func gitopsCommand() *cli.Command {
if totalFilenames > 1 {
firstFileMustBeGlobal = ptr.Bool(true)
}
// we keep track of team software installers and scripts for correct policy application
teamsSoftwareInstallers := make(map[string][]fleet.SoftwarePackageResponse)
teamsScripts := make(map[string][]fleet.ScriptResponse)
// We keep track of the secrets to check if duplicates exist during dry run
secrets := make(map[string]struct{})
for _, flFilename := range flFilenames.Value() {
@@ -207,7 +212,7 @@ func gitopsCommand() *cli.Command {
}
}
assumptions, err := fleetClient.DoGitOps(c.Context, config, flFilename, logf, flDryRun, teamDryRunAssumptions, appConfig)
assumptions, err := fleetClient.DoGitOps(c.Context, config, flFilename, logf, flDryRun, teamDryRunAssumptions, appConfig, teamsSoftwareInstallers, teamsScripts)
if err != nil {
return err
}
+3 -1
View File
@@ -387,7 +387,9 @@ Use the stop and reset subcommands to manage the server and dependencies once st
}
// this only applies standard queries, the base directory is not used,
// so pass in the current working directory.
_, _, _, err = client.ApplyGroup(c.Context, specs, ".", logf, nil, fleet.ApplyClientSpecOptions{})
teamsSoftwareInstallers := make(map[string][]fleet.SoftwarePackageResponse)
teamsScripts := make(map[string][]fleet.ScriptResponse)
_, _, _, err = client.ApplyGroup(c.Context, specs, ".", logf, nil, fleet.ApplyClientSpecOptions{}, teamsSoftwareInstallers, teamsScripts)
if err != nil {
return err
}
+4 -1
View File
@@ -596,7 +596,10 @@ func parsePolicyRunScript(baseDir string, teamName *string, policy *Policy, scri
}
}
if !scriptOnTeamFound {
return fmt.Errorf("policy script not found on team: %v vs. %v", foundScriptPaths, scriptPath)
if *teamName == noTeam {
return fmt.Errorf("policy script %s was not defined in controls in no-team.yml", scriptPath)
}
return fmt.Errorf("policy script %s was not defined in controls for %s", scriptPath, *teamName)
}
scriptName := filepath.Base(policy.RunScript.Path)
+1 -1
View File
@@ -1016,7 +1016,7 @@ controls:
}
_, err = GitOpsFromFile(path, basePath, &appConfig, nopLogf)
assert.ErrorContains(t, err,
"policy script not found on team",
"was not defined in controls for TeamName",
)
}
+10 -7
View File
@@ -397,9 +397,9 @@ func (c *Client) ApplyGroup(
logf func(format string, args ...interface{}),
appconfig *fleet.EnrichedAppConfig,
opts fleet.ApplyClientSpecOptions,
teamsSoftwareInstallers map[string][]fleet.SoftwarePackageResponse,
teamsScripts map[string][]fleet.ScriptResponse,
) (map[string]uint, map[string][]fleet.SoftwarePackageResponse, map[string][]fleet.ScriptResponse, error) {
teamSoftwareInstallers := make(map[string][]fleet.SoftwarePackageResponse)
teamScripts := make(map[string][]fleet.ScriptResponse)
logfn := func(format string, args ...interface{}) {
if logf != nil {
@@ -513,7 +513,7 @@ func (c *Client) ApplyGroup(
if err != nil {
return nil, nil, nil, fmt.Errorf("applying no-team scripts: %w", err)
}
teamScripts["No team"] = noTeamScripts
teamsScripts["No team"] = noTeamScripts
}
if err := c.ApplyAppConfig(specs.AppConfig, opts.ApplySpecOptions); err != nil {
return nil, nil, nil, fmt.Errorf("applying fleet config: %w", err)
@@ -683,7 +683,7 @@ func (c *Client) ApplyGroup(
if err != nil {
return nil, nil, nil, fmt.Errorf("applying scripts for team %q: %w", tmName, err)
}
teamScripts[tmName] = scriptResponses
teamsScripts[tmName] = scriptResponses
}
}
if len(tmSoftwarePackagesPayloads) > 0 {
@@ -695,7 +695,7 @@ func (c *Client) ApplyGroup(
if err != nil {
return nil, nil, nil, fmt.Errorf("applying software installers for team %q: %w", tmName, err)
}
teamSoftwareInstallers[tmName] = installers
teamsSoftwareInstallers[tmName] = installers
}
}
if len(tmSoftwareAppsPayloads) > 0 {
@@ -749,7 +749,7 @@ func (c *Client) ApplyGroup(
}
}
return teamIDsByName, teamSoftwareInstallers, teamScripts, nil
return teamIDsByName, teamsSoftwareInstallers, teamsScripts, nil
}
func buildSoftwarePackagesPayload(baseDir string, specs []fleet.SoftwarePackageSpec) ([]fleet.SoftwareInstallerPayload, error) {
@@ -1223,6 +1223,9 @@ func (c *Client) DoGitOps(
dryRun bool,
teamDryRunAssumptions *fleet.TeamSpecsDryRunAssumptions,
appConfig *fleet.EnrichedAppConfig,
// pass-by-ref to build lists
teamsSoftwareInstallers map[string][]fleet.SoftwarePackageResponse,
teamsScripts map[string][]fleet.ScriptResponse,
) (*fleet.TeamSpecsDryRunAssumptions, error) {
baseDir := filepath.Dir(fullFilename)
filename := filepath.Base(fullFilename)
@@ -1468,7 +1471,7 @@ func (c *Client) DoGitOps(
DryRun: dryRun,
},
ExpandEnvConfigProfiles: true,
})
}, teamsSoftwareInstallers, teamsScripts)
if err != nil {
return nil, err
}