Fix upcoming activities for automatic installers (#21714)

Small fix for #21428.

This is to show the activity the right way (Because installations
triggered by Fleet will have `host_software_installs` with `NULL`
`user_id`.).
This commit is contained in:
Lucas Manuel Rodriguez 2024-08-30 17:00:29 -03:00 committed by GitHub
parent 390c6888d7
commit f30017f354
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 10 deletions

View file

@ -316,10 +316,12 @@ func (ds *Datastore) ListHostUpcomingActivities(ctx context.Context, hostID uint
// list pending software installs
fmt.Sprintf(`SELECT
hsi.execution_id as uuid,
u.name as name,
u.id as user_id,
u.gravatar_url as gravatar_url,
u.email as user_email,
-- policies with automatic installers generate a host_software_installs with (user_id=NULL,self_service=0),
-- thus the user_id for the upcoming activity needs to be the user that uploaded the software installer.
IF(hsi.user_id IS NULL AND NOT hsi.self_service, u2.name, u.name) AS name,
IF(hsi.user_id IS NULL AND NOT hsi.self_service, u2.id, u.id) as user_id,
IF(hsi.user_id IS NULL AND NOT hsi.self_service, u2.gravatar_url, u.gravatar_url) as gravatar_url,
IF(hsi.user_id IS NULL AND NOT hsi.self_service, u2.email, u.email) AS user_email,
:installed_software_type as activity_type,
hsi.created_at as created_at,
JSON_OBJECT(
@ -339,6 +341,8 @@ func (ds *Datastore) ListHostUpcomingActivities(ctx context.Context, hostID uint
software_titles st ON st.id = si.title_id
LEFT OUTER JOIN
users u ON u.id = hsi.user_id
LEFT OUTER JOIN
users u2 ON u2.id = si.user_id
LEFT OUTER JOIN
host_display_names hdn ON hdn.host_id = hsi.host_id
WHERE

View file

@ -494,7 +494,10 @@ func testListHostUpcomingActivities(t *testing.T, ds *Datastore) {
InstallScriptExitCode: ptr.Int(0),
})
require.NoError(t, err)
h1Foo, err := ds.InsertSoftwareInstallRequest(noUserCtx, h1.ID, sw1Meta.InstallerID, false) // no user for this one
// No user for this one and not Self-service, means it was installed by Fleet thus the author was decided to be the admin
// that uploaded the installer.
h1Foo, err := ds.InsertSoftwareInstallRequest(noUserCtx, h1.ID, sw1Meta.InstallerID, false)
require.NoError(t, err)
// create a single pending request for h2, as well as a non-pending one
@ -509,6 +512,9 @@ func testListHostUpcomingActivities(t *testing.T, ds *Datastore) {
// add a pending software install request for h2
h2Bar, err := ds.InsertSoftwareInstallRequest(ctx, h2.ID, sw2Meta.InstallerID, false)
require.NoError(t, err)
// No user for this one and Self-service, means it was installed by the end user, so the user_id should be null/nil.
h2Foo, err := ds.InsertSoftwareInstallRequest(noUserCtx, h2.ID, sw1Meta.InstallerID, true)
require.NoError(t, err)
// nothing for h3
@ -517,6 +523,8 @@ func testListHostUpcomingActivities(t *testing.T, ds *Datastore) {
endTime = SetOrderedCreatedAtTimestamps(t, ds, endTime, "host_software_installs", "execution_id", h1FooFailed, h1Bar)
endTime = SetOrderedCreatedAtTimestamps(t, ds, endTime, "host_script_results", "execution_id", h1C, h1D, h1E)
endTime = SetOrderedCreatedAtTimestamps(t, ds, endTime, "host_software_installs", "execution_id", h1FooInstalled, h1Foo)
endTime = SetOrderedCreatedAtTimestamps(t, ds, endTime, "host_software_installs", "execution_id", h1Foo)
endTime = SetOrderedCreatedAtTimestamps(t, ds, endTime, "host_software_installs", "execution_id", h2Foo)
endTime = SetOrderedCreatedAtTimestamps(t, ds, endTime, "host_software_installs", "execution_id", h2Bar)
endTime = SetOrderedCreatedAtTimestamps(t, ds, endTime, "host_script_results", "execution_id", h2A, h2F)
SetOrderedCreatedAtTimestamps(t, ds, endTime, "host_vpp_software_installs", "command_uuid", vppCommand1, vppCommand2)
@ -529,7 +537,8 @@ func testListHostUpcomingActivities(t *testing.T, ds *Datastore) {
h1E: false,
h2A: true,
h2F: true,
h1Foo: false,
h1Foo: true,
h2Foo: false,
h1Bar: true,
h2Bar: true,
vppCommand1: true,
@ -544,6 +553,10 @@ func testListHostUpcomingActivities(t *testing.T, ds *Datastore) {
h1Foo: "foo",
h1Bar: "bar",
h2Bar: "bar",
h2Foo: "foo",
}
execIDsWithUserAdminID := map[string]struct{}{
h1Foo: {},
}
cases := []struct {
@ -595,10 +608,10 @@ func testListHostUpcomingActivities(t *testing.T, ds *Datastore) {
wantMeta: &fleet.PaginationMetadata{HasNextResults: false, HasPreviousResults: true, TotalResults: 8},
},
{
opts: fleet.ListOptions{PerPage: 3},
opts: fleet.ListOptions{PerPage: 4},
hostID: h2.ID,
wantExecs: []string{h2Bar, h2A, vppCommand2},
wantMeta: &fleet.PaginationMetadata{HasNextResults: false, HasPreviousResults: false, TotalResults: 3},
wantExecs: []string{h2Foo, h2Bar, h2A, vppCommand2},
wantMeta: &fleet.PaginationMetadata{HasNextResults: false, HasPreviousResults: false, TotalResults: 4},
},
{
opts: fleet.ListOptions{},
@ -639,7 +652,11 @@ func testListHostUpcomingActivities(t *testing.T, ds *Datastore) {
case fleet.ActivityTypeInstalledSoftware{}.ActivityName():
require.Equal(t, wantExec, details["install_uuid"], "result %d", i)
require.Equal(t, execIDsSoftwareTitle[wantExec], details["software_title"], "result %d", i)
wantUser = u2
if _, ok := execIDsWithUserAdminID[details["install_uuid"].(string)]; ok {
wantUser = u
} else {
wantUser = u2
}
case fleet.ActivityInstalledAppStoreApp{}.ActivityName():
require.Equal(t, wantExec, details["command_uuid"], "result %d", i)

View file

@ -13214,6 +13214,16 @@ func (s *integrationEnterpriseTestSuite) TestPolicyAutomationsSoftwareInstallers
},
), http.StatusOK, &distributedResp)
// Upcoming activities for host1Team1 should show the automatic installation of dummy_installer.pkg.
// Check the author should be the admin that uploaded the installer.
var listUpcomingAct listHostUpcomingActivitiesResponse
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d/activities/upcoming", host1Team1.ID), nil, http.StatusOK, &listUpcomingAct)
require.Len(t, listUpcomingAct.Activities, 1)
require.NotNil(t, listUpcomingAct.Activities[0].ActorID)
require.Equal(t, globalAdmin.ID, *listUpcomingAct.Activities[0].ActorID)
require.Equal(t, globalAdmin.Name, *listUpcomingAct.Activities[0].ActorFullName)
require.Equal(t, globalAdmin.Email, *listUpcomingAct.Activities[0].ActorEmail)
//
// Finally have orbit install the packages and check activities.
//