From bc6dc21ac9956eecd015516aa1d32b3293ac527f Mon Sep 17 00:00:00 2001
From: jacobshandling <61553566+jacobshandling@users.noreply.github.com>
Date: Thu, 10 Apr 2025 13:50:14 -0700
Subject: [PATCH] Add host id to fleet enrolled activity (#28068)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## For #26695
- [x] Changes file added for user-visible changes in `changes/`
- [x] Added/updated automated tests
- [x] A detailed QA plan exists on the associated ticket (if it isn't
there, work with the product group's QA engineer to add it)
- [x] Manual QA for all new/changed functionality
---------
Co-authored-by: Jacob Shandling
---
.../26695-add-host-id-to-fleet-enrolled-activity | 1 +
docs/Contributing/Audit-logs.md | 6 ++++--
server/datastore/mysql/activities.go | 13 ++++++++-----
server/fleet/activities.go | 7 +++++--
server/service/integration_mdm_test.go | 10 +++++-----
server/service/orbit.go | 1 +
6 files changed, 24 insertions(+), 14 deletions(-)
create mode 100644 changes/26695-add-host-id-to-fleet-enrolled-activity
diff --git a/changes/26695-add-host-id-to-fleet-enrolled-activity b/changes/26695-add-host-id-to-fleet-enrolled-activity
new file mode 100644
index 0000000000..5a5c70c693
--- /dev/null
+++ b/changes/26695-add-host-id-to-fleet-enrolled-activity
@@ -0,0 +1 @@
+* Include newly created host ids in activities generated when hosts enroll in fleet
diff --git a/docs/Contributing/Audit-logs.md b/docs/Contributing/Audit-logs.md
index 0185fa8d89..dc2e5f83ba 100644
--- a/docs/Contributing/Audit-logs.md
+++ b/docs/Contributing/Audit-logs.md
@@ -526,6 +526,7 @@ This activity contains the following fields:
Generated when a host is enrolled to Fleet (Fleet's agent fleetd is installed).
This activity contains the following fields:
+- "host_id": ID of the host.
- "host_serial": Serial number of the host.
- "host_display_name": Display name of the host.
@@ -533,8 +534,9 @@ This activity contains the following fields:
```json
{
- "host_serial": "B04FL3ALPT21",
- "host_display_name": "WIN-DESKTOP-JGS78KJ7C"
+ "host_id": "123",
+ "host_serial": "B04FL3ALPT21",
+ "host_display_name": "WIN-DESKTOP-JGS78KJ7C"
}
```
diff --git a/server/datastore/mysql/activities.go b/server/datastore/mysql/activities.go
index 9c0b92cf6f..a21bc34c11 100644
--- a/server/datastore/mysql/activities.go
+++ b/server/datastore/mysql/activities.go
@@ -17,8 +17,10 @@ import (
"github.com/jmoiron/sqlx"
)
-var automationActivityAuthor = "Fleet"
-var deleteIDsBatchSize = 1000
+var (
+ automationActivityAuthor = "Fleet"
+ deleteIDsBatchSize = 1000
+)
// NewActivity stores an activity item that the user performed
func (ds *Datastore) NewActivity(
@@ -772,8 +774,10 @@ func (ds *Datastore) CancelHostUpcomingActivity(ctx context.Context, hostID uint
// read the activity along with the required information to create the
// "canceled" past activity, and check if the activity was activated or
// not.
- stmt := strings.Join([]string{loadScriptActivityStmt, loadSoftwareInstallActivityStmt,
- loadSoftwareUninstallActivityStmt, loadVPPAppInstallActivityStmt}, " UNION ALL ")
+ stmt := strings.Join([]string{
+ loadScriptActivityStmt, loadSoftwareInstallActivityStmt,
+ loadSoftwareUninstallActivityStmt, loadVPPAppInstallActivityStmt,
+ }, " UNION ALL ")
stmt, args, err := sqlx.Named(stmt, map[string]any{"host_id": hostID, "execution_id": executionID})
if err != nil {
return ctxerr.Wrap(ctx, err, "build load upcoming activity to cancel statement")
@@ -932,7 +936,6 @@ func (ds *Datastore) CancelHostUpcomingActivity(ctx context.Context, hostID uint
}
return nil
})
-
if err != nil {
return nil, err
}
diff --git a/server/fleet/activities.go b/server/fleet/activities.go
index b9369c2790..7c5a5c3f4d 100644
--- a/server/fleet/activities.go
+++ b/server/fleet/activities.go
@@ -865,6 +865,7 @@ func (a ActivityTypeDeletedUserTeamRole) Documentation() (activity string, detai
}
type ActivityTypeFleetEnrolled struct {
+ HostID uint `json:"host_id"`
HostSerial string `json:"host_serial"`
HostDisplayName string `json:"host_display_name"`
}
@@ -876,10 +877,12 @@ func (a ActivityTypeFleetEnrolled) ActivityName() string {
func (a ActivityTypeFleetEnrolled) Documentation() (activity string, details string, detailsExample string) {
return `Generated when a host is enrolled to Fleet (Fleet's agent fleetd is installed).`,
`This activity contains the following fields:
+- "host_id": ID of the host.
- "host_serial": Serial number of the host.
- "host_display_name": Display name of the host.`, `{
- "host_serial": "B04FL3ALPT21",
- "host_display_name": "WIN-DESKTOP-JGS78KJ7C"
+ "host_id": "123",
+ "host_serial": "B04FL3ALPT21",
+ "host_display_name": "WIN-DESKTOP-JGS78KJ7C"
}`
}
diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go
index 686cd510d2..3e70f771bc 100644
--- a/server/service/integration_mdm_test.go
+++ b/server/service/integration_mdm_test.go
@@ -2734,7 +2734,7 @@ func (s *integrationMDMTestSuite) TestEnrollOrbitAfterDEPSync() {
s.lastActivityMatches(
"fleet_enrolled",
- fmt.Sprintf(`{"host_display_name": "%s", "host_serial": "%s"}`, h.DisplayName(), h.HardwareSerial),
+ fmt.Sprintf(`{"host_id": %v, "host_display_name": "%s", "host_serial": "%s"}`, h.ID, h.DisplayName(), h.HardwareSerial),
0,
)
@@ -5199,7 +5199,7 @@ func (s *integrationMDMTestSuite) setTokenForTest(t *testing.T, email, password
func (s *integrationMDMTestSuite) TestSSO() {
t := s.T()
- var lastSubmittedProfile = &godep.Profile{}
+ lastSubmittedProfile := &godep.Profile{}
mdmDevice, wantSettings := s.setUpEndUserAuthentication(t, lastSubmittedProfile)
// patch without specifying the mdm sso settings fields and an unrelated
@@ -5626,7 +5626,7 @@ func (s *integrationMDMTestSuite) checkStoredIdPInfo(t *testing.T, uuid, usernam
func (s *integrationMDMTestSuite) TestSSOWithSCIM() {
t := s.T()
- var lastSubmittedProfile = &godep.Profile{}
+ lastSubmittedProfile := &godep.Profile{}
mdmDevice, _ := s.setUpEndUserAuthentication(t, lastSubmittedProfile)
res := s.LoginMDMSSOUser("sso_user_no_displayname", "user123#")
@@ -5822,11 +5822,11 @@ func (s *integrationMDMTestSuite) TestSSOWithSCIM() {
hostResp = getHostResponse{}
s.DoJSON("GET", fmt.Sprintf("/api/v1/fleet/hosts/%d", hostID), nil, http.StatusOK, &hostResp)
checkEndUser()
-
}
func (s *integrationMDMTestSuite) setUpEndUserAuthentication(t *testing.T, lastSubmittedProfile *godep.Profile) (*mdmtest.TestAppleMDMClient,
- fleet.SSOProviderSettings) {
+ fleet.SSOProviderSettings,
+) {
mdmDevice := mdmtest.NewTestMDMClientAppleDirect(mdmtest.AppleEnrollInfo{
SCEPChallenge: s.scepChallenge,
}, "MacBookPro16,1")
diff --git a/server/service/orbit.go b/server/service/orbit.go
index bcaa985efa..f7e9c250e9 100644
--- a/server/service/orbit.go
+++ b/server/service/orbit.go
@@ -174,6 +174,7 @@ func (svc *Service) EnrollOrbit(ctx context.Context, hostInfo fleet.OrbitHostInf
ctx,
nil,
fleet.ActivityTypeFleetEnrolled{
+ HostID: host.ID,
HostSerial: hostInfo.HardwareSerial,
HostDisplayName: host.DisplayName(),
},