Update backend and GitOps to handle AppleOSUpdateSettings.UpdateNewHosts (#37295)
**Related issue:** Resolves #36188 Update backend and GitOps to handle AppleOSUpdateSettings.UpdateNewHosts
This commit is contained in:
@@ -0,0 +1 @@
|
||||
* Updated backend and GitOps to handle AppleOSUpdateSettings.UpdateNewHosts
|
||||
@@ -248,6 +248,7 @@ spec:
|
||||
macos_updates:
|
||||
minimum_version: 12.3.1
|
||||
deadline: 2011-03-01
|
||||
update_new_hosts: true
|
||||
`)
|
||||
|
||||
newAgentOpts := json.RawMessage(`{"config":{"views":{"foo":"bar"}}}`)
|
||||
@@ -255,6 +256,7 @@ spec:
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.3.1"),
|
||||
Deadline: optjson.SetString("2011-03-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
MacOSSetup: fleet.MacOSSetup{
|
||||
EnableReleaseDeviceManually: optjson.SetBool(false),
|
||||
@@ -291,6 +293,7 @@ spec:
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.3.1"),
|
||||
Deadline: optjson.SetString("2011-03-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
DeadlineDays: optjson.SetInt(5),
|
||||
@@ -319,6 +322,7 @@ spec:
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.3.1"),
|
||||
Deadline: optjson.SetString("2011-03-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
DeadlineDays: optjson.SetInt(5),
|
||||
|
||||
@@ -411,12 +411,17 @@ func TestGitOpsBasicGlobalPremium(t *testing.T) {
|
||||
_, err = tmpFile.WriteString(
|
||||
`
|
||||
controls:
|
||||
macos_updates:
|
||||
deadline: "2024-03-03"
|
||||
minimum_version: "18.0"
|
||||
ios_updates:
|
||||
deadline: "2022-02-02"
|
||||
minimum_version: "17.6"
|
||||
update_new_hosts: true
|
||||
ipados_updates:
|
||||
deadline: "2023-03-03"
|
||||
minimum_version: "18.0"
|
||||
update_new_hosts: false
|
||||
enable_disk_encryption: true
|
||||
windows_require_bitlocker_pin: true
|
||||
queries:
|
||||
@@ -487,6 +492,16 @@ software:
|
||||
// Check MDM settings
|
||||
require.True(t, savedAppConfig.MDM.EnableDiskEncryption.Value)
|
||||
require.True(t, savedAppConfig.MDM.RequireBitLockerPIN.Value)
|
||||
require.Equal(t, "18.0", savedAppConfig.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-03-03", savedAppConfig.MDM.MacOSUpdates.Deadline.Value)
|
||||
// To keep things backwards compatible if MinimumVersion & Deadline are set, then UpdateNewHosts should be set to true
|
||||
require.Equal(t, optjson.SetBool(true), savedAppConfig.MDM.MacOSUpdates.UpdateNewHosts)
|
||||
require.Equal(t, "2022-02-02", savedAppConfig.MDM.IOSUpdates.Deadline.Value)
|
||||
require.Equal(t, "17.6", savedAppConfig.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, optjson.Bool{}, savedAppConfig.MDM.IOSUpdates.UpdateNewHosts)
|
||||
require.Equal(t, "2023-03-03", savedAppConfig.MDM.IPadOSUpdates.Deadline.Value)
|
||||
require.Equal(t, "18.0", savedAppConfig.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, optjson.Bool{}, savedAppConfig.MDM.IPadOSUpdates.UpdateNewHosts)
|
||||
|
||||
// Check certificate authorities
|
||||
assert.True(t, ds.GetGroupedCertificateAuthoritiesFuncInvoked)
|
||||
@@ -751,6 +766,9 @@ func TestGitOpsBasicTeam(t *testing.T) {
|
||||
_, err = tmpFile.WriteString(
|
||||
`
|
||||
controls:
|
||||
macos_updates:
|
||||
deadline: "2025-10-10"
|
||||
minimum_version: "18.0"
|
||||
ios_updates:
|
||||
deadline: "2024-10-10"
|
||||
minimum_version: "18.0"
|
||||
@@ -807,6 +825,11 @@ software:
|
||||
assert.Empty(t, enrolledTeamSecrets)
|
||||
assert.True(t, savedTeam.Config.Features.EnableSoftwareInventory)
|
||||
|
||||
assert.Equal(t, "2025-10-10", savedTeam.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
assert.Equal(t, "18.0", savedTeam.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
// To keep things backwards compatible if MinimumVersion & Deadline are set, then UpdateNewHosts should be set to true
|
||||
assert.Equal(t, optjson.SetBool(true), savedTeam.Config.MDM.MacOSUpdates.UpdateNewHosts)
|
||||
|
||||
// The previous run created the team, so let's rerun with an existing team
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", tmpFile.Name()})
|
||||
assert.Empty(t, enrolledTeamSecrets)
|
||||
@@ -1489,6 +1512,7 @@ software:
|
||||
assert.Empty(t, savedTeam.Config.MDM.WindowsSettings.CustomSettings.Value)
|
||||
assert.Empty(t, savedTeam.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
assert.Empty(t, savedTeam.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
assert.False(t, savedTeam.Config.MDM.MacOSUpdates.UpdateNewHosts.Value)
|
||||
assert.Empty(t, savedTeam.Config.MDM.MacOSSetup.BootstrapPackage.Value)
|
||||
assert.False(t, savedTeam.Config.MDM.EnableDiskEncryption)
|
||||
assert.Equal(t, filepath.Base(tmpFile.Name()), *savedTeam.Filename)
|
||||
|
||||
@@ -218,7 +218,8 @@
|
||||
"enabled_and_configured": true,
|
||||
"macos_updates": {
|
||||
"minimum_version": "15.1",
|
||||
"deadline": "2024-12-31"
|
||||
"deadline": "2024-12-31",
|
||||
"update_new_hosts": true
|
||||
},
|
||||
"ios_updates": {
|
||||
"minimum_version": "18.1",
|
||||
|
||||
@@ -18,7 +18,7 @@ android_settings:
|
||||
macos_updates:
|
||||
minimum_version: "15.1"
|
||||
deadline: "2024-12-31"
|
||||
update_new_hosts:
|
||||
update_new_hosts: true
|
||||
ios_updates:
|
||||
minimum_version: "18.1"
|
||||
deadline: "2025-12-31"
|
||||
|
||||
@@ -107,7 +107,8 @@
|
||||
"enable_disk_encryption": true,
|
||||
"macos_updates": {
|
||||
"minimum_version": "95.1",
|
||||
"deadline": "2020-12-31"
|
||||
"deadline": "2020-12-31",
|
||||
"update_new_hosts": true
|
||||
},
|
||||
"ios_updates": {
|
||||
"minimum_version": "98.1",
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ controls:
|
||||
macos_updates:
|
||||
deadline: "2024-12-31"
|
||||
minimum_version: "15.1"
|
||||
update_new_hosts:
|
||||
update_new_hosts: true
|
||||
scripts:
|
||||
- path: ../lib/no-team/scripts/Script Z.ps1
|
||||
windows_enabled_and_configured: true
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ controls:
|
||||
macos_updates:
|
||||
deadline: "2020-12-31"
|
||||
minimum_version: "95.1"
|
||||
update_new_hosts:
|
||||
update_new_hosts: true
|
||||
scripts:
|
||||
- path: "../lib/team-a-👍/scripts/Script B.ps1"
|
||||
windows_enabled_and_configured: true
|
||||
|
||||
@@ -170,6 +170,7 @@ func (svc *Service) ModifyTeam(ctx context.Context, teamID uint, payload fleet.T
|
||||
|
||||
var (
|
||||
macOSMinVersionUpdated bool
|
||||
updateNewHostsChanged bool
|
||||
iOSMinVersionUpdated bool
|
||||
iPadOSMinVersionUpdated bool
|
||||
windowsUpdatesUpdated bool
|
||||
@@ -182,9 +183,10 @@ func (svc *Service) ModifyTeam(ctx context.Context, teamID uint, payload fleet.T
|
||||
if err := payload.MDM.MacOSUpdates.Validate(); err != nil {
|
||||
return nil, fleet.NewInvalidArgumentError("macos_updates", err.Error())
|
||||
}
|
||||
if payload.MDM.MacOSUpdates.MinimumVersion.Set || payload.MDM.MacOSUpdates.Deadline.Set {
|
||||
if payload.MDM.MacOSUpdates.MinimumVersion.Set || payload.MDM.MacOSUpdates.Deadline.Set || payload.MDM.MacOSUpdates.UpdateNewHosts.Set {
|
||||
macOSMinVersionUpdated = team.Config.MDM.MacOSUpdates.MinimumVersion.Value != payload.MDM.MacOSUpdates.MinimumVersion.Value ||
|
||||
team.Config.MDM.MacOSUpdates.Deadline.Value != payload.MDM.MacOSUpdates.Deadline.Value
|
||||
updateNewHostsChanged = team.Config.MDM.MacOSUpdates.UpdateNewHosts.Value != payload.MDM.MacOSUpdates.UpdateNewHosts.Value
|
||||
team.Config.MDM.MacOSUpdates = *payload.MDM.MacOSUpdates
|
||||
}
|
||||
}
|
||||
@@ -192,6 +194,7 @@ func (svc *Service) ModifyTeam(ctx context.Context, teamID uint, payload fleet.T
|
||||
if err := payload.MDM.IOSUpdates.Validate(); err != nil {
|
||||
return nil, fleet.NewInvalidArgumentError("ios_updates", err.Error())
|
||||
}
|
||||
|
||||
if payload.MDM.IOSUpdates.MinimumVersion.Set || payload.MDM.IOSUpdates.Deadline.Set {
|
||||
iOSMinVersionUpdated = team.Config.MDM.IOSUpdates.MinimumVersion.Value != payload.MDM.IOSUpdates.MinimumVersion.Value ||
|
||||
team.Config.MDM.IOSUpdates.Deadline.Value != payload.MDM.IOSUpdates.Deadline.Value
|
||||
@@ -376,6 +379,28 @@ func (svc *Service) ModifyTeam(ctx context.Context, teamID uint, payload fleet.T
|
||||
}
|
||||
}
|
||||
|
||||
if updateNewHostsChanged {
|
||||
var activity fleet.ActivityDetails
|
||||
activity = fleet.ActivityTypeEnabledMacosUpdateNewHosts{
|
||||
TeamID: &team.ID,
|
||||
TeamName: &team.Name,
|
||||
}
|
||||
if payload.MDM != nil && payload.MDM.MacOSUpdates != nil && !payload.MDM.MacOSUpdates.UpdateNewHosts.Value {
|
||||
activity = fleet.ActivityTypeDisabledMacosUpdateNewHosts{
|
||||
TeamID: &team.ID,
|
||||
TeamName: &team.Name,
|
||||
}
|
||||
}
|
||||
|
||||
if err := svc.NewActivity(
|
||||
ctx,
|
||||
authz.UserFromContext(ctx),
|
||||
activity,
|
||||
); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "create activity for team macOS update new hosts edited")
|
||||
}
|
||||
}
|
||||
|
||||
if windowsUpdatesUpdated {
|
||||
var deadline, grace *int
|
||||
if team.Config.MDM.WindowsUpdates.DeadlineDays.Valid {
|
||||
|
||||
@@ -6711,7 +6711,7 @@ WHERE (
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ds *Datastore) GetMDMAppleOSUpdatesSettingsByHostSerial(ctx context.Context, serial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
func (ds *Datastore) GetMDMAppleOSUpdatesSettingsByHostSerial(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
stmt := `
|
||||
SELECT
|
||||
team_id, platform
|
||||
@@ -6728,7 +6728,7 @@ LIMIT 1`
|
||||
Platform string `db:"platform"`
|
||||
}
|
||||
if err := sqlx.GetContext(ctx, ds.reader(ctx), &dest, stmt, serial); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "getting team id for host")
|
||||
return "", nil, ctxerr.Wrap(ctx, err, "getting team id for host")
|
||||
}
|
||||
|
||||
var settings fleet.AppleOSUpdateSettings
|
||||
@@ -6736,7 +6736,7 @@ LIMIT 1`
|
||||
// use the global settings
|
||||
ac, err := ds.AppConfig(ctx)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "getting app config for os update settings")
|
||||
return "", nil, ctxerr.Wrap(ctx, err, "getting app config for os update settings")
|
||||
}
|
||||
switch dest.Platform {
|
||||
case "ios":
|
||||
@@ -6746,13 +6746,13 @@ LIMIT 1`
|
||||
case "darwin":
|
||||
settings = ac.MDM.MacOSUpdates
|
||||
default:
|
||||
return nil, ctxerr.New(ctx, fmt.Sprintf("unsupported platform %s", dest.Platform))
|
||||
return "", nil, ctxerr.New(ctx, fmt.Sprintf("unsupported platform %s", dest.Platform))
|
||||
}
|
||||
} else {
|
||||
// use the team settings
|
||||
tm, err := ds.TeamLite(ctx, *dest.TeamID)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "getting team os update settings")
|
||||
return "", nil, ctxerr.Wrap(ctx, err, "getting team os update settings")
|
||||
}
|
||||
switch dest.Platform {
|
||||
case "ios":
|
||||
@@ -6762,11 +6762,11 @@ LIMIT 1`
|
||||
case "darwin":
|
||||
settings = tm.Config.MDM.MacOSUpdates
|
||||
default:
|
||||
return nil, ctxerr.New(ctx, fmt.Sprintf("unsupported platform %s", dest.Platform))
|
||||
return "", nil, ctxerr.New(ctx, fmt.Sprintf("unsupported platform %s", dest.Platform))
|
||||
}
|
||||
}
|
||||
|
||||
return &settings, nil
|
||||
return dest.Platform, &settings, nil
|
||||
}
|
||||
|
||||
// ClearMDMUpcomingActivitiesDB clears the upcoming activities of the host that
|
||||
|
||||
@@ -8011,9 +8011,14 @@ func TestGetMDMAppleOSUpdatesSettingsByHostSerial(t *testing.T) {
|
||||
|
||||
checkDevice := func(t *testing.T, teamID uint, key string, wantVersion string) {
|
||||
checkExpectedVersion(t, getConfigSettings(teamID, key), wantVersion)
|
||||
gotSettings, err := ds.GetMDMAppleOSUpdatesSettingsByHostSerial(context.Background(), devicesByKey[key].SerialNumber)
|
||||
platform, gotSettings, err := ds.GetMDMAppleOSUpdatesSettingsByHostSerial(context.Background(), devicesByKey[key].SerialNumber)
|
||||
require.NoError(t, err)
|
||||
checkExpectedVersion(t, gotSettings, wantVersion)
|
||||
if key == "macos" {
|
||||
require.Equal(t, "darwin", platform)
|
||||
} else {
|
||||
require.Equal(t, platform, key)
|
||||
}
|
||||
}
|
||||
|
||||
// empty global settings to start
|
||||
@@ -8110,7 +8115,7 @@ func TestGetMDMAppleOSUpdatesSettingsByHostSerial(t *testing.T) {
|
||||
})
|
||||
|
||||
// non-DEP host should return not found
|
||||
_, err = ds.GetMDMAppleOSUpdatesSettingsByHostSerial(context.Background(), "non-dep-serial")
|
||||
_, _, err = ds.GetMDMAppleOSUpdatesSettingsByHostSerial(context.Background(), "non-dep-serial")
|
||||
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||
|
||||
// deleted DEP host should return not found
|
||||
@@ -8118,7 +8123,7 @@ func TestGetMDMAppleOSUpdatesSettingsByHostSerial(t *testing.T) {
|
||||
_, err := q.ExecContext(context.Background(), "UPDATE host_dep_assignments SET deleted_at = NOW() WHERE host_id = ?", hostIDsByKey["macos"])
|
||||
return err
|
||||
})
|
||||
_, err = ds.GetMDMAppleOSUpdatesSettingsByHostSerial(context.Background(), devicesByKey["macos"].SerialNumber)
|
||||
_, _, err = ds.GetMDMAppleOSUpdatesSettingsByHostSerial(context.Background(), devicesByKey["macos"].SerialNumber)
|
||||
require.ErrorIs(t, err, sql.ErrNoRows)
|
||||
}
|
||||
|
||||
|
||||
@@ -1566,8 +1566,8 @@ type Datastore interface {
|
||||
MDMAppleSetPendingDeclarationsAs(ctx context.Context, hostUUID string, status *MDMDeliveryStatus, detail string) error
|
||||
MDMAppleSetRemoveDeclarationsAsPending(ctx context.Context, hostUUID string, declarationUUIDs []string) error
|
||||
// GetMDMAppleOSUpdatesSettingsByHostSerial returns applicable Apple OS update settings (if any)
|
||||
// for the host with the given serial number. The host must be DEP assigned to Fleet.
|
||||
GetMDMAppleOSUpdatesSettingsByHostSerial(ctx context.Context, hostSerial string) (*AppleOSUpdateSettings, error)
|
||||
// for the host with the given serial number alongside the host's platform. The host must be DEP assigned to Fleet.
|
||||
GetMDMAppleOSUpdatesSettingsByHostSerial(ctx context.Context, hostSerial string) (string, *AppleOSUpdateSettings, error)
|
||||
|
||||
// InsertMDMConfigAssets inserts MDM related config assets, such as SCEP and APNS certs and keys.
|
||||
// tx is optional and can be used to pass an existing transaction.
|
||||
|
||||
@@ -1045,7 +1045,7 @@ type MDMAppleSetPendingDeclarationsAsFunc func(ctx context.Context, hostUUID str
|
||||
|
||||
type MDMAppleSetRemoveDeclarationsAsPendingFunc func(ctx context.Context, hostUUID string, declarationUUIDs []string) error
|
||||
|
||||
type GetMDMAppleOSUpdatesSettingsByHostSerialFunc func(ctx context.Context, hostSerial string) (*fleet.AppleOSUpdateSettings, error)
|
||||
type GetMDMAppleOSUpdatesSettingsByHostSerialFunc func(ctx context.Context, hostSerial string) (string, *fleet.AppleOSUpdateSettings, error)
|
||||
|
||||
type InsertMDMConfigAssetsFunc func(ctx context.Context, assets []fleet.MDMConfigAsset, tx sqlx.ExtContext) error
|
||||
|
||||
@@ -7789,7 +7789,7 @@ func (s *DataStore) MDMAppleSetRemoveDeclarationsAsPending(ctx context.Context,
|
||||
return s.MDMAppleSetRemoveDeclarationsAsPendingFunc(ctx, hostUUID, declarationUUIDs)
|
||||
}
|
||||
|
||||
func (s *DataStore) GetMDMAppleOSUpdatesSettingsByHostSerial(ctx context.Context, hostSerial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
func (s *DataStore) GetMDMAppleOSUpdatesSettingsByHostSerial(ctx context.Context, hostSerial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
s.mu.Lock()
|
||||
s.GetMDMAppleOSUpdatesSettingsByHostSerialFuncInvoked = true
|
||||
s.mu.Unlock()
|
||||
|
||||
@@ -390,6 +390,10 @@ func (svc *Service) ModifyAppConfig(ctx context.Context, p []byte, applyOpts fle
|
||||
return nil, ctxerr.Wrap(ctx, err)
|
||||
}
|
||||
|
||||
// AppleOSUpdateSettings.UpdateNewHosts only applies to macOS ... so just ignore w/e posted for iOS/iPadOS
|
||||
appConfig.MDM.IOSUpdates.UpdateNewHosts = optjson.Bool{}
|
||||
appConfig.MDM.IPadOSUpdates.UpdateNewHosts = optjson.Bool{}
|
||||
|
||||
// if turning off Windows MDM and Windows Migration is not explicitly set to
|
||||
// on in the same update, set it to off (otherwise, if it is explicitly set
|
||||
// to true, return an error that it can't be done when MDM is off, this is
|
||||
@@ -1131,6 +1135,17 @@ func (svc *Service) processAppleOSUpdateSettings(
|
||||
return ctxerr.Wrap(ctx, err, "create activity for app config apple min version modification")
|
||||
}
|
||||
}
|
||||
|
||||
if oldOSUpdateSettings.UpdateNewHosts.Value != newOSUpdateSettings.UpdateNewHosts.Value && appleDevice == fleet.MacOS {
|
||||
var activity fleet.ActivityDetails
|
||||
activity = fleet.ActivityTypeEnabledMacosUpdateNewHosts{}
|
||||
if !newOSUpdateSettings.UpdateNewHosts.Value {
|
||||
activity = fleet.ActivityTypeDisabledMacosUpdateNewHosts{}
|
||||
}
|
||||
if err := svc.NewActivity(ctx, authz.UserFromContext(ctx), activity); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "create activity for app config apple min version modification")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -936,8 +936,8 @@ func TestMDMConfig(t *testing.T) {
|
||||
ManualAgentInstall: optjson.Bool{Set: true},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
VolumePurchasingProgram: optjson.Slice[fleet.MDMAppleVolumePurchasingProgramInfo]{Set: true, Value: []fleet.MDMAppleVolumePurchasingProgramInfo{}},
|
||||
WindowsUpdates: fleet.WindowsUpdates{DeadlineDays: optjson.Int{Set: true}, GracePeriodDays: optjson.Int{Set: true}},
|
||||
WindowsSettings: fleet.WindowsSettings{
|
||||
@@ -986,8 +986,8 @@ func TestMDMConfig(t *testing.T) {
|
||||
ManualAgentInstall: optjson.Bool{Set: true},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
VolumePurchasingProgram: optjson.Slice[fleet.MDMAppleVolumePurchasingProgramInfo]{Set: true, Value: []fleet.MDMAppleVolumePurchasingProgramInfo{}},
|
||||
WindowsUpdates: fleet.WindowsUpdates{DeadlineDays: optjson.Int{Set: true}, GracePeriodDays: optjson.Int{Set: true}},
|
||||
WindowsSettings: fleet.WindowsSettings{
|
||||
@@ -1018,8 +1018,8 @@ func TestMDMConfig(t *testing.T) {
|
||||
ManualAgentInstall: optjson.Bool{Set: true},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
VolumePurchasingProgram: optjson.Slice[fleet.MDMAppleVolumePurchasingProgramInfo]{Set: true, Value: []fleet.MDMAppleVolumePurchasingProgramInfo{}},
|
||||
WindowsUpdates: fleet.WindowsUpdates{DeadlineDays: optjson.Int{Set: true}, GracePeriodDays: optjson.Int{Set: true}},
|
||||
WindowsSettings: fleet.WindowsSettings{
|
||||
@@ -1057,8 +1057,8 @@ func TestMDMConfig(t *testing.T) {
|
||||
ManualAgentInstall: optjson.Bool{Set: true},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
VolumePurchasingProgram: optjson.Slice[fleet.MDMAppleVolumePurchasingProgramInfo]{Set: true, Value: []fleet.MDMAppleVolumePurchasingProgramInfo{}},
|
||||
WindowsUpdates: fleet.WindowsUpdates{DeadlineDays: optjson.Int{Set: true}, GracePeriodDays: optjson.Int{Set: true}},
|
||||
WindowsSettings: fleet.WindowsSettings{
|
||||
@@ -1096,8 +1096,8 @@ func TestMDMConfig(t *testing.T) {
|
||||
ManualAgentInstall: optjson.Bool{Set: true},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
VolumePurchasingProgram: optjson.Slice[fleet.MDMAppleVolumePurchasingProgramInfo]{Set: true, Value: []fleet.MDMAppleVolumePurchasingProgramInfo{}},
|
||||
WindowsUpdates: fleet.WindowsUpdates{DeadlineDays: optjson.Int{Set: true}, GracePeriodDays: optjson.Int{Set: true}},
|
||||
WindowsSettings: fleet.WindowsSettings{
|
||||
@@ -1135,8 +1135,8 @@ func TestMDMConfig(t *testing.T) {
|
||||
ManualAgentInstall: optjson.Bool{Set: true},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
VolumePurchasingProgram: optjson.Slice[fleet.MDMAppleVolumePurchasingProgramInfo]{Set: true, Value: []fleet.MDMAppleVolumePurchasingProgramInfo{}},
|
||||
WindowsUpdates: fleet.WindowsUpdates{DeadlineDays: optjson.Int{Set: true}, GracePeriodDays: optjson.Int{Set: true}},
|
||||
WindowsSettings: fleet.WindowsSettings{
|
||||
@@ -1199,8 +1199,8 @@ func TestMDMConfig(t *testing.T) {
|
||||
ManualAgentInstall: optjson.Bool{Set: true},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}, UpdateNewHosts: optjson.Bool{Set: true}},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{MinimumVersion: optjson.String{Set: true}, Deadline: optjson.String{Set: true}},
|
||||
VolumePurchasingProgram: optjson.Slice[fleet.MDMAppleVolumePurchasingProgramInfo]{Set: true, Value: []fleet.MDMAppleVolumePurchasingProgramInfo{}},
|
||||
WindowsUpdates: fleet.WindowsUpdates{DeadlineDays: optjson.Int{Set: true}, GracePeriodDays: optjson.Int{Set: true}},
|
||||
WindowsSettings: fleet.WindowsSettings{
|
||||
|
||||
@@ -2099,7 +2099,7 @@ func (svc *Service) CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx context.Cont
|
||||
}
|
||||
|
||||
if !needsUpdate {
|
||||
level.Debug(svc.logger).Log("msg", "device is above minimum, skipping os version check", "serial", m.Serial)
|
||||
level.Debug(svc.logger).Log("msg", "device is above minimum or update new host not checked, skipping os version check", "serial", m.Serial)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -2124,23 +2124,57 @@ func (svc *Service) needsOSUpdateForDEPEnrollment(ctx context.Context, m fleet.M
|
||||
// some cross-check against the machine info to ensure that the platform of the host aligns with
|
||||
// what we expect from the machine info. But that would involve work to derive the platform from
|
||||
// the machine info (presumably from the product name, but that's not a 1:1 mapping).
|
||||
settings, err := svc.ds.GetMDMAppleOSUpdatesSettingsByHostSerial(ctx, m.Serial)
|
||||
platform, settings, err := svc.ds.GetMDMAppleOSUpdatesSettingsByHostSerial(ctx, m.Serial)
|
||||
if err != nil {
|
||||
if fleet.IsNotFound(err) {
|
||||
level.Info(svc.logger).Log("msg", "checking os updates settings, settings not found", "serial", m.Serial)
|
||||
level.Info(svc.logger).Log(
|
||||
"msg", "checking os updates settings, settings not found",
|
||||
"serial", m.Serial,
|
||||
)
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
// TODO: confirm what this check should do
|
||||
if !settings.MinimumVersion.Set || !settings.MinimumVersion.Valid || settings.MinimumVersion.Value == "" {
|
||||
level.Info(svc.logger).Log("msg", "checking os updates settings, minimum version not set", "serial", m.Serial, "current_version", m.OSVersion, "minimum_version", settings.MinimumVersion.Value)
|
||||
return false, nil
|
||||
|
||||
minVersion := settings.MinimumVersion.Value
|
||||
hasMinVersion := settings.MinimumVersion.Set && settings.MinimumVersion.Valid && minVersion != ""
|
||||
updateNewHosts := settings.UpdateNewHosts.Set && settings.UpdateNewHosts.Valid && settings.UpdateNewHosts.Value
|
||||
isMacOS := platform == "darwin"
|
||||
|
||||
if isMacOS {
|
||||
// If "Update New Hosts" is unchecked on macOS, we never update.
|
||||
if !updateNewHosts {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// If "Update New Hosts" is checked but no version is set, we force an update
|
||||
if !hasMinVersion {
|
||||
level.Info(svc.logger).Log(
|
||||
"msg", "checking os updates settings, minimum version not set, forcing macos update",
|
||||
"serial", m.Serial,
|
||||
)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
needsUpdate, err := apple_mdm.IsLessThanVersion(m.OSVersion, settings.MinimumVersion.Value)
|
||||
// TODO: confirm what this check should do
|
||||
if !hasMinVersion {
|
||||
level.Info(svc.logger).Log(
|
||||
"msg", "checking os updates settings, minimum version not set",
|
||||
"serial", m.Serial,
|
||||
"current_version", m.OSVersion,
|
||||
"minimum_version", minVersion,
|
||||
)
|
||||
}
|
||||
|
||||
needsUpdate, err := apple_mdm.IsLessThanVersion(m.OSVersion, minVersion)
|
||||
if err != nil {
|
||||
level.Info(svc.logger).Log("msg", "checking os updates settings, cannot compare versions", "serial", m.Serial, "current_version", m.OSVersion, "minimum_version", settings.MinimumVersion.Value)
|
||||
level.Info(svc.logger).Log(
|
||||
"msg", "checking os updates settings, cannot compare versions",
|
||||
"serial", m.Serial,
|
||||
"current_version", m.OSVersion,
|
||||
"minimum_version", minVersion,
|
||||
)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -5061,10 +5061,193 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Run("settings minimum equal to latest", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
return &fleet.AppleOSUpdateSettings{
|
||||
// Non-macOS platforms
|
||||
for _, platform := range []string{"ios", "ipados"} {
|
||||
t.Run(fmt.Sprintf("%s: %s", platform, tt.name), func(t *testing.T) {
|
||||
t.Run("settings minimum equal to latest", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(latestMacOSVersion),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("settings minimum below latest", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.5"),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("settings minimum above latest", func(t *testing.T) {
|
||||
// edge case, but in practice it would get treated as if minimum was equal to latest
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.7"),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("device above settings minimum", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.1"),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
require.Nil(t, sur)
|
||||
})
|
||||
|
||||
t.Run("minimum not set", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", &fleet.AppleOSUpdateSettings{}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(""),
|
||||
}, nil
|
||||
}
|
||||
sur, err = svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
})
|
||||
|
||||
t.Run("minimum not found", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", nil, ¬FoundError{}
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(fmt.Sprintf("%s for macOS", tt.name), func(t *testing.T) {
|
||||
t.Run("when UpdateNewHosts is not set should never update", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "darwin", &fleet.AppleOSUpdateSettings{
|
||||
UpdateNewHosts: optjson.SetBool(false),
|
||||
MinimumVersion: optjson.SetString(latestMacOSVersion),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
})
|
||||
|
||||
t.Run("when UpdateNewHosts is set and minimum is not set", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "darwin", &fleet.AppleOSUpdateSettings{
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
// min version is not important for determining whether an update is required so the logic is based on
|
||||
// the installed version only
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
}
|
||||
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "darwin", &fleet.AppleOSUpdateSettings{
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
MinimumVersion: optjson.SetString(""),
|
||||
}, nil
|
||||
}
|
||||
sur, err = svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Ditto previous comment
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("when apple OS settings not found", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "darwin", nil, ¬FoundError{}
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
})
|
||||
|
||||
t.Run("when UpdateNewHosts is set and required minimum is equal to latest", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "darwin", &fleet.AppleOSUpdateSettings{
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
MinimumVersion: optjson.SetString(latestMacOSVersion),
|
||||
}, nil
|
||||
}
|
||||
@@ -5085,96 +5268,6 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("settings minimum below latest", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
return &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.5"),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("settings minimum above latest", func(t *testing.T) {
|
||||
// edge case, but in practice it would get treated as if minimum was equal to latest
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
return &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.7"),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("device above settings minimum", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
return &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.1"),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
require.Nil(t, sur)
|
||||
})
|
||||
|
||||
t.Run("minimum not set", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
return &fleet.AppleOSUpdateSettings{}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
return &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(""),
|
||||
}, nil
|
||||
}
|
||||
sur, err = svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
})
|
||||
|
||||
t.Run("minimum not found", func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
return nil, ¬FoundError{}
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5183,8 +5276,8 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (*fleet.AppleOSUpdateSettings, error) {
|
||||
return &fleet.AppleOSUpdateSettings{MinimumVersion: optjson.SetString(latestMacOSVersion)}, nil
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", &fleet.AppleOSUpdateSettings{MinimumVersion: optjson.SetString(latestMacOSVersion)}, nil
|
||||
}
|
||||
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
|
||||
@@ -2191,6 +2191,13 @@ func (c *Client) DoGitOps(
|
||||
if deadline, ok := macOSUpdates["deadline"]; !ok || deadline == nil {
|
||||
macOSUpdates["deadline"] = ""
|
||||
}
|
||||
|
||||
// To keep things backward compatible, if a minimum_version and deadline are both set,
|
||||
// then we also set update_new_hosts
|
||||
if macOSUpdates["minimum_version"] != "" && macOSUpdates["deadline"] != "" {
|
||||
macOSUpdates["update_new_hosts"] = true
|
||||
}
|
||||
|
||||
// Put in default values for ios_updates
|
||||
if incoming.Controls.IOSUpdates != nil {
|
||||
mdmAppConfig["ios_updates"] = incoming.Controls.IOSUpdates
|
||||
@@ -2204,6 +2211,9 @@ func (c *Client) DoGitOps(
|
||||
if deadline, ok := iOSUpdates["deadline"]; !ok || deadline == nil {
|
||||
iOSUpdates["deadline"] = ""
|
||||
}
|
||||
// update_new_hosts is only used for macOS so ignore any values posted for iOS
|
||||
iOSUpdates["update_new_hosts"] = nil
|
||||
|
||||
// Put in default values for ipados_updates
|
||||
if incoming.Controls.IPadOSUpdates != nil {
|
||||
mdmAppConfig["ipados_updates"] = incoming.Controls.IPadOSUpdates
|
||||
@@ -2217,6 +2227,9 @@ func (c *Client) DoGitOps(
|
||||
if deadline, ok := iPadOSUpdates["deadline"]; !ok || deadline == nil {
|
||||
iPadOSUpdates["deadline"] = ""
|
||||
}
|
||||
// update_new_hosts is only used for macOS so ignore any values posted for iPadOS
|
||||
iPadOSUpdates["update_new_hosts"] = nil
|
||||
|
||||
// Put in default values for macos_setup
|
||||
if incoming.Controls.MacOSSetup != nil {
|
||||
incoming.Controls.MacOSSetup.SetDefaultsIfNeeded()
|
||||
|
||||
@@ -219,8 +219,9 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
"features": &features,
|
||||
"mdm": map[string]any{
|
||||
"macos_updates": map[string]any{
|
||||
"minimum_version": "10.15.0",
|
||||
"deadline": "2021-01-01",
|
||||
"minimum_version": "10.15.0",
|
||||
"deadline": "2021-01-01",
|
||||
"update_new_hosts": true,
|
||||
},
|
||||
"ios_updates": map[string]any{
|
||||
"minimum_version": "17.5.1",
|
||||
@@ -252,7 +253,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.5.1"),
|
||||
@@ -367,7 +368,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.5.1"),
|
||||
@@ -407,7 +408,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.5.1"),
|
||||
@@ -449,7 +450,7 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.5.1"),
|
||||
@@ -2684,7 +2685,7 @@ func (s *integrationEnterpriseTestSuite) TestWindowsUpdatesTeamConfig() {
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.String{Set: true},
|
||||
Deadline: optjson.String{Set: true},
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
UpdateNewHosts: optjson.Bool{Set: true, Valid: false, Value: false},
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
DeadlineDays: optjson.SetInt(5),
|
||||
@@ -2920,6 +2921,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
macOSUpdates := &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
}
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
@@ -2928,7 +2930,18 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2021-01-01", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
s.lastActivityMatches(fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "minimum_version": "10.15.0", "deadline": "2021-01-01"}`, team.ID, team.Name), 0)
|
||||
require.Equal(t, true, tmResp.Team.Config.MDM.MacOSUpdates.UpdateNewHosts.Value)
|
||||
|
||||
s.lastActivityOfTypeMatches(
|
||||
fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(),
|
||||
fmt.Sprintf(`{"team_id": %d, "team_name": %q, "minimum_version": "10.15.0", "deadline": "2021-01-01"}`, team.ID, team.Name), 0)
|
||||
|
||||
s.lastActivityOfTypeMatches(
|
||||
fleet.ActivityTypeEnabledMacosUpdateNewHosts{}.ActivityName(),
|
||||
fmt.Sprintf(`{"team_id": %d, "team_name": %q}`,
|
||||
team.ID,
|
||||
team.Name,
|
||||
), 0)
|
||||
|
||||
s.assertAppleOSUpdatesDeclaration(&team.ID, mdm.FleetMacOSUpdatesProfileName, macOSUpdates)
|
||||
s.assertAppleOSUpdatesDeclaration(&team.ID, mdm.FleetIOSUpdatesProfileName, nil)
|
||||
@@ -2938,11 +2951,14 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
iOSUpdates := &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("11.11.11"),
|
||||
Deadline: optjson.SetString("2022-02-02"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
}
|
||||
iPadOSUpdates := &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.12.12"),
|
||||
Deadline: optjson.SetString("2023-03-03"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
}
|
||||
fmt.Printf("%+v\n", iOSUpdates)
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"ios_updates": iOSUpdates,
|
||||
@@ -2951,10 +2967,18 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2021-01-01", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.SetBool(true), tmResp.Team.Config.MDM.MacOSUpdates.UpdateNewHosts)
|
||||
|
||||
require.Equal(t, "11.11.11", tmResp.Team.Config.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2022-02-02", tmResp.Team.Config.MDM.IOSUpdates.Deadline.Value)
|
||||
// UpdateNewHosts values are ignored for iOS
|
||||
require.Equal(t, optjson.Bool{Set: true}, tmResp.Team.Config.MDM.IOSUpdates.UpdateNewHosts)
|
||||
|
||||
require.Equal(t, "12.12.12", tmResp.Team.Config.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2023-03-03", tmResp.Team.Config.MDM.IPadOSUpdates.Deadline.Value)
|
||||
// UpdateNewHosts values are ignored for iPadOS
|
||||
require.Equal(t, optjson.Bool{Set: true}, tmResp.Team.Config.MDM.IPadOSUpdates.UpdateNewHosts)
|
||||
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "minimum_version": "10.15.0", "deadline": "2021-01-01"}`, team.ID, team.Name), 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "minimum_version": "11.11.11", "deadline": "2022-02-02"}`, team.ID, team.Name), 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "minimum_version": "12.12.12", "deadline": "2023-03-03"}`, team.ID, team.Name), 0)
|
||||
@@ -2967,6 +2991,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
macOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
Deadline: optjson.SetString("2025-10-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
}
|
||||
iOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("11.11.11"),
|
||||
@@ -2985,10 +3010,16 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2025-10-01", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.SetBool(true), tmResp.Team.Config.MDM.MacOSUpdates.UpdateNewHosts)
|
||||
|
||||
require.Equal(t, "11.11.11", tmResp.Team.Config.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-02-02", tmResp.Team.Config.MDM.IOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.Bool{Set: true}, tmResp.Team.Config.MDM.IOSUpdates.UpdateNewHosts)
|
||||
|
||||
require.Equal(t, "12.12.12", tmResp.Team.Config.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-03-03", tmResp.Team.Config.MDM.IPadOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.Bool{Set: true}, tmResp.Team.Config.MDM.IPadOSUpdates.UpdateNewHosts)
|
||||
|
||||
macOSLastActivity := s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "minimum_version": "10.15.0", "deadline": "2025-10-01"}`, team.ID, team.Name), 0)
|
||||
iOSLastActivity := s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "minimum_version": "11.11.11", "deadline": "2024-02-02"}`, team.ID, team.Name), 0)
|
||||
iPadOSLastActivity := s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "minimum_version": "12.12.12", "deadline": "2024-03-03"}`, team.ID, team.Name), 0)
|
||||
@@ -2997,6 +3028,35 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
s.assertAppleOSUpdatesDeclaration(&team.ID, mdm.FleetIOSUpdatesProfileName, iOSUpdates)
|
||||
s.assertAppleOSUpdatesDeclaration(&team.ID, mdm.FleetIPadOSUpdatesProfileName, iPadOSUpdates)
|
||||
|
||||
// Unchecking the UpdateNewHosts flag should register as an activity
|
||||
macOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
Deadline: optjson.SetString("2025-10-01"),
|
||||
UpdateNewHosts: optjson.SetBool(false),
|
||||
}
|
||||
iOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("11.11.11"),
|
||||
Deadline: optjson.SetString("2024-02-02"),
|
||||
}
|
||||
iPadOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.12.12"),
|
||||
Deadline: optjson.SetString("2024-03-03"),
|
||||
}
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"macos_updates": macOSUpdates,
|
||||
"ios_updates": iOSUpdates,
|
||||
"ipados_updates": iPadOSUpdates,
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, false, tmResp.Team.Config.MDM.MacOSUpdates.UpdateNewHosts.Value)
|
||||
s.lastActivityOfTypeMatches(
|
||||
fleet.ActivityTypeDisabledMacosUpdateNewHosts{}.ActivityName(),
|
||||
fmt.Sprintf(`{"team_id": %d, "team_name": %q}`,
|
||||
team.ID,
|
||||
team.Name,
|
||||
), 0)
|
||||
|
||||
// setting the windows updates doesn't alter the apple updates
|
||||
tmResp = teamResponse{}
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
@@ -3907,29 +3967,41 @@ func (s *integrationEnterpriseTestSuite) TestMDMAppleOSUpdates() {
|
||||
"mdm": {
|
||||
"macos_updates": {
|
||||
"minimum_version": "12.3.1",
|
||||
"deadline": "2022-01-01"
|
||||
"deadline": "2022-01-01",
|
||||
"update_new_hosts": true
|
||||
},
|
||||
"ios_updates": {
|
||||
"minimum_version": "13.13.13",
|
||||
"deadline": "2023-03-03"
|
||||
"deadline": "2023-03-03",
|
||||
"update_new_hosts": true
|
||||
},
|
||||
"ipados_updates": {
|
||||
"minimum_version": "14.14.14",
|
||||
"deadline": "2024-04-04"
|
||||
"deadline": "2024-04-04",
|
||||
"update_new_hosts": true
|
||||
}
|
||||
}
|
||||
}`), http.StatusOK, &acResp)
|
||||
require.Equal(t, "12.3.1", acResp.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2022-01-01", acResp.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.SetBool(true), acResp.MDM.MacOSUpdates.UpdateNewHosts)
|
||||
|
||||
require.Equal(t, "13.13.13", acResp.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2023-03-03", acResp.MDM.IOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.Bool{Set: true}, acResp.MDM.IOSUpdates.UpdateNewHosts) // posted value is ignored for iOS
|
||||
|
||||
require.Equal(t, "14.14.14", acResp.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-04-04", acResp.MDM.IPadOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.Bool{Set: true}, acResp.MDM.IPadOSUpdates.UpdateNewHosts) // posted value is ignored for iOS
|
||||
|
||||
// edited macos min version activity got created
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(), `{"deadline":"2022-01-01", "minimum_version":"12.3.1", "team_id": null, "team_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), `{"deadline":"2023-03-03", "minimum_version":"13.13.13", "team_id": null, "team_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), `{"deadline":"2024-04-04", "minimum_version":"14.14.14", "team_id": null, "team_name": null}`, 0)
|
||||
|
||||
// Activity for 'Update New Hosts checked' got created
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEnabledMacosUpdateNewHosts{}.ActivityName(), "", 0)
|
||||
|
||||
s.assertAppleOSUpdatesDeclaration(nil, mdm.FleetMacOSUpdatesProfileName, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.3.1"), Deadline: optjson.SetString("2022-01-01"),
|
||||
})
|
||||
@@ -3945,18 +4017,24 @@ func (s *integrationEnterpriseTestSuite) TestMDMAppleOSUpdates() {
|
||||
s.DoJSON("GET", "/api/latest/fleet/config", nil, http.StatusOK, &acResp)
|
||||
require.Equal(t, "12.3.1", acResp.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2022-01-01", acResp.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.SetBool(true), acResp.MDM.MacOSUpdates.UpdateNewHosts)
|
||||
|
||||
require.Equal(t, "13.13.13", acResp.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2023-03-03", acResp.MDM.IOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.Bool{Set: true}, acResp.MDM.IOSUpdates.UpdateNewHosts)
|
||||
|
||||
require.Equal(t, "14.14.14", acResp.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-04-04", acResp.MDM.IPadOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.Bool{Set: true}, acResp.MDM.IOSUpdates.UpdateNewHosts)
|
||||
|
||||
// update the deadline
|
||||
// update the deadline and the update_new_hosts flag
|
||||
acResp = appConfigResponse{}
|
||||
s.DoJSON("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
|
||||
"mdm": {
|
||||
"macos_updates": {
|
||||
"minimum_version": "12.3.1",
|
||||
"deadline": "2024-01-01"
|
||||
"deadline": "2024-01-01",
|
||||
"update_new_hosts": false
|
||||
},
|
||||
"ios_updates": {
|
||||
"minimum_version": "13.13.13",
|
||||
@@ -3970,12 +4048,18 @@ func (s *integrationEnterpriseTestSuite) TestMDMAppleOSUpdates() {
|
||||
}`), http.StatusOK, &acResp)
|
||||
require.Equal(t, "12.3.1", acResp.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-01-01", acResp.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.SetBool(false), acResp.MDM.MacOSUpdates.UpdateNewHosts)
|
||||
|
||||
require.Equal(t, "13.13.13", acResp.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2025-05-05", acResp.MDM.IOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.Bool{Set: true}, acResp.MDM.IOSUpdates.UpdateNewHosts)
|
||||
|
||||
require.Equal(t, "14.14.14", acResp.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2026-06-06", acResp.MDM.IPadOSUpdates.Deadline.Value)
|
||||
require.Equal(t, optjson.Bool{Set: true}, acResp.MDM.IPadOSUpdates.UpdateNewHosts)
|
||||
|
||||
// another edited macos min version activity got created
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeDisabledMacosUpdateNewHosts{}.ActivityName(), "", 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(), `{"deadline":"2024-01-01", "minimum_version":"12.3.1", "team_id": null, "team_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), `{"deadline":"2025-05-05", "minimum_version":"13.13.13", "team_id": null, "team_name": null}`, 0)
|
||||
lastActivity = s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), `{"deadline":"2026-06-06", "minimum_version":"14.14.14", "team_id": null, "team_name": null}`, 0)
|
||||
|
||||
@@ -2458,7 +2458,7 @@ func (s *integrationMDMTestSuite) TestEnforceMiniumOSVersion() {
|
||||
|
||||
// this helper function sets the minimum OS version for the team or no team
|
||||
setMinOSVersion := func(minVersion string, deadline string, teamID *uint) {
|
||||
raw := json.RawMessage(fmt.Sprintf(`{ "mdm": { "macos_updates": { "minimum_version": "%s", "deadline": "%s" } } }`, minVersion, deadline))
|
||||
raw := json.RawMessage(fmt.Sprintf(`{ "mdm": { "macos_updates": { "minimum_version": "%s", "deadline": "%s", "update_new_hosts": true } } }`, minVersion, deadline))
|
||||
if teamID == nil {
|
||||
acResp := appConfigResponse{}
|
||||
s.DoJSON("PATCH", "/api/latest/fleet/config", raw, http.StatusOK, &acResp)
|
||||
|
||||
@@ -5343,6 +5343,7 @@ func (s *integrationMDMTestSuite) TestMDMBatchSetProfilesKeepsReservedNames() {
|
||||
MacOSUpdates: &fleet.AppleOSUpdateSettings{
|
||||
Deadline: optjson.SetString("2023-12-31"),
|
||||
MinimumVersion: optjson.SetString("13.3.8"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -5354,6 +5355,7 @@ func (s *integrationMDMTestSuite) TestMDMBatchSetProfilesKeepsReservedNames() {
|
||||
require.Equal(t, 1, tmResp.Team.Config.MDM.WindowsUpdates.GracePeriodDays.Value)
|
||||
require.Equal(t, "2023-12-31", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, "13.3.8", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, true, tmResp.Team.Config.MDM.MacOSUpdates.UpdateNewHosts.Value)
|
||||
|
||||
require.NoError(t, ReconcileAppleProfiles(ctx, s.ds, s.mdmCommander, s.logger))
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/optjson"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
@@ -155,6 +156,17 @@ type modifyTeamRequest struct {
|
||||
|
||||
func modifyTeamEndpoint(ctx context.Context, request interface{}, svc fleet.Service) (fleet.Errorer, error) {
|
||||
req := request.(*modifyTeamRequest)
|
||||
|
||||
// AppleOSUpdateSettings.UpdateNewHosts is only used in macOS ... so ignore any values sent for iOS/iPadOS
|
||||
if req.TeamPayload.MDM != nil {
|
||||
if req.TeamPayload.MDM.IOSUpdates != nil {
|
||||
req.TeamPayload.MDM.IOSUpdates.UpdateNewHosts = optjson.Bool{}
|
||||
}
|
||||
if req.TeamPayload.MDM.IPadOSUpdates != nil {
|
||||
req.TeamPayload.MDM.IPadOSUpdates.UpdateNewHosts = optjson.Bool{}
|
||||
}
|
||||
}
|
||||
|
||||
team, err := svc.ModifyTeam(ctx, req.ID, req.TeamPayload)
|
||||
if err != nil {
|
||||
return teamResponse{Err: err}, nil
|
||||
|
||||
Reference in New Issue
Block a user