mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 08:58:41 +00:00
add activity items when a Windows host turns MDM on (#12635)
For #12427, and its sub-tasks #12288 and #12612 
This commit is contained in:
parent
100b211ba5
commit
2b4798c4ab
10 changed files with 123 additions and 9 deletions
|
|
@ -553,6 +553,7 @@ This activity contains the following fields:
|
|||
- "host_serial": Serial number of the host.
|
||||
- "host_display_name": Display name of the host.
|
||||
- "installed_from_dep": Whether the host was enrolled via DEP.
|
||||
- "mdm_platform": Used to distinguish between Apple and Microsoft enrollments. Can be "apple", "microsoft" or not present. If missing, this value is treated as "apple" for backwards compatibility.
|
||||
|
||||
#### Example
|
||||
|
||||
|
|
@ -560,7 +561,8 @@ This activity contains the following fields:
|
|||
{
|
||||
"host_serial": "C08VQ2AXHT96",
|
||||
"host_display_name": "MacBookPro16,1 (C08VQ2AXHT96)",
|
||||
"installed_from_dep": true
|
||||
"installed_from_dep": true,
|
||||
"mdm_platform": "apple"
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ export interface IActivityDetails {
|
|||
host_display_names?: string[];
|
||||
host_ids?: number[];
|
||||
installed_from_dep?: boolean;
|
||||
mdm_platform?: "microsoft" | "apple";
|
||||
minimum_version?: string;
|
||||
deadline?: string;
|
||||
profile_name?: string;
|
||||
|
|
|
|||
|
|
@ -708,4 +708,65 @@ describe("Activity Feed", () => {
|
|||
expect(screen.queryByText("baz")).toBeNull();
|
||||
expect(screen.getByText("Alphas", { exact: false })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders a 'mdm_enrolled' type for apple if mdm_platform is not provided", () => {
|
||||
const activity = createMockActivity({
|
||||
type: ActivityType.MdmEnrolled,
|
||||
details: {
|
||||
host_serial: "ABCD",
|
||||
},
|
||||
});
|
||||
render(<ActivityItem activity={activity} isPremiumTier />);
|
||||
|
||||
expect(
|
||||
screen.getByText((content, node) => {
|
||||
return (
|
||||
node?.innerHTML ===
|
||||
"<b>Test User </b>An end user turned on MDM features for a host with serial number <b>ABCD (manual)</b>."
|
||||
);
|
||||
})
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders a 'mdm_enrolled' type for apple with all details provided", () => {
|
||||
const activity = createMockActivity({
|
||||
type: ActivityType.MdmEnrolled,
|
||||
details: {
|
||||
host_serial: "ABCD",
|
||||
installed_from_dep: true,
|
||||
mdm_platform: "apple",
|
||||
},
|
||||
});
|
||||
render(<ActivityItem activity={activity} isPremiumTier />);
|
||||
|
||||
expect(
|
||||
screen.getByText((content, node) => {
|
||||
return (
|
||||
node?.innerHTML ===
|
||||
"<b>Test User </b>An end user turned on MDM features for a host with serial number <b>ABCD (automatic)</b>."
|
||||
);
|
||||
})
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders a 'mdm_enrolled' type activity for windows hosts.", () => {
|
||||
const activity = createMockActivity({
|
||||
type: ActivityType.MdmEnrolled,
|
||||
details: {
|
||||
mdm_platform: "microsoft",
|
||||
host_display_name: "ABCD",
|
||||
},
|
||||
});
|
||||
render(<ActivityItem activity={activity} isPremiumTier />);
|
||||
|
||||
expect(
|
||||
screen.getByText((content, node) => {
|
||||
console.log(node?.innerHTML);
|
||||
return (
|
||||
node?.innerHTML ===
|
||||
"<b>Test User </b>Mobile device management (MDM) was turned on for <b>ABCD (manual)</b>."
|
||||
);
|
||||
})
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -215,6 +215,17 @@ const TAGGED_TEMPLATES = {
|
|||
);
|
||||
},
|
||||
mdmEnrolled: (activity: IActivity) => {
|
||||
if (activity.details?.mdm_platform === "microsoft") {
|
||||
return (
|
||||
<>
|
||||
Mobile device management (MDM) was turned on for{" "}
|
||||
<b>{activity.details?.host_display_name} (manual)</b>.
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// note: if mdm_platform is missing, we assume this is Apple MDM for backwards
|
||||
// compatibility
|
||||
return (
|
||||
<>
|
||||
An end user turned on MDM features for a host with serial number{" "}
|
||||
|
|
|
|||
|
|
@ -692,6 +692,7 @@ type ActivityTypeMDMEnrolled struct {
|
|||
HostSerial string `json:"host_serial"`
|
||||
HostDisplayName string `json:"host_display_name"`
|
||||
InstalledFromDEP bool `json:"installed_from_dep"`
|
||||
MDMPlatform string `json:"mdm_platform"`
|
||||
}
|
||||
|
||||
func (a ActivityTypeMDMEnrolled) ActivityName() string {
|
||||
|
|
@ -703,10 +704,12 @@ func (a ActivityTypeMDMEnrolled) Documentation() (activity string, details strin
|
|||
`This activity contains the following fields:
|
||||
- "host_serial": Serial number of the host.
|
||||
- "host_display_name": Display name of the host.
|
||||
- "installed_from_dep": Whether the host was enrolled via DEP.`, `{
|
||||
- "installed_from_dep": Whether the host was enrolled via DEP.
|
||||
- "mdm_platform": Used to distinguish between Apple and Microsoft enrollments. Can be "apple", "microsoft" or not present. If missing, this value is treated as "apple" for backwards compatibility.`, `{
|
||||
"host_serial": "C08VQ2AXHT96",
|
||||
"host_display_name": "MacBookPro16,1 (C08VQ2AXHT96)",
|
||||
"installed_from_dep": true
|
||||
"installed_from_dep": true,
|
||||
"mdm_platform": "apple"
|
||||
}`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
MDMPlatformApple = "apple"
|
||||
MDMPlatformMicrosoft = "microsoft"
|
||||
)
|
||||
|
||||
type AppleMDM struct {
|
||||
CommonName string `json:"common_name"`
|
||||
SerialNumber string `json:"serial_number"`
|
||||
|
|
|
|||
|
|
@ -2211,6 +2211,7 @@ func (svc *MDMAppleCheckinAndCommandService) Authenticate(r *mdm.Request, m *mdm
|
|||
HostSerial: info.HardwareSerial,
|
||||
HostDisplayName: info.DisplayName,
|
||||
InstalledFromDEP: info.InstalledFromDEP,
|
||||
MDMPlatform: fleet.MDMPlatformApple,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -972,6 +972,7 @@ func TestMDMAuthenticate(t *testing.T) {
|
|||
require.Equal(t, serial, a.HostSerial)
|
||||
require.Equal(t, a.HostDisplayName, fmt.Sprintf("%s (%s)", model, serial))
|
||||
require.False(t, a.InstalledFromDEP)
|
||||
require.Equal(t, fleet.MDMPlatformApple, a.MDMPlatform)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -925,7 +925,7 @@ func (s *integrationMDMTestSuite) TestDEPProfileAssignment() {
|
|||
require.JSONEq(
|
||||
t,
|
||||
fmt.Sprintf(
|
||||
`{"host_serial": "%s", "host_display_name": "%s (%s)", "installed_from_dep": true}`,
|
||||
`{"host_serial": "%s", "host_display_name": "%s (%s)", "installed_from_dep": true, "mdm_platform": "apple"}`,
|
||||
devices[0].SerialNumber, devices[0].Model, devices[0].SerialNumber,
|
||||
),
|
||||
string(*activity.Details),
|
||||
|
|
@ -1068,8 +1068,8 @@ func (s *integrationMDMTestSuite) TestAppleMDMDeviceEnrollment() {
|
|||
}
|
||||
}
|
||||
require.Len(t, details, 2)
|
||||
require.JSONEq(t, fmt.Sprintf(`{"host_serial": "%s", "host_display_name": "%s (%s)", "installed_from_dep": false}`, mdmDeviceA.SerialNumber, mdmDeviceA.Model, mdmDeviceA.SerialNumber), string(*details[len(details)-2]))
|
||||
require.JSONEq(t, fmt.Sprintf(`{"host_serial": "%s", "host_display_name": "%s (%s)", "installed_from_dep": false}`, mdmDeviceB.SerialNumber, mdmDeviceB.Model, mdmDeviceB.SerialNumber), string(*details[len(details)-1]))
|
||||
require.JSONEq(t, fmt.Sprintf(`{"host_serial": "%s", "host_display_name": "%s (%s)", "installed_from_dep": false, "mdm_platform": "apple"}`, mdmDeviceA.SerialNumber, mdmDeviceA.Model, mdmDeviceA.SerialNumber), string(*details[len(details)-2]))
|
||||
require.JSONEq(t, fmt.Sprintf(`{"host_serial": "%s", "host_display_name": "%s (%s)", "installed_from_dep": false, "mdm_platform": "apple"}`, mdmDeviceB.SerialNumber, mdmDeviceB.Model, mdmDeviceB.SerialNumber), string(*details[len(details)-1]))
|
||||
|
||||
// set an enroll secret
|
||||
var applyResp applyEnrollSecretSpecResponse
|
||||
|
|
@ -5414,6 +5414,17 @@ func (s *integrationMDMTestSuite) TestValidRequestSecurityTokenRequest() {
|
|||
require.True(t, s.isXMLTagContentPresent("TokenType", resSoapMsg))
|
||||
require.True(t, s.isXMLTagContentPresent("RequestID", resSoapMsg))
|
||||
require.True(t, s.isXMLTagContentPresent("BinarySecurityToken", resSoapMsg))
|
||||
|
||||
// Checking if an activity was created for the enrollment
|
||||
s.lastActivityOfTypeMatches(
|
||||
fleet.ActivityTypeMDMEnrolled{}.ActivityName(),
|
||||
`{
|
||||
"mdm_platform": "microsoft",
|
||||
"host_serial": "",
|
||||
"installed_from_dep": false,
|
||||
"host_display_name": "DESKTOP-0C89RC0"
|
||||
}`,
|
||||
0)
|
||||
}
|
||||
|
||||
func (s *integrationMDMTestSuite) TestInvalidRequestSecurityTokenRequestWithMissingAdditionalContext() {
|
||||
|
|
|
|||
|
|
@ -819,10 +819,15 @@ func (svc *Service) GetMDMWindowsEnrollResponse(ctx context.Context, secTokenMsg
|
|||
return nil, ctxerr.Wrap(ctx, err, "creation of RequestSecurityTokenResponseCollection message")
|
||||
}
|
||||
|
||||
// RequestSecurityTokenResponseCollection message is ready
|
||||
// The identity and provisioning information will be sent to the Windows MDM Enrollment Client
|
||||
// RequestSecurityTokenResponseCollection message is ready. The identity
|
||||
// and provisioning information will be sent to the Windows MDM
|
||||
// Enrollment Client
|
||||
|
||||
// But before doing that, let's save the device information to the list of MDM enrolled MDM devices
|
||||
// But before doing that, let's save the device information to the list
|
||||
// of MDM enrolled MDM devices
|
||||
//
|
||||
// This method also creates the relevant enrollment activity as it has
|
||||
// access to the device information.
|
||||
err = svc.storeWindowsMDMEnrolledDevice(ctx, secTokenMsg)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "enrolled device information cannot be stored")
|
||||
|
|
@ -1004,6 +1009,19 @@ func (svc *Service) storeWindowsMDMEnrolledDevice(ctx context.Context, secTokenM
|
|||
return err
|
||||
}
|
||||
|
||||
err = svc.ds.NewActivity(ctx, nil, &fleet.ActivityTypeMDMEnrolled{
|
||||
HostDisplayName: reqDeviceName,
|
||||
MDMPlatform: fleet.MDMPlatformMicrosoft,
|
||||
})
|
||||
if err != nil {
|
||||
// only logging, the device is enrolled at this point, and we
|
||||
// wouldn't want to fail the request because there was a problem
|
||||
// creating an activity feed item.
|
||||
logging.WithExtras(logging.WithNoUser(ctx),
|
||||
"msg", "failed to generate windows MDM enrolled activity",
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue