Add activity item for resend configuration profile (#18271)

This commit is contained in:
Sarah Gillespie 2024-04-15 14:18:09 -05:00 committed by GitHub
parent 1e6839c004
commit ecdcb7c2fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 72 additions and 4 deletions

View file

@ -1108,6 +1108,25 @@ This activity contains the following fields:
}
```
## resent_configuration_profile
Generated when a user resends an MDM configuration profile to a host.
This activity contains the following fields:
- "host_id": The ID of the host.
- "host_display_name": The display name of the host.
- "profile_name": The name of the configuration profile.
#### Example
```json
{
"host_id": 1,
"host_display_name": "Anna's MacBook Pro",
"profile_name": "Passcode requirements"
}
```
<meta name="title" value="Audit logs">
<meta name="pageOrderInSection" value="1400">

View file

@ -88,6 +88,8 @@ var ActivityDetailsList = []ActivityDetails{
ActivityTypeCreatedDeclarationProfile{},
ActivityTypeDeletedDeclarationProfile{},
ActivityTypeEditedDeclarationProfile{},
ActivityTypeResentConfigurationProfile{},
}
type ActivityDetails interface {
@ -1390,6 +1392,28 @@ func (a ActivityTypeEditedDeclarationProfile) Documentation() (activity string,
}`
}
type ActivityTypeResentConfigurationProfile struct {
HostID *uint `json:"host_id"`
HostDisplayName *string `json:"host_display_name"`
ProfileName string `json:"profile_name"`
}
func (a ActivityTypeResentConfigurationProfile) ActivityName() string {
return "resent_configuration_profile"
}
func (a ActivityTypeResentConfigurationProfile) Documentation() (activity string, details string, detailsExample string) {
return `Generated when a user resends an MDM configuration profile to a host.`,
`This activity contains the following fields:
- "host_id": The ID of the host.
- "host_display_name": The display name of the host.
- "profile_name": The name of the configuration profile.`, `{
"host_id": 1,
"host_display_name": "Anna's MacBook Pro",
"profile_name": "Passcode requirements"
}`
}
// LogRoleChangeActivities logs activities for each role change, globally and one for each change in teams.
func LogRoleChangeActivities(ctx context.Context, ds Datastore, adminUser *User, oldGlobalRole *string, oldTeamRoles []UserTeam, user *User) error {
if user.GlobalRole != nil && (oldGlobalRole == nil || *oldGlobalRole != *user.GlobalRole) {

View file

@ -791,14 +791,18 @@ func (s *integrationMDMTestSuite) TestAppleProfileManagement() {
require.Equal(t, prof, installs[0])
require.Empty(t, removes)
s.checkMDMProfilesSummaries(t, &tm.ID, fleet.MDMProfilesSummary{Verifying: 1}, nil)
s.lastActivityMatches(
fleet.ActivityTypeResentConfigurationProfile{}.ActivityName(),
fmt.Sprintf(`{"host_id": %d, "host_display_name": %q, "profile_name": %q}`, host.ID, host.DisplayName(), "name-"+mcUUID),
0)
// add a declaration to the team
declIdent := "decl-ident-" + t.Name()
declIdent := "decl-ident-" + uuid.NewString()
fields := map[string][]string{
"team_id": {fmt.Sprintf("%d", tm.ID)},
}
body, headers := generateNewProfileMultipartRequest(
t, declIdent+".json", declarationForTest(declIdent), s.token, fields,
t, "some-declaration.json", declarationForTest(declIdent), s.token, fields,
)
res = s.DoRawWithHeaders("POST", "/api/latest/fleet/configuration_profiles", body.Bytes(), http.StatusOK, headers)
var resp newMDMConfigProfileResponse
@ -837,6 +841,10 @@ func (s *integrationMDMTestSuite) TestAppleProfileManagement() {
_ = s.DoRaw("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/configuration_profiles/resend/%s", host.ID, declUUID), nil, http.StatusAccepted)
checkDDMSync(mdmDevice)
s.checkMDMProfilesSummaries(t, &tm.ID, fleet.MDMProfilesSummary{Verifying: 1}, nil)
s.lastActivityMatches(
fleet.ActivityTypeResentConfigurationProfile{}.ActivityName(),
fmt.Sprintf(`{"host_id": %d, "host_display_name": %q, "profile_name": "some-declaration"}`, host.ID, host.DisplayName()),
0)
// transfer the host to the global team
err = s.ds.AddHostsToTeam(ctx, nil, []uint{host.ID})
@ -11007,7 +11015,11 @@ func (s *integrationMDMTestSuite) TestWindowsProfileManagement() {
// can resend a profile after it has failed
res = s.DoRaw("POST", fmt.Sprintf("/api/latest/fleet/hosts/%d/configuration_profiles/resend/%s", host.ID, teamProfiles[0]), nil, http.StatusAccepted)
verifyProfiles(mdmDevice, 1, false) // trigger a profile sync, device gets the profile resent
checkHostProfileStatus(t, host.UUID, teamProfiles[0], fleet.MDMDeliveryVerifying) // profile was resent, so it back to verifying
checkHostProfileStatus(t, host.UUID, teamProfiles[0], fleet.MDMDeliveryVerifying) // profile was resent, so back to verifying
s.lastActivityMatches(
fleet.ActivityTypeResentConfigurationProfile{}.ActivityName(),
fmt.Sprintf(`{"host_id": %d, "host_display_name": %q, "profile_name": %q}`, host.ID, host.DisplayName(), "name-"+teamProfiles[0]),
0)
// add a macOS profile to the team
mcUUID := "a" + uuid.NewString()

View file

@ -2025,6 +2025,7 @@ func (svc *Service) ResendHostMDMProfile(ctx context.Context, hostID uint, profi
}
var profileTeamID *uint
var profileName string
switch {
case strings.HasPrefix(profileUUID, fleet.MDMAppleProfileUUIDPrefix):
if err := svc.VerifyMDMAppleConfigured(ctx); err != nil {
@ -2038,6 +2039,7 @@ func (svc *Service) ResendHostMDMProfile(ctx context.Context, hostID uint, profi
return ctxerr.Wrap(ctx, err, "getting apple config profile")
}
profileTeamID = prof.TeamID
profileName = prof.Name
case strings.HasPrefix(profileUUID, fleet.MDMAppleDeclarationUUIDPrefix):
if err := svc.VerifyMDMAppleConfigured(ctx); err != nil {
@ -2051,6 +2053,7 @@ func (svc *Service) ResendHostMDMProfile(ctx context.Context, hostID uint, profi
return ctxerr.Wrap(ctx, err, "getting apple declaration")
}
profileTeamID = decl.TeamID
profileName = decl.Name
case strings.HasPrefix(profileUUID, fleet.MDMWindowsProfileUUIDPrefix):
if err := svc.VerifyMDMWindowsConfigured(ctx); err != nil {
@ -2064,6 +2067,7 @@ func (svc *Service) ResendHostMDMProfile(ctx context.Context, hostID uint, profi
return ctxerr.Wrap(ctx, err, "getting windows config profile")
}
profileTeamID = prof.TeamID
profileName = prof.Name
default:
return ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("HostMDMProfile", "Invalid profile UUID prefix.").WithStatus(http.StatusNotFound), "check profile UUID prefix")
@ -2093,7 +2097,13 @@ func (svc *Service) ResendHostMDMProfile(ctx context.Context, hostID uint, profi
return ctxerr.Wrap(ctx, err, "resending host mdm profile")
}
// TODO: log activity?
if err := svc.ds.NewActivity(ctx, authz.UserFromContext(ctx), &fleet.ActivityTypeResentConfigurationProfile{
HostID: &host.ID,
HostDisplayName: ptr.String(host.DisplayName()),
ProfileName: profileName,
}); err != nil {
return ctxerr.Wrap(ctx, err, "logging activity for resend config profile")
}
return nil
}

View file

@ -1708,6 +1708,9 @@ func TestMDMResendConfigProfileAuthz(t *testing.T) {
ds.ResendHostMDMProfileFunc = func(ctx context.Context, hostUUID, profUUID string) error {
return nil
}
ds.NewActivityFunc = func(context.Context, *fleet.User, fleet.ActivityDetails) error {
return nil
}
checkShouldFail := func(t *testing.T, err error, shouldFail bool) {
if !shouldFail {