From f9ecc350628b890a357c7764613653e00305e532 Mon Sep 17 00:00:00 2001 From: Lucas Manuel Rodriguez Date: Tue, 17 Sep 2024 13:30:27 -0300 Subject: [PATCH] Minor fixes to policy software installations (#22148) PR for the three fixes described in #22104. - [X] Added/updated tests - [X] Manual QA for all new/changed functionality --- cmd/fleetctl/get_test.go | 2 +- cmd/fleetctl/gitops_test.go | 41 +++++++++++++++---- ee/server/service/software_installers.go | 5 ++- pkg/spec/gitops.go | 3 ++ server/datastore/mysql/activities.go | 2 +- server/datastore/mysql/software_installers.go | 16 ++------ .../mysql/software_installers_test.go | 21 ++++++---- server/fleet/datastore.go | 2 +- server/fleet/service.go | 2 +- server/fleet/software_installer.go | 11 +++++ server/mock/datastore_mock.go | 4 +- server/service/client.go | 24 +++++------ server/service/client_software.go | 4 +- server/service/client_teams.go | 4 +- server/service/software_installers.go | 10 ++--- 15 files changed, 94 insertions(+), 57 deletions(-) diff --git a/cmd/fleetctl/get_test.go b/cmd/fleetctl/get_test.go index fc9dbe03fbca..e775f4ea5fb4 100644 --- a/cmd/fleetctl/get_test.go +++ b/cmd/fleetctl/get_test.go @@ -2320,7 +2320,7 @@ func TestGetTeamsYAMLAndApply(t *testing.T) { declaration.DeclarationUUID = uuid.NewString() return declaration, nil } - ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { + ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { return nil, nil } diff --git a/cmd/fleetctl/gitops_test.go b/cmd/fleetctl/gitops_test.go index 8a6d1aeeb8b7..0f6c33b061c4 100644 --- a/cmd/fleetctl/gitops_test.go +++ b/cmd/fleetctl/gitops_test.go @@ -229,7 +229,7 @@ func TestGitOpsBasicGlobalPremium(t *testing.T) { ds.NewJobFunc = func(ctx context.Context, job *fleet.Job) (*fleet.Job, error) { return &fleet.Job{}, nil } - ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { + ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { return nil, nil } @@ -373,7 +373,7 @@ func TestGitOpsBasicTeam(t *testing.T) { ds.DeleteMDMAppleDeclarationByNameFunc = func(ctx context.Context, teamID *uint, name string) error { return nil } - ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { + ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { return nil, nil } ds.ApplyEnrollSecretsFunc = func(ctx context.Context, teamID *uint, secrets []*fleet.EnrollSecret) error { @@ -804,7 +804,7 @@ func TestGitOpsFullTeam(t *testing.T) { return nil } var appliedSoftwareInstallers []*fleet.UploadSoftwareInstallerPayload - ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { + ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { appliedSoftwareInstallers = installers return nil, nil } @@ -1055,7 +1055,7 @@ func TestGitOpsBasicGlobalAndTeam(t *testing.T) { savedTeam = team return team, nil } - ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { + ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { return nil, nil } ds.ListSoftwareTitlesFunc = func(ctx context.Context, opt fleet.SoftwareTitleListOptions, tmFilter fleet.TeamFilter) ([]fleet.SoftwareTitleListResult, int, *fleet.PaginationMetadata, error) { @@ -1317,7 +1317,7 @@ func TestGitOpsBasicGlobalAndNoTeam(t *testing.T) { savedTeam = team return team, nil } - ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { + ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { return nil, nil } ds.ListSoftwareTitlesFunc = func(ctx context.Context, opt fleet.SoftwareTitleListOptions, tmFilter fleet.TeamFilter) ([]fleet.SoftwareTitleListResult, int, *fleet.PaginationMetadata, error) { @@ -1442,6 +1442,20 @@ software: `) require.NoError(t, err) + noTeamFilePathPoliciesCalendarPath := filepath.Join(t.TempDir(), "no-team.yml") + noTeamFilePathPoliciesCalendar, err := os.Create(noTeamFilePathPoliciesCalendarPath) + require.NoError(t, err) + _, err = noTeamFilePathPoliciesCalendar.WriteString(` +controls: +policies: + - name: Foobar + query: SELECT 1 FROM osquery_info WHERE start_time < 0; + calendar_events_enabled: true +name: No team +software: +`) + require.NoError(t, err) + noTeamFilePathWithControls := filepath.Join(t.TempDir(), "no-team.yml") noTeamFileWithControls, err := os.Create(noTeamFilePathWithControls) require.NoError(t, err) @@ -1480,16 +1494,25 @@ software: require.Error(t, err) assert.True(t, strings.Contains(err.Error(), "'controls' cannot be set on both global config and on no-team.yml")) // Real run, both global and no-team.yml define controls. - _, err = runAppNoChecks([]string{"gitops", "-f", globalFileWithControls.Name(), "-f", teamFile.Name(), "-f", noTeamFileWithControls.Name(), "--dry-run"}) + _, err = runAppNoChecks([]string{"gitops", "-f", globalFileWithControls.Name(), "-f", teamFile.Name(), "-f", noTeamFileWithControls.Name()}) require.Error(t, err) assert.True(t, strings.Contains(err.Error(), "'controls' cannot be set on both global config and on no-team.yml")) + // Dry run, both global and no-team.yml defines policy with calendar events enabled. + _, err = runAppNoChecks([]string{"gitops", "-f", globalFileWithControls.Name(), "-f", teamFile.Name(), "-f", noTeamFilePathPoliciesCalendar.Name(), "--dry-run"}) + require.Error(t, err) + assert.True(t, strings.Contains(err.Error(), "calendar events are not supported on \"No team\" policies: \"Foobar\""), err.Error()) + // Real run, both global and no-team.yml define controls. + _, err = runAppNoChecks([]string{"gitops", "-f", globalFileWithControls.Name(), "-f", teamFile.Name(), "-f", noTeamFilePathPoliciesCalendar.Name()}) + require.Error(t, err) + assert.True(t, strings.Contains(err.Error(), "calendar events are not supported on \"No team\" policies: \"Foobar\""), err.Error()) + // Dry run, controls should be defined somewhere, either in no-team.yml or global. _, err = runAppNoChecks([]string{"gitops", "-f", globalFileWithoutControlsAndSoftwareKeys.Name(), "-f", teamFile.Name(), "-f", noTeamFileWithoutControls.Name(), "--dry-run"}) require.Error(t, err) assert.True(t, strings.Contains(err.Error(), "'controls' must be set on global config or no-team.yml")) // Real run, both global and no-team.yml define controls. - _, err = runAppNoChecks([]string{"gitops", "-f", globalFileWithoutControlsAndSoftwareKeys.Name(), "-f", teamFile.Name(), "-f", noTeamFileWithoutControls.Name(), "--dry-run"}) + _, err = runAppNoChecks([]string{"gitops", "-f", globalFileWithoutControlsAndSoftwareKeys.Name(), "-f", teamFile.Name(), "-f", noTeamFileWithoutControls.Name()}) require.Error(t, err) assert.True(t, strings.Contains(err.Error(), "'controls' must be set on global config or no-team.yml")) @@ -1645,7 +1668,7 @@ func TestGitOpsTeamSoftwareInstallersQueryEnv(t *testing.T) { t.Setenv("QUERY_VAR", "IT_WORKS") - ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { + ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { if installers[0].PreInstallQuery != "select IT_WORKS" { return nil, fmt.Errorf("Missing env var, got %s", installers[0].PreInstallQuery) } @@ -2158,7 +2181,7 @@ func setupFullGitOpsPremiumServer(t *testing.T) (*mock.Store, **fleet.AppConfig, declaration.DeclarationUUID = uuid.NewString() return declaration, nil } - ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { + ds.BatchSetSoftwareInstallersFunc = func(ctx context.Context, teamID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { return nil, nil } diff --git a/ee/server/service/software_installers.go b/ee/server/service/software_installers.go index 1bbccd4ab622..ec1172310f41 100644 --- a/ee/server/service/software_installers.go +++ b/ee/server/service/software_installers.go @@ -747,7 +747,8 @@ func (svc *Service) UninstallSoftwareTitle(ctx context.Context, hostID uint, sof } func (svc *Service) insertSoftwareUninstallRequest(ctx context.Context, executionID string, host *fleet.Host, - installer *fleet.SoftwareInstaller) error { + installer *fleet.SoftwareInstaller, +) error { if err := svc.ds.InsertSoftwareUninstallRequest(ctx, executionID, host.ID, installer.InstallerID); err != nil { return ctxerr.Wrap(ctx, err, "inserting software uninstall request") } @@ -892,7 +893,7 @@ const maxInstallerSizeBytes int64 = 1024 * 1024 * 500 func (svc *Service) BatchSetSoftwareInstallers( ctx context.Context, tmName string, payloads []fleet.SoftwareInstallerPayload, dryRun bool, -) ([]fleet.SoftwareInstaller, error) { +) ([]fleet.SoftwarePackageResponse, error) { if err := svc.authz.Authorize(ctx, &fleet.Team{}, fleet.ActionRead); err != nil { return nil, err } diff --git a/pkg/spec/gitops.go b/pkg/spec/gitops.go index 0d15687da72b..a5938e2b9eef 100644 --- a/pkg/spec/gitops.go +++ b/pkg/spec/gitops.go @@ -518,6 +518,9 @@ func parsePolicies(top map[string]json.RawMessage, result *GitOps, baseDir strin } else { item.Team = "" } + if item.CalendarEventsEnabled && result.IsNoTeam() { + multiError = multierror.Append(multiError, fmt.Errorf("calendar events are not supported on \"No team\" policies: %q", item.Name)) + } } duplicates := getDuplicateNames( result.Policies, func(p *GitOpsPolicySpec) string { diff --git a/server/datastore/mysql/activities.go b/server/datastore/mysql/activities.go index 356f608ef359..650c097cb985 100644 --- a/server/datastore/mysql/activities.go +++ b/server/datastore/mysql/activities.go @@ -343,7 +343,7 @@ func (ds *Datastore) ListHostUpcomingActivities(ctx context.Context, hostID uint 'software_package', si.filename, 'install_uuid', hsi.execution_id, 'status', CAST(hsi.status AS CHAR), - 'self_service', si.self_service IS TRUE + 'self_service', hsi.self_service IS TRUE ) as details FROM host_software_installs hsi diff --git a/server/datastore/mysql/software_installers.go b/server/datastore/mysql/software_installers.go index 23a0a1e45637..c7fbfe467f04 100644 --- a/server/datastore/mysql/software_installers.go +++ b/server/datastore/mysql/software_installers.go @@ -651,7 +651,7 @@ func (ds *Datastore) CleanupUnusedSoftwareInstallers(ctx context.Context, softwa return ctxerr.Wrap(ctx, err, "cleanup unused software installers") } -func (ds *Datastore) BatchSetSoftwareInstallers(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { +func (ds *Datastore) BatchSetSoftwareInstallers(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { const upsertSoftwareTitles = ` INSERT INTO software_titles (name, source, browser) @@ -752,16 +752,7 @@ ON DUPLICATE KEY UPDATE const loadInsertedSoftwareInstallers = ` SELECT - id, team_id, - storage_id, - filename, - version, - install_script_content_id, - pre_install_query, - post_install_script_content_id, - platform, - self_service, title_id, url FROM @@ -775,7 +766,7 @@ WHERE global_or_team_id = ? globalOrTeamID = *tmID } - var insertedSoftwareInstallers []fleet.SoftwareInstaller + var insertedSoftwareInstallers []fleet.SoftwarePackageResponse if err := ds.withRetryTxx(ctx, func(tx sqlx.ExtContext) error { // if no installers are provided, just delete whatever was in // the table @@ -953,7 +944,8 @@ func (ds *Datastore) GetSoftwareInstallersWithoutPackageIDs(ctx context.Context) } func (ds *Datastore) UpdateSoftwareInstallerWithoutPackageIDs(ctx context.Context, id uint, - payload fleet.UploadSoftwareInstallerPayload) error { + payload fleet.UploadSoftwareInstallerPayload, +) error { uninstallScriptID, err := ds.getOrGenerateScriptContentsID(ctx, payload.UninstallScript) if err != nil { return ctxerr.Wrap(ctx, err, "get or generate uninstall script contents ID") diff --git a/server/datastore/mysql/software_installers_test.go b/server/datastore/mysql/software_installers_test.go index aceb530c5994..7e1b97499150 100644 --- a/server/datastore/mysql/software_installers_test.go +++ b/server/datastore/mysql/software_installers_test.go @@ -651,12 +651,14 @@ func testBatchSetSoftwareInstallers(t *testing.T, ds *Datastore) { PreInstallQuery: "foo", UserID: user1.ID, Platform: "darwin", + URL: "https://example.com", }}) require.NoError(t, err) require.Len(t, softwareInstallers, 1) - require.Equal(t, ins0, softwareInstallers[0].Name) + require.NotNil(t, softwareInstallers[0].TeamID) + require.Equal(t, team.ID, *softwareInstallers[0].TeamID) require.NotNil(t, softwareInstallers[0].TitleID) - require.Equal(t, "darwin", softwareInstallers[0].Platform) + require.Equal(t, "https://example.com", softwareInstallers[0].URL) assertSoftware([]fleet.SoftwareTitle{ {Name: ins0, Source: "apps", Browser: ""}, }) @@ -676,6 +678,7 @@ func testBatchSetSoftwareInstallers(t *testing.T, ds *Datastore) { PreInstallQuery: "select 0 from foo;", UserID: user1.ID, Platform: "darwin", + URL: "https://example.com", }, { InstallScript: "install", @@ -689,16 +692,19 @@ func testBatchSetSoftwareInstallers(t *testing.T, ds *Datastore) { PreInstallQuery: "select 1 from bar;", UserID: user1.ID, Platform: "darwin", + URL: "https://example2.com", }, }) require.NoError(t, err) require.Len(t, softwareInstallers, 2) - require.Equal(t, ins0, softwareInstallers[0].Name) require.NotNil(t, softwareInstallers[0].TitleID) - require.Equal(t, "darwin", softwareInstallers[0].Platform) - require.Equal(t, ins1, softwareInstallers[1].Name) + require.NotNil(t, softwareInstallers[0].TeamID) + require.Equal(t, team.ID, *softwareInstallers[0].TeamID) + require.Equal(t, "https://example.com", softwareInstallers[0].URL) require.NotNil(t, softwareInstallers[1].TitleID) - require.Equal(t, "darwin", softwareInstallers[1].Platform) + require.NotNil(t, softwareInstallers[1].TeamID) + require.Equal(t, team.ID, *softwareInstallers[1].TeamID) + require.Equal(t, "https://example2.com", softwareInstallers[1].URL) assertSoftware([]fleet.SoftwareTitle{ {Name: ins0, Source: "apps", Browser: ""}, {Name: ins1, Source: "apps", Browser: ""}, @@ -721,8 +727,9 @@ func testBatchSetSoftwareInstallers(t *testing.T, ds *Datastore) { }) require.NoError(t, err) require.Len(t, softwareInstallers, 1) - require.Equal(t, ins1, softwareInstallers[0].Name) require.NotNil(t, softwareInstallers[0].TitleID) + require.NotNil(t, softwareInstallers[0].TeamID) + require.Empty(t, softwareInstallers[0].URL) assertSoftware([]fleet.SoftwareTitle{ {Name: ins1, Source: "apps", Browser: ""}, }) diff --git a/server/fleet/datastore.go b/server/fleet/datastore.go index 8184ca5015d6..ed3af2dda26c 100644 --- a/server/fleet/datastore.go +++ b/server/fleet/datastore.go @@ -1695,7 +1695,7 @@ type Datastore interface { CleanupUnusedSoftwareInstallers(ctx context.Context, softwareInstallStore SoftwareInstallerStore, removeCreatedBefore time.Time) error // BatchSetSoftwareInstallers sets the software installers for the given team or no team. - BatchSetSoftwareInstallers(ctx context.Context, tmID *uint, installers []*UploadSoftwareInstallerPayload) ([]SoftwareInstaller, error) + BatchSetSoftwareInstallers(ctx context.Context, tmID *uint, installers []*UploadSoftwareInstallerPayload) ([]SoftwarePackageResponse, error) // HasSelfServiceSoftwareInstallers returns true if self-service software installers are available for the team or globally. HasSelfServiceSoftwareInstallers(ctx context.Context, platform string, teamID *uint) (bool, error) diff --git a/server/fleet/service.go b/server/fleet/service.go index c5624cbb2005..14dd4ba5d179 100644 --- a/server/fleet/service.go +++ b/server/fleet/service.go @@ -645,7 +645,7 @@ type Service interface { // BatchSetSoftwareInstallers replaces the software installers for a specified team. // Returns the metadata of inserted software installers. - BatchSetSoftwareInstallers(ctx context.Context, tmName string, payloads []SoftwareInstallerPayload, dryRun bool) ([]SoftwareInstaller, error) + BatchSetSoftwareInstallers(ctx context.Context, tmName string, payloads []SoftwareInstallerPayload, dryRun bool) ([]SoftwarePackageResponse, error) // SelfServiceInstallSoftwareTitle installs a software title // initiated by the user diff --git a/server/fleet/software_installer.go b/server/fleet/software_installer.go index fc7249bafcb2..67c14f5d23ce 100644 --- a/server/fleet/software_installer.go +++ b/server/fleet/software_installer.go @@ -114,6 +114,17 @@ type SoftwareInstaller struct { URL string `json:"url" db:"url"` } +// SoftwarePackageResponse is the response type used when applying software by batch. +type SoftwarePackageResponse struct { + // TeamID is the ID of the team. + // A value of nil means it is scoped to hosts that are assigned to "No team". + TeamID *uint `json:"team_id" db:"team_id"` + // TitleID is the id of the software title associated with the software installer. + TitleID *uint `json:"title_id" db:"title_id"` + // URL is the source URL for this installer (set when uploading via batch/gitops). + URL string `json:"url" db:"url"` +} + // AuthzType implements authz.AuthzTyper. func (s *SoftwareInstaller) AuthzType() string { return "installable_entity" diff --git a/server/mock/datastore_mock.go b/server/mock/datastore_mock.go index 323144afd716..3d16e29324b4 100644 --- a/server/mock/datastore_mock.go +++ b/server/mock/datastore_mock.go @@ -1064,7 +1064,7 @@ type GetSoftwareInstallResultsFunc func(ctx context.Context, resultsUUID string) type CleanupUnusedSoftwareInstallersFunc func(ctx context.Context, softwareInstallStore fleet.SoftwareInstallerStore, removeCreatedBefore time.Time) error -type BatchSetSoftwareInstallersFunc func(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) +type BatchSetSoftwareInstallersFunc func(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) type HasSelfServiceSoftwareInstallersFunc func(ctx context.Context, platform string, teamID *uint) (bool, error) @@ -6333,7 +6333,7 @@ func (s *DataStore) CleanupUnusedSoftwareInstallers(ctx context.Context, softwar return s.CleanupUnusedSoftwareInstallersFunc(ctx, softwareInstallStore, removeCreatedBefore) } -func (s *DataStore) BatchSetSoftwareInstallers(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwareInstaller, error) { +func (s *DataStore) BatchSetSoftwareInstallers(ctx context.Context, tmID *uint, installers []*fleet.UploadSoftwareInstallerPayload) ([]fleet.SoftwarePackageResponse, error) { s.mu.Lock() s.BatchSetSoftwareInstallersFuncInvoked = true s.mu.Unlock() diff --git a/server/service/client.go b/server/service/client.go index 2818da432f40..6be25f00834a 100644 --- a/server/service/client.go +++ b/server/service/client.go @@ -397,8 +397,8 @@ func (c *Client) ApplyGroup( logf func(format string, args ...interface{}), appconfig *fleet.EnrichedAppConfig, opts fleet.ApplyClientSpecOptions, -) (map[string]uint, map[string][]fleet.SoftwareInstaller, error) { - teamSoftwareInstallers := make(map[string][]fleet.SoftwareInstaller) +) (map[string]uint, map[string][]fleet.SoftwarePackageResponse, error) { + teamSoftwareInstallers := make(map[string][]fleet.SoftwarePackageResponse) logfn := func(format string, args ...interface{}) { if logf != nil { @@ -1470,7 +1470,7 @@ func (c *Client) DoGitOps( return nil, err } - var teamSoftwareInstallers []fleet.SoftwareInstaller + var teamSoftwareInstallers []fleet.SoftwarePackageResponse if config.TeamName != nil { if !config.IsNoTeam() { if len(teamIDsByName) != 1 { @@ -1510,8 +1510,8 @@ func (c *Client) DoGitOps( return teamAssumptions, nil } -func (c *Client) doGitOpsNoTeamSoftware(config *spec.GitOps, baseDir string, appconfig *fleet.EnrichedAppConfig, logFn func(format string, args ...interface{}), dryRun bool) ([]fleet.SoftwareInstaller, error) { - var softwareInstallers []fleet.SoftwareInstaller +func (c *Client) doGitOpsNoTeamSoftware(config *spec.GitOps, baseDir string, appconfig *fleet.EnrichedAppConfig, logFn func(format string, args ...interface{}), dryRun bool) ([]fleet.SoftwarePackageResponse, error) { + var softwareInstallers []fleet.SoftwarePackageResponse if config.IsNoTeam() && appconfig != nil && appconfig.License.IsPremium() { packages := make([]fleet.SoftwarePackageSpec, 0, len(config.Software.Packages)) for _, software := range config.Software.Packages { @@ -1538,7 +1538,7 @@ func (c *Client) doGitOpsNoTeamSoftware(config *spec.GitOps, baseDir string, app return softwareInstallers, nil } -func (c *Client) doGitOpsPolicies(config *spec.GitOps, teamSoftwareInstallers []fleet.SoftwareInstaller, logFn func(format string, args ...interface{}), dryRun bool) error { +func (c *Client) doGitOpsPolicies(config *spec.GitOps, teamSoftwareInstallers []fleet.SoftwarePackageResponse, logFn func(format string, args ...interface{}), dryRun bool) error { var teamID *uint // Global policies (nil) switch { case config.TeamID != nil: // Team policies @@ -1550,14 +1550,14 @@ func (c *Client) doGitOpsPolicies(config *spec.GitOps, teamSoftwareInstallers [] if teamID != nil { softwareTitleURLs := make(map[string]uint) for _, softwareInstaller := range teamSoftwareInstallers { - if softwareInstaller.URL == "" { - // Should not happen because we previously applied packages via gitops, but to not panic we just log a warning. - logFn("[!] software installer without url: %s\n", softwareInstaller.Name) - continue - } if softwareInstaller.TitleID == nil { // Should not happen, but to not panic we just log a warning. - logFn("[!] software installer without title id: %s\n", softwareInstaller.Name) + logFn("[!] software installer without title id: team_id=%d, url=%s\n", *teamID, softwareInstaller.URL) + continue + } + if softwareInstaller.URL == "" { + // Should not happen because we previously applied packages via gitops, but to not panic we just log a warning. + logFn("[!] software installer without url: team_id=%d, title_id=%d\n", *teamID, *softwareInstaller.TitleID) continue } softwareTitleURLs[softwareInstaller.URL] = *softwareInstaller.TitleID diff --git a/server/service/client_software.go b/server/service/client_software.go index acf402732e9a..413e6dc7e9d8 100644 --- a/server/service/client_software.go +++ b/server/service/client_software.go @@ -28,7 +28,7 @@ func (c *Client) ListSoftwareTitles(query string) ([]fleet.SoftwareTitleListResu return responseBody.SoftwareTitles, nil } -func (c *Client) ApplyNoTeamSoftwareInstallers(softwareInstallers []fleet.SoftwareInstallerPayload, opts fleet.ApplySpecOptions) ([]fleet.SoftwareInstaller, error) { +func (c *Client) ApplyNoTeamSoftwareInstallers(softwareInstallers []fleet.SoftwareInstallerPayload, opts fleet.ApplySpecOptions) ([]fleet.SoftwarePackageResponse, error) { verb, path := "POST", "/api/latest/fleet/software/batch" query, err := url.ParseQuery(opts.RawQuery()) if err != nil { @@ -38,5 +38,5 @@ func (c *Client) ApplyNoTeamSoftwareInstallers(softwareInstallers []fleet.Softwa if err := c.authenticatedRequestWithQuery(map[string]interface{}{"software": softwareInstallers}, verb, path, &resp, query.Encode()); err != nil { return nil, err } - return resp.Installers, nil + return resp.Packages, nil } diff --git a/server/service/client_teams.go b/server/service/client_teams.go index da9332067a53..5c5180a6b700 100644 --- a/server/service/client_teams.go +++ b/server/service/client_teams.go @@ -93,7 +93,7 @@ func (c *Client) ApplyTeamScripts(tmName string, scripts []fleet.ScriptPayload, return c.authenticatedRequestWithQuery(map[string]interface{}{"scripts": scripts}, verb, path, nil, query.Encode()) } -func (c *Client) ApplyTeamSoftwareInstallers(tmName string, softwareInstallers []fleet.SoftwareInstallerPayload, opts fleet.ApplySpecOptions) ([]fleet.SoftwareInstaller, error) { +func (c *Client) ApplyTeamSoftwareInstallers(tmName string, softwareInstallers []fleet.SoftwareInstallerPayload, opts fleet.ApplySpecOptions) ([]fleet.SoftwarePackageResponse, error) { verb, path := "POST", "/api/latest/fleet/software/batch" query, err := url.ParseQuery(opts.RawQuery()) if err != nil { @@ -104,7 +104,7 @@ func (c *Client) ApplyTeamSoftwareInstallers(tmName string, softwareInstallers [ if err := c.authenticatedRequestWithQuery(map[string]interface{}{"software": softwareInstallers}, verb, path, &resp, query.Encode()); err != nil { return nil, err } - return resp.Installers, nil + return resp.Packages, nil } func (c *Client) ApplyTeamAppStoreAppsAssociation(tmName string, vppBatchPayload []fleet.VPPBatchPayload, opts fleet.ApplySpecOptions) error { diff --git a/server/service/software_installers.go b/server/service/software_installers.go index b64be63e3efc..eef55a7da46b 100644 --- a/server/service/software_installers.go +++ b/server/service/software_installers.go @@ -402,22 +402,22 @@ type batchSetSoftwareInstallersRequest struct { } type batchSetSoftwareInstallersResponse struct { - Installers []fleet.SoftwareInstaller `json:"installers"` - Err error `json:"error,omitempty"` + Packages []fleet.SoftwarePackageResponse `json:"packages"` + Err error `json:"error,omitempty"` } func (r batchSetSoftwareInstallersResponse) error() error { return r.Err } func batchSetSoftwareInstallersEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (errorer, error) { req := request.(*batchSetSoftwareInstallersRequest) - installers, err := svc.BatchSetSoftwareInstallers(ctx, req.TeamName, req.Software, req.DryRun) + packages, err := svc.BatchSetSoftwareInstallers(ctx, req.TeamName, req.Software, req.DryRun) if err != nil { return batchSetSoftwareInstallersResponse{Err: err}, nil } - return batchSetSoftwareInstallersResponse{Installers: installers}, nil + return batchSetSoftwareInstallersResponse{Packages: packages}, nil } -func (svc *Service) BatchSetSoftwareInstallers(ctx context.Context, tmName string, payloads []fleet.SoftwareInstallerPayload, dryRun bool) ([]fleet.SoftwareInstaller, error) { +func (svc *Service) BatchSetSoftwareInstallers(ctx context.Context, tmName string, payloads []fleet.SoftwareInstallerPayload, dryRun bool) ([]fleet.SoftwarePackageResponse, error) { // skipauth: No authorization check needed due to implementation returning // only license error. svc.authz.SkipAuthorization(ctx)