Update DEP enrollment flow to apply minimum macOS version check when specified (#40720)
This commit is contained in:
@@ -0,0 +1 @@
|
||||
- Updated DEP enrollment flow to apply minimum macOS version check when specified.
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
nanodep_client "github.com/fleetdm/fleet/v4/server/mdm/nanodep/client"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanodep/tokenpki"
|
||||
mdmtest "github.com/fleetdm/fleet/v4/server/mdm/testing_utils"
|
||||
"github.com/fleetdm/fleet/v4/server/mock"
|
||||
mdmmock "github.com/fleetdm/fleet/v4/server/mock/mdm"
|
||||
nanodep_mock "github.com/fleetdm/fleet/v4/server/mock/nanodep"
|
||||
@@ -206,6 +207,9 @@ func TestApplyTeamSpecs(t *testing.T) {
|
||||
license := &fleet.LicenseInfo{Tier: fleet.TierPremium, Expiration: time.Now().Add(24 * time.Hour)}
|
||||
_, ds := testing_utils.RunServerWithMockedDS(t, &service.TestServerOpts{License: license})
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
teamsByName := map[string]*fleet.Team{
|
||||
"team1": {
|
||||
ID: 42,
|
||||
@@ -321,7 +325,7 @@ spec:
|
||||
- secret: AAA
|
||||
mdm:
|
||||
macos_updates:
|
||||
minimum_version: 12.3.1
|
||||
minimum_version: 14.6.1
|
||||
deadline: 2011-03-01
|
||||
update_new_hosts: true
|
||||
`)
|
||||
@@ -329,7 +333,7 @@ spec:
|
||||
newAgentOpts := json.RawMessage(`{"config":{"views":{"foo":"bar"}}}`)
|
||||
newMDMSettings := fleet.TeamMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.3.1"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2011-03-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
@@ -368,7 +372,7 @@ spec:
|
||||
require.Equal(t, "[+] applied 1 fleet\n", RunAppForTest(t, []string{"apply", "-f", filename}))
|
||||
newMDMSettings = fleet.TeamMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.3.1"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2011-03-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
@@ -398,7 +402,7 @@ spec:
|
||||
|
||||
newMDMSettings = fleet.TeamMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.3.1"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2011-03-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
@@ -436,13 +440,13 @@ spec:
|
||||
name: team1
|
||||
mdm:
|
||||
macos_updates:
|
||||
minimum_version: 10.10.10
|
||||
minimum_version: 14.6.1
|
||||
deadline: 1992-03-01
|
||||
ios_updates:
|
||||
minimum_version: 11.11.11
|
||||
minimum_version: 17.6.1
|
||||
deadline: 1993-04-02
|
||||
ipados_updates:
|
||||
minimum_version: 12.12.12
|
||||
minimum_version: 17.6.1
|
||||
deadline: 1994-05-03
|
||||
secrets:
|
||||
- secret: BBB
|
||||
@@ -450,15 +454,15 @@ spec:
|
||||
|
||||
newMDMSettings = fleet.TeamMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.10.10"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("1992-03-01"),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("11.11.11"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("1993-04-02"),
|
||||
},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.12.12"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("1994-05-03"),
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
@@ -690,6 +694,9 @@ func TestApplyAppConfig(t *testing.T) {
|
||||
license := &fleet.LicenseInfo{Tier: fleet.TierPremium, Expiration: time.Now().Add(24 * time.Hour)}
|
||||
_, ds := testing_utils.RunServerWithMockedDS(t, &service.TestServerOpts{License: license})
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
ds.ListUsersFunc = func(ctx context.Context, opt fleet.UserListOptions) ([]*fleet.User, error) {
|
||||
return userRoleSpecList, nil
|
||||
}
|
||||
@@ -776,7 +783,7 @@ spec:
|
||||
mdm:
|
||||
apple_bm_default_team: "team1"
|
||||
macos_updates:
|
||||
minimum_version: 12.1.1
|
||||
minimum_version: 14.6.1
|
||||
deadline: 2011-02-01
|
||||
windows_updates:
|
||||
deadline_days: 5
|
||||
@@ -787,7 +794,7 @@ spec:
|
||||
DeprecatedAppleBMDefaultTeam: "team1",
|
||||
AppleBMTermsExpired: false,
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.1.1"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2011-02-01"),
|
||||
},
|
||||
MacOSSetup: fleet.MacOSSetup{
|
||||
@@ -870,7 +877,7 @@ spec:
|
||||
DeprecatedAppleBMDefaultTeam: "team1",
|
||||
AppleBMTermsExpired: false,
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.1.1"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2011-02-01"),
|
||||
},
|
||||
MacOSSetup: fleet.MacOSSetup{
|
||||
@@ -1343,6 +1350,9 @@ func TestApplyAsGitOps(t *testing.T) {
|
||||
// Mock Apple DEP API
|
||||
depStorage := SetupMockDEPStorageAndMockDEPServer(t)
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
config.SetTestMDMConfig(t, &fleetCfg, testCertPEM, testKeyPEM, "../../../server/service/testdata")
|
||||
|
||||
_, ds := testing_utils.RunServerWithMockedDS(t, &service.TestServerOpts{
|
||||
@@ -1541,7 +1551,7 @@ kind: config
|
||||
spec:
|
||||
mdm:
|
||||
macos_updates:
|
||||
minimum_version: 10.10.10
|
||||
minimum_version: 14.6.1
|
||||
deadline: 2020-02-02
|
||||
windows_updates:
|
||||
deadline_days: 1
|
||||
@@ -1570,7 +1580,7 @@ spec:
|
||||
LockEndUserInfo: optjson.SetBool(false),
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.10.10"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2020-02-02"),
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
@@ -1614,7 +1624,7 @@ spec:
|
||||
LockEndUserInfo: optjson.SetBool(false),
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.10.10"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2020-02-02"),
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
@@ -1641,7 +1651,7 @@ spec:
|
||||
mdm:
|
||||
enable_disk_encryption: false
|
||||
macos_updates:
|
||||
minimum_version: 10.10.10
|
||||
minimum_version: 14.6.1
|
||||
deadline: 1992-03-01
|
||||
windows_updates:
|
||||
deadline_days: 0
|
||||
@@ -1665,7 +1675,7 @@ spec:
|
||||
CustomSettings: []fleet.MDMProfileSpec{{Path: mobileConfigPath}},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.10.10"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("1992-03-01"),
|
||||
},
|
||||
MacOSSetup: fleet.MacOSSetup{
|
||||
@@ -1708,7 +1718,7 @@ spec:
|
||||
CustomSettings: []fleet.MDMProfileSpec{{Path: mobileConfigPath}},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.10.10"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("1992-03-01"),
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
@@ -1746,7 +1756,7 @@ spec:
|
||||
CustomSettings: []fleet.MDMProfileSpec{{Path: mobileConfigPath}},
|
||||
},
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.10.10"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("1992-03-01"),
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
@@ -3457,7 +3467,7 @@ spec:
|
||||
minimum_version: "12.2"
|
||||
deadline: "1892-01-01T00:00:00Z"
|
||||
`,
|
||||
wantErr: `422 Validation Failed: deadline accepts YYYY-MM-DD format only (E.g., "2023-06-01.")`,
|
||||
wantErr: fmt.Sprintf(`422 Validation Failed: %s`, fleet.AppleOSVersionDeadlineInvalidMessage),
|
||||
},
|
||||
{
|
||||
desc: "macos_updates.deadline with invalid date",
|
||||
@@ -3472,7 +3482,7 @@ spec:
|
||||
minimum_version: "12.2"
|
||||
deadline: "18-01-01"
|
||||
`,
|
||||
wantErr: `422 Validation Failed: deadline accepts YYYY-MM-DD format only (E.g., "2023-06-01.")`,
|
||||
wantErr: fmt.Sprintf(`422 Validation Failed: %s`, fleet.AppleOSVersionDeadlineInvalidMessage),
|
||||
},
|
||||
{
|
||||
desc: "macos_updates.deadline with incomplete date",
|
||||
@@ -3487,7 +3497,7 @@ spec:
|
||||
minimum_version: "12.2"
|
||||
deadline: "2022-01"
|
||||
`,
|
||||
wantErr: `422 Validation Failed: deadline accepts YYYY-MM-DD format only (E.g., "2023-06-01.")`,
|
||||
wantErr: fmt.Sprintf(`422 Validation Failed: %s`, fleet.AppleOSVersionDeadlineInvalidMessage),
|
||||
},
|
||||
{
|
||||
desc: "windows_updates.deadline_days but grace period empty",
|
||||
@@ -3782,7 +3792,7 @@ spec:
|
||||
minimum_version: "12.2"
|
||||
deadline: "1892-01-01T00:00:00Z"
|
||||
`,
|
||||
wantErr: `422 Validation Failed: deadline accepts YYYY-MM-DD format only (E.g., "2023-06-01.")`,
|
||||
wantErr: fmt.Sprintf(`422 Validation Failed: %s`, fleet.AppleOSVersionDeadlineInvalidMessage),
|
||||
},
|
||||
{
|
||||
desc: "app config macos_updates.deadline with invalid date",
|
||||
@@ -3795,7 +3805,7 @@ spec:
|
||||
minimum_version: "12.2"
|
||||
deadline: "18-01-01"
|
||||
`,
|
||||
wantErr: `422 Validation Failed: deadline accepts YYYY-MM-DD format only (E.g., "2023-06-01.")`,
|
||||
wantErr: fmt.Sprintf(`422 Validation Failed: %s`, fleet.AppleOSVersionDeadlineInvalidMessage),
|
||||
},
|
||||
{
|
||||
desc: "app config macos_updates.deadline with incomplete date",
|
||||
@@ -3808,7 +3818,7 @@ spec:
|
||||
minimum_version: "12.2"
|
||||
deadline: "2022-01"
|
||||
`,
|
||||
wantErr: `422 Validation Failed: deadline accepts YYYY-MM-DD format only (E.g., "2023-06-01.")`,
|
||||
wantErr: fmt.Sprintf(`422 Validation Failed: %s`, fleet.AppleOSVersionDeadlineInvalidMessage),
|
||||
},
|
||||
{
|
||||
desc: "app config windows_updates.deadline_days but grace period empty",
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/mdm"
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanodep/tokenpki"
|
||||
mdmtest "github.com/fleetdm/fleet/v4/server/mdm/testing_utils"
|
||||
mdmtesting "github.com/fleetdm/fleet/v4/server/mdm/testing_utils"
|
||||
"github.com/fleetdm/fleet/v4/server/mock"
|
||||
digicert_mock "github.com/fleetdm/fleet/v4/server/mock/digicert"
|
||||
@@ -335,6 +336,9 @@ func TestGitOpsBasicGlobalPremium(t *testing.T) {
|
||||
},
|
||||
)
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
ds.BatchSetMDMProfilesFunc = func(
|
||||
ctx context.Context, tmID *uint, macProfiles []*fleet.MDMAppleConfigProfile, winProfiles []*fleet.MDMWindowsConfigProfile,
|
||||
macDecls []*fleet.MDMAppleDeclaration, androidProfiles []*fleet.MDMAndroidConfigProfile, vars []fleet.MDMProfileIdentifierFleetVariables,
|
||||
@@ -486,14 +490,14 @@ func TestGitOpsBasicGlobalPremium(t *testing.T) {
|
||||
controls:
|
||||
macos_updates:
|
||||
deadline: "2024-03-03"
|
||||
minimum_version: "18.0"
|
||||
minimum_version: "14.6.1"
|
||||
ios_updates:
|
||||
deadline: "2022-02-02"
|
||||
minimum_version: "17.6"
|
||||
update_new_hosts: true
|
||||
ipados_updates:
|
||||
deadline: "2023-03-03"
|
||||
minimum_version: "18.0"
|
||||
minimum_version: "17.6"
|
||||
update_new_hosts: false
|
||||
enable_disk_encryption: true
|
||||
windows_require_bitlocker_pin: true
|
||||
@@ -565,7 +569,7 @@ 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, "14.6.1", 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)
|
||||
@@ -573,7 +577,7 @@ software:
|
||||
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, "17.6", savedAppConfig.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, optjson.Bool{}, savedAppConfig.MDM.IPadOSUpdates.UpdateNewHosts)
|
||||
|
||||
// Check certificate authorities
|
||||
@@ -673,6 +677,9 @@ func TestGitOpsBasicTeam(t *testing.T) {
|
||||
},
|
||||
)
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
const secret = "TestSecret"
|
||||
|
||||
ds.SetTeamVPPAppsFunc = func(ctx context.Context, teamID *uint, adamIDs []fleet.VPPAppTeam, _ map[string]uint) (bool, error) {
|
||||
@@ -842,11 +849,11 @@ func TestGitOpsBasicTeam(t *testing.T) {
|
||||
controls:
|
||||
macos_updates:
|
||||
deadline: "2025-10-10"
|
||||
minimum_version: "18.0"
|
||||
minimum_version: "14.6.1"
|
||||
update_new_hosts: false
|
||||
ios_updates:
|
||||
deadline: "2024-10-10"
|
||||
minimum_version: "18.0"
|
||||
minimum_version: "17.6"
|
||||
ipados_updates:
|
||||
deadline: "2025-11-11"
|
||||
minimum_version: "17.6"
|
||||
@@ -911,7 +918,7 @@ software:
|
||||
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)
|
||||
assert.Equal(t, "14.6.1", savedTeam.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
|
||||
// Ensure the default value (if deadline and minimum_version are set) can be overriden with explicit setting
|
||||
assert.Equal(t, optjson.SetBool(false), savedTeam.Config.MDM.MacOSUpdates.UpdateNewHosts)
|
||||
@@ -2093,6 +2100,10 @@ func TestGitOpsBasicGlobalAndNoTeam(t *testing.T) {
|
||||
KeyValueStore: testing_utils.NewMemKeyValueStore(),
|
||||
},
|
||||
)
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
// Mock appConfig
|
||||
savedAppConfig := &fleet.AppConfig{}
|
||||
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
|
||||
@@ -2347,7 +2358,7 @@ software:
|
||||
controls:
|
||||
ipados_updates:
|
||||
deadline: "2023-03-03"
|
||||
minimum_version: "18.0"
|
||||
minimum_version: "17.6.1"
|
||||
policies:
|
||||
name: No team
|
||||
software:
|
||||
@@ -5707,6 +5718,9 @@ func TestGitOpsAppleOSUpdates(t *testing.T) {
|
||||
},
|
||||
)
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
const localTeamName = "Team1"
|
||||
var savedTeam *fleet.Team
|
||||
baseTeam := &fleet.Team{
|
||||
@@ -5924,11 +5938,11 @@ software:
|
||||
t.Run("macos_updates", func(t *testing.T) {
|
||||
t.Run("same values do not trigger BulkSetPendingMDMHostProfiles", func(t *testing.T) {
|
||||
bulkSetPendingCalls = 0
|
||||
savedTeam = existingTeamWithMacOSUpdates("2024-03-03", "14.0")
|
||||
savedTeam = existingTeamWithMacOSUpdates("2024-03-03", "14.6.1")
|
||||
|
||||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = teamFile.WriteString(macOSYAML("2024-03-03", "14.0"))
|
||||
_, err = teamFile.WriteString(macOSYAML("2024-03-03", "14.6.1"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", teamFile.Name()})
|
||||
@@ -5938,11 +5952,11 @@ software:
|
||||
|
||||
t.Run("changed deadline triggers BulkSetPendingMDMHostProfiles", func(t *testing.T) {
|
||||
bulkSetPendingCalls = 0
|
||||
savedTeam = existingTeamWithMacOSUpdates("2024-03-03", "14.0")
|
||||
savedTeam = existingTeamWithMacOSUpdates("2024-03-03", "14.6.1")
|
||||
|
||||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = teamFile.WriteString(macOSYAML("2024-04-04", "14.0"))
|
||||
_, err = teamFile.WriteString(macOSYAML("2024-04-04", "14.6.1"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", teamFile.Name()})
|
||||
@@ -5952,11 +5966,11 @@ software:
|
||||
|
||||
t.Run("changed minimum_version triggers BulkSetPendingMDMHostProfiles", func(t *testing.T) {
|
||||
bulkSetPendingCalls = 0
|
||||
savedTeam = existingTeamWithMacOSUpdates("2024-03-03", "14.0")
|
||||
savedTeam = existingTeamWithMacOSUpdates("2024-03-03", "14.6.1")
|
||||
|
||||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = teamFile.WriteString(macOSYAML("2024-03-03", "15.0"))
|
||||
_, err = teamFile.WriteString(macOSYAML("2024-03-03", "13.6.9"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", teamFile.Name()})
|
||||
@@ -5968,11 +5982,11 @@ software:
|
||||
t.Run("ios_updates", func(t *testing.T) {
|
||||
t.Run("same values do not trigger BulkSetPendingMDMHostProfiles", func(t *testing.T) {
|
||||
bulkSetPendingCalls = 0
|
||||
savedTeam = existingTeamWithIOSUpdates("2024-03-03", "17.0")
|
||||
savedTeam = existingTeamWithIOSUpdates("2024-03-03", "17.6.1")
|
||||
|
||||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = teamFile.WriteString(iOSYAML("2024-03-03", "17.0"))
|
||||
_, err = teamFile.WriteString(iOSYAML("2024-03-03", "17.6.1"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", teamFile.Name()})
|
||||
@@ -5982,11 +5996,11 @@ software:
|
||||
|
||||
t.Run("changed deadline triggers BulkSetPendingMDMHostProfiles", func(t *testing.T) {
|
||||
bulkSetPendingCalls = 0
|
||||
savedTeam = existingTeamWithIOSUpdates("2024-03-03", "17.0")
|
||||
savedTeam = existingTeamWithIOSUpdates("2024-03-03", "17.6.1")
|
||||
|
||||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = teamFile.WriteString(iOSYAML("2024-04-04", "17.0"))
|
||||
_, err = teamFile.WriteString(iOSYAML("2024-04-04", "17.6.1"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", teamFile.Name()})
|
||||
@@ -5996,11 +6010,11 @@ software:
|
||||
|
||||
t.Run("changed minimum_version triggers BulkSetPendingMDMHostProfiles", func(t *testing.T) {
|
||||
bulkSetPendingCalls = 0
|
||||
savedTeam = existingTeamWithIOSUpdates("2024-03-03", "17.0")
|
||||
savedTeam = existingTeamWithIOSUpdates("2024-03-03", "17.6.1")
|
||||
|
||||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = teamFile.WriteString(iOSYAML("2024-03-03", "18.0"))
|
||||
_, err = teamFile.WriteString(iOSYAML("2024-03-03", "17.6"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", teamFile.Name()})
|
||||
@@ -6012,11 +6026,11 @@ software:
|
||||
t.Run("ipados_updates", func(t *testing.T) {
|
||||
t.Run("same values do not trigger BulkSetPendingMDMHostProfiles", func(t *testing.T) {
|
||||
bulkSetPendingCalls = 0
|
||||
savedTeam = existingTeamWithIPadOSUpdates("2024-03-03", "17.0")
|
||||
savedTeam = existingTeamWithIPadOSUpdates("2024-03-03", "17.6.1")
|
||||
|
||||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = teamFile.WriteString(iPadOSYAML("2024-03-03", "17.0"))
|
||||
_, err = teamFile.WriteString(iPadOSYAML("2024-03-03", "17.6.1"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", teamFile.Name()})
|
||||
@@ -6026,11 +6040,11 @@ software:
|
||||
|
||||
t.Run("changed deadline triggers BulkSetPendingMDMHostProfiles", func(t *testing.T) {
|
||||
bulkSetPendingCalls = 0
|
||||
savedTeam = existingTeamWithIPadOSUpdates("2024-03-03", "17.0")
|
||||
savedTeam = existingTeamWithIPadOSUpdates("2024-03-03", "17.6.1")
|
||||
|
||||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = teamFile.WriteString(iPadOSYAML("2024-04-04", "17.0"))
|
||||
_, err = teamFile.WriteString(iPadOSYAML("2024-04-04", "17.6.1"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", teamFile.Name()})
|
||||
@@ -6040,11 +6054,11 @@ software:
|
||||
|
||||
t.Run("changed minimum_version triggers BulkSetPendingMDMHostProfiles", func(t *testing.T) {
|
||||
bulkSetPendingCalls = 0
|
||||
savedTeam = existingTeamWithIPadOSUpdates("2024-03-03", "17.0")
|
||||
savedTeam = existingTeamWithIPadOSUpdates("2024-03-03", "17.6.1")
|
||||
|
||||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml")
|
||||
require.NoError(t, err)
|
||||
_, err = teamFile.WriteString(iPadOSYAML("2024-03-03", "18.0"))
|
||||
_, err = teamFile.WriteString(iPadOSYAML("2024-03-03", "17.6"))
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = RunAppForTest(t, []string{"gitops", "-f", teamFile.Name()})
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/logging"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
"github.com/fleetdm/fleet/v4/server/ptr"
|
||||
"github.com/fleetdm/fleet/v4/server/worker"
|
||||
)
|
||||
@@ -212,6 +213,19 @@ func (svc *Service) ModifyTeam(ctx context.Context, teamID uint, payload fleet.T
|
||||
}
|
||||
}
|
||||
|
||||
// Always check whether specified versions are supported by Apple (even if they weren't updated)
|
||||
// Note that we're validating against the full, non-public asset set of OS versions here because
|
||||
// in our DEP flow the minimum version just acts as the threshold for whether or not to update
|
||||
// the host to the latest, public version. We don't need to install the specified version on the
|
||||
// host during DEP so it doesn't need to be in the public asset set.
|
||||
if errs := apple_mdm.ValidateMDMSettingsAppleSupportedOSVersion(team.Config.MDM, false); len(errs) > 0 {
|
||||
invalid := &fleet.InvalidArgumentError{}
|
||||
for k, v := range errs {
|
||||
invalid.Append(k, v.Error())
|
||||
}
|
||||
return nil, invalid
|
||||
}
|
||||
|
||||
if payload.MDM.WindowsUpdates != nil {
|
||||
if err := payload.MDM.WindowsUpdates.Validate(); err != nil {
|
||||
return nil, fleet.NewInvalidArgumentError("windows_updates", err.Error())
|
||||
@@ -1131,6 +1145,8 @@ func (svc *Service) ApplyTeamSpecs(ctx context.Context, specs []*fleet.TeamSpec,
|
||||
if len(secrets) > fleet.MaxEnrollSecretsCount {
|
||||
return nil, ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("secrets", "too many secrets"), "validate secrets")
|
||||
}
|
||||
// TODO: should we be we validating the other Apple platforms? if so, we should also include
|
||||
// ValidateMDMSettingsAppleSupportedOSVersion for each platform
|
||||
if err := spec.MDM.MacOSUpdates.Validate(); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("macos_updates", err.Error()))
|
||||
}
|
||||
|
||||
+6
-3
@@ -1,6 +1,8 @@
|
||||
import React, { useContext, useState } from "react";
|
||||
import { isEmpty } from "lodash";
|
||||
import { AxiosResponse } from "axios";
|
||||
|
||||
import { IApiError } from "interfaces/errors";
|
||||
import { APP_CONTEXT_NO_TEAM_ID } from "interfaces/team";
|
||||
import { NotificationContext } from "context/notification";
|
||||
import configAPI from "services/entities/config";
|
||||
@@ -15,6 +17,7 @@ import validatePresence from "components/forms/validators/validate_presence";
|
||||
import CustomLink from "components/CustomLink";
|
||||
import { AppContext } from "context/app";
|
||||
import GitOpsModeTooltipWrapper from "components/GitOpsModeTooltipWrapper";
|
||||
import { getErrorMessage } from "./helpers";
|
||||
|
||||
const baseClass = "apple-os-target-form";
|
||||
|
||||
@@ -164,8 +167,8 @@ const AppleOSTargetForm = ({
|
||||
? await configAPI.update(updateData)
|
||||
: await teamsAPI.update(updateData, currentTeamId);
|
||||
renderFlash("success", "Successfully updated.");
|
||||
} catch {
|
||||
renderFlash("error", "Couldn’t update. Please try again.");
|
||||
} catch (err) {
|
||||
renderFlash("error", getErrorMessage(err as AxiosResponse<IApiError>));
|
||||
} finally {
|
||||
currentTeamId === APP_CONTEXT_NO_TEAM_ID
|
||||
? refetchAppConfig()
|
||||
@@ -226,7 +229,7 @@ const AppleOSTargetForm = ({
|
||||
value={updateNewHosts}
|
||||
className={`${baseClass}__checkbox`}
|
||||
labelTooltipContent={
|
||||
"Hosts that automatically enroll (ADE) are updated to Apple's latest version during macOS Setup Assistant."
|
||||
"During automated enrollment (ADE), hosts below the minimum version are updated to the latest version. If a minimum version isn't set, all hosts are updated to the latest version."
|
||||
}
|
||||
>
|
||||
Update new hosts to latest
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import React from "react";
|
||||
import { AxiosResponse } from "axios";
|
||||
|
||||
import { IApiError } from "interfaces/errors";
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const getErrorMessage = (err: AxiosResponse<IApiError>) => {
|
||||
const apiReason = err?.data?.errors?.[0]?.reason?.toLowerCase?.();
|
||||
|
||||
if (apiReason?.includes("version isn't supported by apple")) {
|
||||
return (
|
||||
<>
|
||||
Couldn't update. The <b>Minimum version</b> isn't supported by
|
||||
Apple.
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (apiReason?.includes("deadline isn't a valid date")) {
|
||||
return (
|
||||
<>
|
||||
Couldn't update. The <b>Deadline</b> isn't a valid date.
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return "Couldn’t update. Please try again.";
|
||||
};
|
||||
+1
-1
@@ -371,7 +371,7 @@ func (m AppleOSUpdateSettings) Validate() error {
|
||||
}
|
||||
|
||||
if _, err := time.Parse("2006-01-02", m.Deadline.Value); err != nil {
|
||||
return errors.New(`deadline accepts YYYY-MM-DD format only (E.g., "2023-06-01.")`)
|
||||
return errors.New(AppleOSVersionDeadlineInvalidMessage)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -25,6 +25,8 @@ var (
|
||||
AndroidMDMNotConfiguredMessage = "Android MDM isn't turned on. For more information about setting up MDM, please visit https://fleetdm.com/learn-more-about/how-to-connect-android-enterprise"
|
||||
AppleMDMNotConfiguredMessage = "macOS MDM isn't turned on. Visit https://fleetdm.com/docs/using-fleet to learn how to turn on MDM."
|
||||
AppleABMDefaultTeamDeprecatedMessage = "mdm.apple_bm_default_team has been deprecated. Please use the new mdm.apple_business_manager key documented here: https://fleetdm.com/learn-more-about/apple-business-manager-gitops"
|
||||
AppleOSVersionUnsupportedMessage = "The minimum version isn't supported by Apple."
|
||||
AppleOSVersionDeadlineInvalidMessage = "The deadline isn't a valid date."
|
||||
CantTurnOffMDMForWindowsHostsMessage = "Can't turn off MDM for Windows hosts."
|
||||
CantTurnOffMDMForPersonalHostsMessage = "Couldn't turn off MDM. This command isn't available for personal hosts."
|
||||
CantWipePersonalHostsMessage = "Couldn't wipe. This command isn't available for personal hosts."
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/logging"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/apple/gdmf"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/apple/mobileconfig"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/internal/commonmdm"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanodep/godep"
|
||||
@@ -1397,7 +1398,8 @@ func (pb *ProfileBimap) add(wantedProfile, currentProfile *fleet.MDMAppleProfile
|
||||
type NewActivityFunc = fleet.NewActivityFunc
|
||||
|
||||
func IOSiPadOSRefetch(ctx context.Context, ds fleet.Datastore, commander *MDMAppleCommander, logger *slog.Logger,
|
||||
newActivityFn NewActivityFunc) error {
|
||||
newActivityFn NewActivityFunc,
|
||||
) error {
|
||||
appCfg, err := ds.AppConfig(ctx)
|
||||
if err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "fetching app config")
|
||||
@@ -1511,7 +1513,8 @@ func IOSiPadOSRefetch(ctx context.Context, ds fleet.Datastore, commander *MDMApp
|
||||
// turnOffMDMIfAPNSFailed checks if the error is an APNSDeliveryError and turns off MDM for the failed devices.
|
||||
// Returns a boolean value to indicate whether or not MDM was turned off.
|
||||
func turnOffMDMIfAPNSFailed(ctx context.Context, ds fleet.Datastore, err error, logger *slog.Logger, newActivityFn NewActivityFunc) (bool,
|
||||
error) {
|
||||
error,
|
||||
) {
|
||||
var e *APNSDeliveryError
|
||||
if !errors.As(err, &e) {
|
||||
return false, nil
|
||||
@@ -1606,6 +1609,55 @@ func IOSiPadOSRevive(ctx context.Context, ds fleet.Datastore, commander *MDMAppl
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateMDMSettingsAppleSupportedOSVersion[T fleet.MDM | fleet.TeamMDM](settings T, excludeNonPublicAssetSets bool) map[string]error {
|
||||
var macOSUpdates, iOSUpdates, iPadOSUpdates fleet.AppleOSUpdateSettings
|
||||
if m, ok := any(settings).(fleet.MDM); ok {
|
||||
macOSUpdates = m.MacOSUpdates
|
||||
iOSUpdates = m.IOSUpdates
|
||||
iPadOSUpdates = m.IPadOSUpdates
|
||||
} else if t, ok := any(settings).(fleet.TeamMDM); ok {
|
||||
macOSUpdates = t.MacOSUpdates
|
||||
iOSUpdates = t.IOSUpdates
|
||||
iPadOSUpdates = t.IPadOSUpdates
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if macOSUpdates.MinimumVersion.Value == "" && iOSUpdates.MinimumVersion.Value == "" && iPadOSUpdates.MinimumVersion.Value == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
am, err := gdmf.GetAssetMetadata()
|
||||
if err != nil {
|
||||
return map[string]error{"mdm": fmt.Errorf("fetching Apple asset metadata: %w", err)}
|
||||
} else if am == nil {
|
||||
// this should never happen, but just in case, return an error indicating that the metadata is not available instead of panicking with a nil pointer dereference
|
||||
return map[string]error{"mdm": errors.New("Apple asset metadata is not available")}
|
||||
}
|
||||
|
||||
errs := make(map[string]error, 3)
|
||||
if macOSUpdates.MinimumVersion.Value != "" {
|
||||
if ok := am.IsSupportedMacOSVersion(macOSUpdates.MinimumVersion.Value, excludeNonPublicAssetSets); !ok {
|
||||
errs["mdm.macos_updates.minimum_version"] = errors.New(fleet.AppleOSVersionUnsupportedMessage)
|
||||
}
|
||||
}
|
||||
if iOSUpdates.MinimumVersion.Value != "" {
|
||||
// NOTE: iPod generally falls in the category of iOS in Fleet, but we're only validating against iPhone here
|
||||
// because we assume Apple will eventually remove iPod versions from the Apple Software Lookup Service
|
||||
// and we want to avoid breaking workflows for users in that event
|
||||
if ok := am.IsSupportedIOSVersion(iOSUpdates.MinimumVersion.Value, "iphone", excludeNonPublicAssetSets); !ok {
|
||||
errs["mdm.ios_updates.minimum_version"] = errors.New(fleet.AppleOSVersionUnsupportedMessage)
|
||||
}
|
||||
}
|
||||
if iPadOSUpdates.MinimumVersion.Value != "" {
|
||||
if ok := am.IsSupportedIOSVersion(iPadOSUpdates.MinimumVersion.Value, "ipad", excludeNonPublicAssetSets); !ok {
|
||||
errs["mdm.ipados_updates.minimum_version"] = errors.New(fleet.AppleOSVersionUnsupportedMessage)
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
// RecoveryLockCommander defines the interface for sending recovery lock commands.
|
||||
// This interface is implemented by MDMAppleCommander and allows for testing.
|
||||
type RecoveryLockCommander interface {
|
||||
|
||||
@@ -4,14 +4,18 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/optjson"
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/apple/mobileconfig"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanodep/client"
|
||||
@@ -270,6 +274,168 @@ func TestGenerateEnrollmentProfileMobileconfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateMDMSettingsAppleSupportedOSVersion(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
// load the test data from the file
|
||||
b, err := os.ReadFile("./gdmf/testdata/gdmf.json")
|
||||
require.NoError(t, err)
|
||||
_, err = w.Write(b)
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
t.Cleanup(srv.Close)
|
||||
dev_mode.SetOverride("FLEET_DEV_GDMF_URL", srv.URL, t)
|
||||
|
||||
// selected versions of from testdata/gdmf.json that we'll use in out tests
|
||||
expectSupportedMacOSPublic := []string{"14.6.1", "13.6.9", "12.7.6", "11.7.10"}
|
||||
expectSupportedMacOSNonPublic := []string{"14.5", "14.6", "13.6.8", "13.6.7", "12.7.5"}
|
||||
expectSupportedIOSPublic := "17.6.1"
|
||||
expectSupportedIOSNonPublic := "17.5.1"
|
||||
// lastIPodSupportedVersion : = "15.8.3"
|
||||
|
||||
// helper function to initialize app config MDM settings with known good versions (tests will modify as needed)
|
||||
mockAppConfigMDM := func() fleet.MDM {
|
||||
return fleet.MDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(expectSupportedMacOSPublic[0]),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(expectSupportedIOSPublic),
|
||||
},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(expectSupportedIOSPublic),
|
||||
},
|
||||
}
|
||||
}
|
||||
// helper function to initialize team MDM settings with known good versions (tests will modify as needed)
|
||||
mockTeamMDM := func() fleet.TeamMDM {
|
||||
return fleet.TeamMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(expectSupportedMacOSPublic[0]),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(expectSupportedIOSPublic),
|
||||
},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(expectSupportedIOSPublic),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// helper function to check if the error matches expectations for a given platform and log appropriately
|
||||
checkErr := func(platform string, wantErr string, gotErrs map[string]error, msg string) {
|
||||
key := fmt.Sprintf("mdm.%s_updates.minimum_version", platform)
|
||||
if wantErr == "" {
|
||||
assert.Empty(t, gotErrs, msg+": expected no error for platform %s but got: %v", platform, gotErrs)
|
||||
} else {
|
||||
assert.Len(t, gotErrs, 1, msg+": expected error for platform %s but got no errors", platform)
|
||||
assert.Contains(t, gotErrs, key, msg+": expected error for platform %s but got no error", platform)
|
||||
assert.ErrorContains(t, gotErrs[key], wantErr, msg+": expected error for platform %s but got: %v", platform, gotErrs[key])
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("macos", func(t *testing.T) {
|
||||
t.Run("app config mdm settings", func(t *testing.T) {
|
||||
ac := mockAppConfigMDM()
|
||||
for _, v := range expectSupportedMacOSPublic {
|
||||
ac.MacOSUpdates.MinimumVersion = optjson.SetString(v)
|
||||
checkErr("macos", "", ValidateMDMSettingsAppleSupportedOSVersion(ac, false), "expect public macOS version to be supported when including non-public asset sets")
|
||||
checkErr("macos", "", ValidateMDMSettingsAppleSupportedOSVersion(ac, true), "expect public macOS version to be supported when excluding non-public asset sets")
|
||||
}
|
||||
for _, v := range expectSupportedMacOSNonPublic {
|
||||
ac.MacOSUpdates.MinimumVersion = optjson.SetString(v)
|
||||
checkErr("macos", "", ValidateMDMSettingsAppleSupportedOSVersion(ac, false), "expect non-public macOS version to be supported when including non-public asset sets")
|
||||
checkErr("macos", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(ac, true), "expect non-public macOS version to return error when excluding non-public asset sets")
|
||||
}
|
||||
|
||||
ac.MacOSUpdates.MinimumVersion = optjson.SetString("11.7.9") // not supported in either asset set, so we expect an error in both cases
|
||||
checkErr("macos", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(ac, false), "expect unsupported macOS version to return error when including non-public asset sets")
|
||||
checkErr("macos", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(ac, true), "expect unsupported macOS version to return error when excluding non-public asset sets")
|
||||
})
|
||||
t.Run("team mdm settings", func(t *testing.T) {
|
||||
tm := mockTeamMDM()
|
||||
for _, v := range expectSupportedMacOSPublic {
|
||||
tm.MacOSUpdates.MinimumVersion = optjson.SetString(v)
|
||||
checkErr("macos", "", ValidateMDMSettingsAppleSupportedOSVersion(tm, false), "expect public macOS version to be supported when including non-public asset sets")
|
||||
checkErr("macos", "", ValidateMDMSettingsAppleSupportedOSVersion(tm, true), "expect public macOS version to be supported when excluding non-public asset sets")
|
||||
}
|
||||
for _, v := range expectSupportedMacOSNonPublic {
|
||||
tm.MacOSUpdates.MinimumVersion = optjson.SetString(v)
|
||||
checkErr("macos", "", ValidateMDMSettingsAppleSupportedOSVersion(tm, false), "expect non-public macOS version to be supported when including non-public asset sets")
|
||||
checkErr("macos", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(tm, true), "expect non-public macOS version to return error when excluding non-public asset sets")
|
||||
}
|
||||
|
||||
tm.MacOSUpdates.MinimumVersion = optjson.SetString("11.7.9") // not supported in either asset set, so we expect an error in both cases
|
||||
checkErr("macos", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(tm, false), "expect unsupported macOS version to return error when including non-public asset sets")
|
||||
checkErr("macos", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(tm, true), "expect unsupported macOS version to return error when excluding non-public asset sets")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("ios", func(t *testing.T) {
|
||||
t.Run("app config mdm settings", func(t *testing.T) {
|
||||
ac := mockAppConfigMDM()
|
||||
ac.IOSUpdates.MinimumVersion = optjson.SetString(expectSupportedIOSPublic)
|
||||
checkErr("ios", "", ValidateMDMSettingsAppleSupportedOSVersion(ac, false), "expect public iOS version to be supported when including non-public asset sets")
|
||||
checkErr("ios", "", ValidateMDMSettingsAppleSupportedOSVersion(ac, true), "expect public iOS version to be supported when excluding non-public asset sets")
|
||||
|
||||
ac.IOSUpdates.MinimumVersion = optjson.SetString(expectSupportedIOSNonPublic)
|
||||
checkErr("ios", "", ValidateMDMSettingsAppleSupportedOSVersion(ac, false), "expect non-public iOS version to be supported when including non-public asset sets")
|
||||
checkErr("ios", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(ac, true), "expect non-public iOS version to return error when excluding non-public asset sets")
|
||||
|
||||
ac.IOSUpdates.MinimumVersion = optjson.SetString("5.3.9") // only supported for Apple Watch, so we expect an error
|
||||
checkErr("ios", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(ac, false), "expect unsupported iOS version to return error when including non-public asset sets")
|
||||
checkErr("ios", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(ac, true), "expect unsupported iOS version to return error when excluding non-public asset sets")
|
||||
})
|
||||
|
||||
t.Run("team mdm settings", func(t *testing.T) {
|
||||
tm := mockTeamMDM()
|
||||
tm.IOSUpdates.MinimumVersion = optjson.SetString(expectSupportedIOSPublic)
|
||||
checkErr("ios", "", ValidateMDMSettingsAppleSupportedOSVersion(tm, false), "expect public iOS version to be supported when including non-public asset sets")
|
||||
checkErr("ios", "", ValidateMDMSettingsAppleSupportedOSVersion(tm, true), "expect public iOS version to be supported when excluding non-public asset sets")
|
||||
|
||||
tm.IOSUpdates.MinimumVersion = optjson.SetString(expectSupportedIOSNonPublic)
|
||||
checkErr("ios", "", ValidateMDMSettingsAppleSupportedOSVersion(tm, false), "expect non-public iOS version to be supported when including non-public asset sets")
|
||||
checkErr("ios", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(tm, true), "expect non-public iOS version to return error when excluding non-public asset sets")
|
||||
|
||||
tm.IOSUpdates.MinimumVersion = optjson.SetString("5.3.9") // only supported for Apple Watch, so we expect an error
|
||||
checkErr("ios", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(tm, false), "expect unsupported iOS version to return error when including non-public asset sets")
|
||||
checkErr("ios", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(tm, true), "expect unsupported iOS version to return error when excluding non-public asset sets")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("ipados", func(t *testing.T) {
|
||||
t.Run("app config mdm settings", func(t *testing.T) {
|
||||
ac := mockAppConfigMDM()
|
||||
ac.IPadOSUpdates.MinimumVersion = optjson.SetString(expectSupportedIOSPublic)
|
||||
checkErr("ipados", "", ValidateMDMSettingsAppleSupportedOSVersion(ac, false), "expect public iPadOS version to be supported when including non-public asset sets")
|
||||
checkErr("ipados", "", ValidateMDMSettingsAppleSupportedOSVersion(ac, true), "expect public iPadOS version to be supported when excluding non-public asset sets")
|
||||
|
||||
ac.IPadOSUpdates.MinimumVersion = optjson.SetString(expectSupportedIOSNonPublic)
|
||||
checkErr("ipados", "", ValidateMDMSettingsAppleSupportedOSVersion(ac, false), "expect non-public iPadOS version to be supported when including non-public asset sets")
|
||||
checkErr("ipados", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(ac, true), "expect non-public iPadOS version to return error when excluding non-public asset sets")
|
||||
|
||||
ac.IPadOSUpdates.MinimumVersion = optjson.SetString("5.3.9") // only supported for Apple Watch, so we expect an error
|
||||
checkErr("ipados", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(ac, false), "expect unsupported iPadOS version to return error when including non-public asset sets")
|
||||
checkErr("ipados", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(ac, true), "expect unsupported iPadOS version to return error when excluding non-public asset sets")
|
||||
})
|
||||
|
||||
t.Run("team mdm settings", func(t *testing.T) {
|
||||
tm := mockTeamMDM()
|
||||
tm.IPadOSUpdates.MinimumVersion = optjson.SetString(expectSupportedIOSPublic)
|
||||
checkErr("ipados", "", ValidateMDMSettingsAppleSupportedOSVersion(tm, false), "expect public iPadOS version to be supported when including non-public asset sets")
|
||||
checkErr("ipados", "", ValidateMDMSettingsAppleSupportedOSVersion(tm, true), "expect public iPadOS version to be supported when excluding non-public asset sets")
|
||||
|
||||
tm.IPadOSUpdates.MinimumVersion = optjson.SetString(expectSupportedIOSNonPublic)
|
||||
checkErr("ipados", "", ValidateMDMSettingsAppleSupportedOSVersion(tm, false), "expect non-public iPadOS version to be supported when including non-public asset sets")
|
||||
checkErr("ipados", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(tm, true), "expect non-public iPadOS version to return error when excluding non-public asset sets")
|
||||
|
||||
tm.IPadOSUpdates.MinimumVersion = optjson.SetString("5.3.9") // only supported for Apple Watch, so we expect an error
|
||||
checkErr("ipados", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(tm, false), "expect unsupported iPadOS version to return error when including non-public asset sets")
|
||||
checkErr("ipados", fleet.AppleOSVersionUnsupportedMessage, ValidateMDMSettingsAppleSupportedOSVersion(tm, true), "expect unsupported iPadOS version to return error when excluding non-public asset sets")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
type notFoundError struct{}
|
||||
|
||||
func (e notFoundError) IsNotFound() bool { return true }
|
||||
|
||||
@@ -58,34 +58,79 @@ type AssetSets struct {
|
||||
// XROS []Asset `json:"xrOS"` // Fleet doesn't support xrOS yet
|
||||
}
|
||||
|
||||
// APIResponse represents the response from the Apple Software Lookup Service[1][2].
|
||||
// AssetMetadata represents the response from the Apple Software Lookup Service[1][2].
|
||||
// [1]: http://gdmf.apple.com/v2/pmv
|
||||
// [2]: https://support.apple.com/guide/deployment/use-mdm-to-deploy-software-updates-depafd2fad80/web
|
||||
type APIResponse struct {
|
||||
type AssetMetadata struct {
|
||||
PublicAssetSets AssetSets `json:"PublicAssetSets"`
|
||||
AssetSets AssetSets `json:"AssetSets"`
|
||||
// PublicRapidSecurityResponses interface{} `json:"PublicRapidSecurityResponses"` // Fleet doesn't support PublicRapidSecurityResponses yet
|
||||
}
|
||||
|
||||
// IsSupportedMacOSVersion checks if the given macOS version is supported by Apple. The
|
||||
// excludeNonPublicAssetSets parameter controls whether to check against the full asset set or just
|
||||
// the public asset set, which is relevant for DEP enrollment where only public versions are valid.
|
||||
func (a AssetMetadata) IsSupportedMacOSVersion(version string, excludeNonPublicAssetSets bool) bool {
|
||||
as := a.AssetSets.MacOS
|
||||
if excludeNonPublicAssetSets {
|
||||
as = a.PublicAssetSets.MacOS
|
||||
}
|
||||
|
||||
for _, s := range as {
|
||||
if s.ProductVersion == version {
|
||||
return true // version is supported
|
||||
}
|
||||
}
|
||||
|
||||
return false // version is not supported
|
||||
}
|
||||
|
||||
// IsSupportedIOSVersion checks if the given iOS version is supported by Apple for the given device
|
||||
// prefix (e.g. "iPhone", "iPad"). If devicePrefix is empty, it checks if the version is supported
|
||||
// for any iOS device (which includes things like iPod, Apple Watch, and Apple TV). The
|
||||
// excludeNonPublicAssetSets parameter controls whether to check against the full asset set or just
|
||||
// the public asset set, which is relevant for DEP enrollment where only public versions are valid.
|
||||
func (a AssetMetadata) IsSupportedIOSVersion(version string, devicePrefix string, excludeNonPublicAssetSets bool) bool {
|
||||
as := a.AssetSets.IOS
|
||||
if excludeNonPublicAssetSets {
|
||||
as = a.PublicAssetSets.IOS
|
||||
}
|
||||
|
||||
for _, s := range as {
|
||||
if s.ProductVersion == version {
|
||||
if devicePrefix == "" {
|
||||
return true // version is supported for iOS with any device prefix
|
||||
}
|
||||
for _, d := range s.SupportedDevices {
|
||||
if strings.HasPrefix(strings.ToLower(d), strings.ToLower(devicePrefix)) {
|
||||
return true // version is supported for device with the given prefix
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false // version is not supported
|
||||
}
|
||||
|
||||
// GetLatestOSVersion returns the latest OS version for the given device. The device is matched
|
||||
// against the Apple Software Update Lookup Service[1][2] to find the latest version. If no matching
|
||||
// asset is found, an error is returned.
|
||||
// against the Apple Software Update Lookup Service[1][2] to find the latest version in the
|
||||
// PublicAssetSets. If no matching asset is found, an error is returned.
|
||||
// [1]: http://gdmf.apple.com/v2/pmv
|
||||
// [2]: https://support.apple.com/guide/deployment/use-mdm-to-deploy-software-updates-depafd2fad80/web
|
||||
func GetLatestOSVersion(device fleet.MDMAppleMachineInfo) (*Asset, error) {
|
||||
r, err := GetAssetMetadata()
|
||||
am, err := GetAssetMetadata()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("retrieving asset metadata: %w", err)
|
||||
}
|
||||
|
||||
assetSet := r.PublicAssetSets.MacOS // default to public asset set; note that if the device is not macOS, iPhone, iPad, or iPod we'll fail to match the supported device and return an error below
|
||||
assetSet := am.PublicAssetSets.MacOS // default to public asset set; note that if the device is not macOS, iPhone, iPad, or iPod we'll fail to match the supported device and return an error below
|
||||
if strings.HasPrefix(device.Product, "iPhone") ||
|
||||
strings.HasPrefix(device.Product, "iPod") ||
|
||||
strings.HasPrefix(device.Product, "iPad") ||
|
||||
strings.HasPrefix(device.SoftwareUpdateDeviceID, "iPhone") ||
|
||||
strings.HasPrefix(device.SoftwareUpdateDeviceID, "iPod") ||
|
||||
strings.HasPrefix(device.SoftwareUpdateDeviceID, "iPad") {
|
||||
assetSet = r.PublicAssetSets.IOS
|
||||
assetSet = am.PublicAssetSets.IOS
|
||||
}
|
||||
latestIdx := -1
|
||||
for i, s := range assetSet {
|
||||
@@ -129,7 +174,7 @@ func createClient() *http.Client {
|
||||
// GetAssetMetadata retrieves the asset metadata from the Apple Software Lookup Service[1][2].
|
||||
// [1]: http://gdmf.apple.com/v2/pmv
|
||||
// [2]: https://support.apple.com/guide/deployment/use-mdm-to-deploy-software-updates-depafd2fad80/web
|
||||
func GetAssetMetadata() (*APIResponse, error) {
|
||||
func GetAssetMetadata() (*AssetMetadata, error) {
|
||||
baseURL := getBaseURL()
|
||||
reqURL, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
@@ -151,7 +196,7 @@ func GetAssetMetadata() (*APIResponse, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading response body from Apple endpoint: %w", err)
|
||||
}
|
||||
var dest APIResponse
|
||||
var dest AssetMetadata
|
||||
if err := json.Unmarshal(body, &dest); err != nil {
|
||||
return nil, fmt.Errorf("decoding response data from Apple endpoint: %w", err)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestGetLatest(t *testing.T) {
|
||||
_, err = w.Write(b)
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
defer srv.Close()
|
||||
t.Cleanup(srv.Close)
|
||||
dev_mode.SetOverride("FLEET_DEV_GDMF_URL", srv.URL, t)
|
||||
|
||||
// test the function
|
||||
@@ -225,11 +225,8 @@ func TestRetries(t *testing.T) {
|
||||
_, err := w.Write([]byte(`{"error": "bad request"}`))
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
dev_mode.SetOverride("FLEET_DEV_GDMF_URL", srv.URL)
|
||||
t.Cleanup(func() {
|
||||
srv.Close()
|
||||
dev_mode.ClearOverride("FLEET_DEV_GDMF_URL")
|
||||
})
|
||||
t.Cleanup(srv.Close)
|
||||
dev_mode.SetOverride("FLEET_DEV_GDMF_URL", srv.URL, t)
|
||||
|
||||
latest, err := GetLatestOSVersion(fleet.MDMAppleMachineInfo{
|
||||
OSVersion: "14.4.1",
|
||||
|
||||
@@ -5,7 +5,16 @@ import (
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/dev_mode"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func NewTestMDMAppleCertTemplate() *x509.Certificate {
|
||||
@@ -27,3 +36,23 @@ func NewTestMDMAppleCertTemplate() *x509.Certificate {
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
}
|
||||
|
||||
// StartNewAppleGDMFTestServer creates a new test server that serves the GDMF data from the testdata
|
||||
// file. It also sets the necessary dev mode overrides to point to the test server and disable
|
||||
// caching. It closes the server and clears the underlying overrides when the test finishes.
|
||||
func StartNewAppleGDMFTestServer(t *testing.T) {
|
||||
_, thisFile, _, _ := runtime.Caller(0)
|
||||
gdmfTestDataPath := filepath.Join(filepath.Dir(thisFile), "../apple/gdmf/testdata/gdmf.json")
|
||||
|
||||
appleGDMFSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
// load the test data from the file
|
||||
b, err := os.ReadFile(gdmfTestDataPath)
|
||||
require.NoError(t, err)
|
||||
_, err = w.Write(b)
|
||||
require.NoError(t, err)
|
||||
}))
|
||||
t.Cleanup(appleGDMFSrv.Close)
|
||||
|
||||
dev_mode.SetOverride("FLEET_DEV_GDMF_URL", appleGDMFSrv.URL, t)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/license"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/viewer"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
"github.com/fleetdm/fleet/v4/server/platform/endpointer"
|
||||
"github.com/fleetdm/fleet/v4/server/platform/logging"
|
||||
"github.com/fleetdm/fleet/v4/server/version"
|
||||
@@ -1486,6 +1487,15 @@ func (svc *Service) validateMDM(
|
||||
invalid.Append("ipados_updates", err.Error())
|
||||
}
|
||||
|
||||
// Always check whether specified versions are supported by Apple (even if they weren't updated)
|
||||
// Note that we're validating against the full, non-public asset set of OS versions here because
|
||||
// in our DEP flow the minimum version just acts as the threshold for whether or not to update
|
||||
// the host to the latest, public version. We don't need to install the specified version on the
|
||||
// host during DEP so it doesn't need to be in the public asset set.
|
||||
for k, v := range apple_mdm.ValidateMDMSettingsAppleSupportedOSVersion(*mdm, false) {
|
||||
invalid.Append(k, v.Error())
|
||||
}
|
||||
|
||||
if err := mdm.MacOSSetup.Validate(); err != nil {
|
||||
var invalidArgErr *fleet.InvalidArgumentError
|
||||
if errors.As(err, &invalidArgErr) {
|
||||
|
||||
+34
-28
@@ -2081,16 +2081,17 @@ func (svc *Service) CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx context.Cont
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
needsUpdate, err := svc.needsOSUpdateForDEPEnrollment(ctx, *m)
|
||||
// shouldUpdate depends on the app_config settings for minimum_version and update_new_hosts
|
||||
shouldUpdate, err := svc.shouldOSUpdateForDEPEnrollment(ctx, *m)
|
||||
if err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "checking os updates settings", "serial", m.Serial)
|
||||
}
|
||||
|
||||
if !needsUpdate {
|
||||
} else if !shouldUpdate {
|
||||
svc.logger.DebugContext(ctx, "device is above minimum or update new host not checked, skipping os version check", "serial", m.Serial)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// if the device should update based on appconfig settings, we also need to check what versions
|
||||
// are actually available for the device from Apple
|
||||
sur, err := svc.getAppleSoftwareUpdateRequiredForDEPEnrollment(*m)
|
||||
if err != nil {
|
||||
// log for debugging but allow enrollment to proceed
|
||||
@@ -2101,7 +2102,7 @@ func (svc *Service) CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx context.Cont
|
||||
return sur, nil
|
||||
}
|
||||
|
||||
func (svc *Service) needsOSUpdateForDEPEnrollment(ctx context.Context, m fleet.MDMAppleMachineInfo) (bool, error) {
|
||||
func (svc *Service) shouldOSUpdateForDEPEnrollment(ctx context.Context, m fleet.MDMAppleMachineInfo) (bool, error) {
|
||||
// NOTE: Under the hood, the datastore is joining host_dep_assignments to the hosts table to
|
||||
// look up DEP hosts by serial number. It grabs the team id and platform from the
|
||||
// hosts table. Then it uses the team id to get either the global config or team config.
|
||||
@@ -2124,35 +2125,40 @@ func (svc *Service) needsOSUpdateForDEPEnrollment(ctx context.Context, m fleet.M
|
||||
}
|
||||
|
||||
minVersion := settings.MinimumVersion.Value
|
||||
hasMinVersion := settings.MinimumVersion.Set && settings.MinimumVersion.Valid && minVersion != ""
|
||||
|
||||
// For macOS hosts, whether to update new hosts during DEP enrollment is determined solely by UpdateNewHosts
|
||||
if platform == "darwin" {
|
||||
updateNewHosts := settings.UpdateNewHosts.Set && settings.UpdateNewHosts.Valid && settings.UpdateNewHosts.Value
|
||||
|
||||
svc.logger.InfoContext(ctx, "checking os updates settings for macos, update will be forced if UpdateNewHosts is set",
|
||||
"update_new_hosts", updateNewHosts,
|
||||
"serial", m.Serial,
|
||||
)
|
||||
return updateNewHosts, nil
|
||||
isSetMinVersion := settings.MinimumVersion.Set && settings.MinimumVersion.Valid && minVersion != ""
|
||||
logs := []any{
|
||||
"platform", platform,
|
||||
"minimum_version", minVersion,
|
||||
"current_version", m.OSVersion,
|
||||
"serial", m.Serial,
|
||||
}
|
||||
|
||||
// TODO: confirm what this check should do
|
||||
if !hasMinVersion {
|
||||
svc.logger.InfoContext(ctx, "checking os updates settings, minimum version not set",
|
||||
"serial", m.Serial,
|
||||
"current_version", m.OSVersion,
|
||||
"minimum_version", minVersion,
|
||||
)
|
||||
if platform != "darwin" && !isSetMinVersion {
|
||||
svc.logger.InfoContext(ctx, "checking os updates settings for non-macos platform, minimum version not set, skipping version check", logs...)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if platform == "darwin" {
|
||||
updateNewHosts := settings.UpdateNewHosts.Set && settings.UpdateNewHosts.Valid && settings.UpdateNewHosts.Value
|
||||
logs = append(logs, "update_new_hosts", updateNewHosts)
|
||||
switch {
|
||||
case !updateNewHosts:
|
||||
// never update macos if updateNewHosts is false
|
||||
svc.logger.InfoContext(ctx, "checking os updates settings for macos, new hosts should not update", logs...)
|
||||
return false, nil
|
||||
case !isSetMinVersion:
|
||||
// always update macos if updateNewHosts is true and minimum version is not set
|
||||
svc.logger.InfoContext(ctx, "checking os updates settings for macos, new hosts should always update to latest", logs...)
|
||||
return true, nil
|
||||
default:
|
||||
// default to normal version check (require update if less than minimum version)
|
||||
svc.logger.InfoContext(ctx, "checking os updates settings for macos, new hosts should update to latest if below minimum version", logs...)
|
||||
}
|
||||
}
|
||||
|
||||
needsUpdate, err := apple_mdm.IsLessThanVersion(m.OSVersion, minVersion)
|
||||
if err != nil {
|
||||
svc.logger.InfoContext(ctx, "checking os updates settings, cannot compare versions",
|
||||
"serial", m.Serial,
|
||||
"current_version", m.OSVersion,
|
||||
"minimum_version", minVersion,
|
||||
)
|
||||
svc.logger.InfoContext(ctx, "checking os updates settings, cannot compare versions", logs...)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -5287,7 +5287,7 @@ func TestUnmarshalAppList(t *testing.T) {
|
||||
assert.ElementsMatch(t, expectedSoftware, software)
|
||||
}
|
||||
|
||||
func TestNeedsOSUpdateForDEPEnrollment(t *testing.T) {
|
||||
func TestShouldOSUpdateForDEPEnrollment(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
platform string
|
||||
@@ -5321,7 +5321,7 @@ func TestNeedsOSUpdateForDEPEnrollment(t *testing.T) {
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "if platform is macOS and update_new_hosts is set",
|
||||
name: "if platform is macOS and both update_new_hosts and minimum_version are set and host is below the minimum version",
|
||||
platform: string(fleet.MacOSPlatform),
|
||||
appleMachineInfo: fleet.MDMAppleMachineInfo{
|
||||
OSVersion: "16.0.1",
|
||||
@@ -5332,6 +5332,29 @@ func TestNeedsOSUpdateForDEPEnrollment(t *testing.T) {
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "if platform is macOS and both update_new_hosts and minimum_version are set and host is at the minimum version",
|
||||
platform: string(fleet.MacOSPlatform),
|
||||
appleMachineInfo: fleet.MDMAppleMachineInfo{
|
||||
OSVersion: "16.0.2",
|
||||
},
|
||||
appleOSUpdateSettings: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("16.0.2"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
expectedResult: false,
|
||||
},
|
||||
{
|
||||
name: "if platform is macOS and update_new_hosts is set but minimum_version is not set",
|
||||
platform: string(fleet.MacOSPlatform),
|
||||
appleMachineInfo: fleet.MDMAppleMachineInfo{
|
||||
OSVersion: "16.0.1",
|
||||
},
|
||||
appleOSUpdateSettings: fleet.AppleOSUpdateSettings{
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
expectedResult: true,
|
||||
},
|
||||
{
|
||||
name: "if platform is not macOS and min_version is not set",
|
||||
platform: string(fleet.IPadOSPlatform),
|
||||
@@ -5376,7 +5399,7 @@ func TestNeedsOSUpdateForDEPEnrollment(t *testing.T) {
|
||||
svc := &Service{ds: ds, logger: slog.New(slog.DiscardHandler)}
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := svc.needsOSUpdateForDEPEnrollment(ctx, tt.appleMachineInfo)
|
||||
result, err := svc.shouldOSUpdateForDEPEnrollment(ctx, tt.appleMachineInfo)
|
||||
require.Equal(t, tt.expectedResult, result)
|
||||
require.Equal(t, tt.expectedErr, err)
|
||||
})
|
||||
@@ -5400,6 +5423,9 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
latestMacOSVersion := "14.6.1"
|
||||
latestMacOSBuild := "23G93"
|
||||
|
||||
latestIOSVersion := "17.6.1"
|
||||
latestIOSBuild := "21G93"
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
machineInfo *fleet.MDMAppleMachineInfo
|
||||
@@ -5485,17 +5511,62 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
// FIXME: When we have more time, this whole test is overdue for a refactor because a bunch of jank
|
||||
// came with the update new hosts settings for macOS that made the test cases more dependent on
|
||||
// subtle differences in the machine info for macOS vs non-macOS platforms and made the setup
|
||||
// more complex and harder to reason about. For now, we can get away with some nested subtests
|
||||
// to reuse the test cases for both macOS and non-macOS platforms, but ideally we would refactor
|
||||
// the function under test to separate out the platform-specific logic so that we can have
|
||||
// clearer and more focused tests for each platform without needing to have a bunch of
|
||||
// conditional logic in the test itself.
|
||||
for _, tt := range testCases {
|
||||
// Non-macOS platforms
|
||||
for _, platform := range []string{"ios", "ipados"} {
|
||||
|
||||
if tt.name == "no match for software update device ID" {
|
||||
// skip this test case for non-macOS platforms since SUDeviceID is really only relevant for macOS updates
|
||||
continue
|
||||
}
|
||||
|
||||
t.Run(fmt.Sprintf("%s: %s", platform, tt.name), func(t *testing.T) {
|
||||
// switch up the machine info to match the platform because test cases were
|
||||
// originally written with macOS in mind
|
||||
var product, osVersion, suDeviceID string
|
||||
var mi *fleet.MDMAppleMachineInfo
|
||||
if tt.machineInfo != nil {
|
||||
osVersion = strings.Replace(tt.machineInfo.OSVersion, "14", "17", 1)
|
||||
if platform == "ios" {
|
||||
product = "iPhone16,2"
|
||||
suDeviceID = strings.Replace(tt.machineInfo.SoftwareUpdateDeviceID, "J516sAP", "iPhone", 1)
|
||||
} else {
|
||||
product = "iPad14,11"
|
||||
suDeviceID = strings.Replace(tt.machineInfo.SoftwareUpdateDeviceID, "J516sAP", "iPad", 1)
|
||||
}
|
||||
|
||||
mi = &fleet.MDMAppleMachineInfo{
|
||||
MDMCanRequestSoftwareUpdate: tt.machineInfo.MDMCanRequestSoftwareUpdate,
|
||||
Product: product,
|
||||
OSVersion: osVersion,
|
||||
SupplementalBuildVersion: tt.machineInfo.SupplementalBuildVersion,
|
||||
SoftwareUpdateDeviceID: suDeviceID,
|
||||
}
|
||||
}
|
||||
// same for update required details
|
||||
var details *fleet.MDMAppleSoftwareUpdateRequiredDetails
|
||||
if tt.updateRequired != nil {
|
||||
details = &fleet.MDMAppleSoftwareUpdateRequiredDetails{
|
||||
OSVersion: latestIOSVersion,
|
||||
BuildVersion: latestIOSBuild,
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
return platform, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(latestIOSVersion),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, mi)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
@@ -5505,7 +5576,7 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
Details: *details,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
@@ -5514,11 +5585,11 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
|
||||
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"),
|
||||
return platform, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.5"),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, mi)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
@@ -5528,7 +5599,7 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
Details: *details,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
@@ -5538,11 +5609,11 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
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"),
|
||||
return platform, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.7"),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, mi)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
@@ -5552,7 +5623,7 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
if tt.updateRequired != nil {
|
||||
require.Equal(t, &fleet.MDMAppleSoftwareUpdateRequired{
|
||||
Code: fleet.MDMAppleSoftwareUpdateRequiredCode,
|
||||
Details: *tt.updateRequired,
|
||||
Details: *details,
|
||||
}, sur)
|
||||
} else {
|
||||
require.Nil(t, sur)
|
||||
@@ -5561,11 +5632,11 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
|
||||
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"),
|
||||
return platform, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.1"),
|
||||
}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, mi)
|
||||
if tt.err != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tt.err)
|
||||
@@ -5578,27 +5649,27 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
|
||||
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
|
||||
return platform, &fleet.AppleOSUpdateSettings{}, nil
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, mi)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", &fleet.AppleOSUpdateSettings{
|
||||
return platform, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString(""),
|
||||
}, nil
|
||||
}
|
||||
sur, err = svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
sur, err = svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, mi)
|
||||
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{}
|
||||
return platform, nil, ¬FoundError{}
|
||||
}
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, mi)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
})
|
||||
@@ -5621,6 +5692,7 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("when UpdateNewHosts is set and minimum is not set", func(t *testing.T) {
|
||||
// test with min version not present
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "darwin", &fleet.AppleOSUpdateSettings{
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
@@ -5640,6 +5712,7 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
require.Nil(t, sur)
|
||||
}
|
||||
|
||||
// test again with min version explicitly set to empty string
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "darwin", &fleet.AppleOSUpdateSettings{
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
@@ -5664,6 +5737,7 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
ds.GetMDMAppleOSUpdatesSettingsByHostSerialFunc = func(ctx context.Context, serial string) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "darwin", nil, ¬FoundError{}
|
||||
}
|
||||
// never block enrollment when settings are not found
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, sur)
|
||||
@@ -5692,6 +5766,30 @@ func TestCheckMDMAppleEnrollmentWithMinimumOSVersion(t *testing.T) {
|
||||
require.Nil(t, sur)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("when UpdateNewHosts is set and required minimum is less than 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("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)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5701,7 +5799,7 @@ 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) (string, *fleet.AppleOSUpdateSettings, error) {
|
||||
return "ios", &fleet.AppleOSUpdateSettings{MinimumVersion: optjson.SetString(latestMacOSVersion)}, nil
|
||||
return "macos", &fleet.AppleOSUpdateSettings{MinimumVersion: optjson.SetString(latestMacOSVersion), UpdateNewHosts: optjson.SetBool(true)}, nil
|
||||
}
|
||||
|
||||
sur, err := svc.CheckMDMAppleEnrollmentWithMinimumOSVersion(ctx, tt.machineInfo)
|
||||
|
||||
@@ -51,6 +51,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/server/live_query/live_query_mock"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm"
|
||||
maintained_apps "github.com/fleetdm/fleet/v4/server/mdm/maintainedapps"
|
||||
mdmtest "github.com/fleetdm/fleet/v4/server/mdm/testing_utils"
|
||||
"github.com/fleetdm/fleet/v4/server/policies"
|
||||
"github.com/fleetdm/fleet/v4/server/ptr"
|
||||
"github.com/fleetdm/fleet/v4/server/pubsub"
|
||||
@@ -180,6 +181,9 @@ func (s *integrationEnterpriseTestSuite) clearOktaConditionalAccess() {
|
||||
func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
t := s.T()
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
// create a team through the service so it initializes the agent ops
|
||||
teamName := t.Name() + "team1"
|
||||
teamNameDecomposed := teamName + "ᄀ" + "ᅡ" // Add a decomposed Unicode character
|
||||
@@ -228,16 +232,16 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
"features": &features,
|
||||
"mdm": map[string]any{
|
||||
"macos_updates": map[string]any{
|
||||
"minimum_version": "10.15.0",
|
||||
"minimum_version": "14.6.1",
|
||||
"deadline": "2021-01-01",
|
||||
"update_new_hosts": true,
|
||||
},
|
||||
"ios_updates": map[string]any{
|
||||
"minimum_version": "17.5.1",
|
||||
"minimum_version": "17.6.1",
|
||||
"deadline": "2024-07-23",
|
||||
},
|
||||
"ipados_updates": map[string]any{
|
||||
"minimum_version": "18.0",
|
||||
"minimum_version": "17.6.1",
|
||||
"deadline": "2024-08-24",
|
||||
},
|
||||
},
|
||||
@@ -260,17 +264,17 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
}, team.Config.Features)
|
||||
require.Equal(t, fleet.TeamMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.5.1"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-07-23"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("18.0"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-08-24"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
},
|
||||
@@ -393,17 +397,17 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
require.Equal(t, applyResp.TeamIDsByName[teamName], team.ID)
|
||||
require.Equal(t, fleet.TeamMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.5.1"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-07-23"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("18.0"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-08-24"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
},
|
||||
@@ -434,17 +438,17 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
s.DoJSON("GET", "/api/latest/fleet/teams/"+fmt.Sprint(team.ID), nil, http.StatusOK, &getTmResp)
|
||||
require.Equal(t, fleet.TeamMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.5.1"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-07-23"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("18.0"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-08-24"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
},
|
||||
@@ -477,17 +481,17 @@ func (s *integrationEnterpriseTestSuite) TestTeamSpecs() {
|
||||
require.Equal(t, team.ID, listTmResp.Teams[0].ID)
|
||||
require.Equal(t, fleet.TeamMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.5.1"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-07-23"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("18.0"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-08-24"),
|
||||
UpdateNewHosts: optjson.Bool{Set: true},
|
||||
},
|
||||
@@ -2979,6 +2983,9 @@ func (s *integrationEnterpriseTestSuite) TestNoTeamFailingPolicyWebhookTrigger()
|
||||
func (s *integrationEnterpriseTestSuite) TestWindowsUpdatesTeamConfig() {
|
||||
t := s.T()
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
// Create a team
|
||||
team := &fleet.Team{
|
||||
Name: t.Name(),
|
||||
@@ -3075,12 +3082,12 @@ func (s *integrationEnterpriseTestSuite) TestWindowsUpdatesTeamConfig() {
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"macos_updates": &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
},
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "14.6.1", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2021-01-01", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, 6, tmResp.Team.Config.MDM.WindowsUpdates.DeadlineDays.Value)
|
||||
require.Equal(t, 2, tmResp.Team.Config.MDM.WindowsUpdates.GracePeriodDays.Value)
|
||||
@@ -3102,7 +3109,7 @@ func (s *integrationEnterpriseTestSuite) TestWindowsUpdatesTeamConfig() {
|
||||
"windows_updates": nil,
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "14.6.1", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2021-01-01", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, 6, tmResp.Team.Config.MDM.WindowsUpdates.DeadlineDays.Value)
|
||||
require.Equal(t, 2, tmResp.Team.Config.MDM.WindowsUpdates.GracePeriodDays.Value)
|
||||
@@ -3246,6 +3253,9 @@ func (s *integrationEnterpriseTestSuite) assertAppleOSUpdatesDeclaration(teamID
|
||||
func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
t := s.T()
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
team := &fleet.Team{
|
||||
Name: t.Name(),
|
||||
Description: "Team description",
|
||||
@@ -3263,7 +3273,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
|
||||
// modify the team's config (macOS first)
|
||||
macOSUpdates := &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2021-01-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
}
|
||||
@@ -3272,13 +3282,13 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
"macos_updates": macOSUpdates,
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "14.6.1", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2021-01-01", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, true, tmResp.Team.Config.MDM.MacOSUpdates.UpdateNewHosts.Value)
|
||||
|
||||
s.lastActivityOfTypeMatches(
|
||||
fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(),
|
||||
fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "10.15.0", "deadline": "2021-01-01"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "14.6.1", "deadline": "2021-01-01"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
|
||||
s.lastActivityOfTypeMatches(
|
||||
fleet.ActivityTypeEnabledMacosUpdateNewHosts{}.ActivityName(),
|
||||
@@ -3295,12 +3305,12 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
|
||||
// modify the team's config (now iOS and iPadOS)
|
||||
iOSUpdates := &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("11.11.11"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2022-02-02"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
}
|
||||
iPadOSUpdates := &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.12.12"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2023-03-03"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
}
|
||||
@@ -3311,23 +3321,23 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
"ipados_updates": iPadOSUpdates,
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "14.6.1", 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, "17.6.1", 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, "17.6.1", 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, "fleet_id": %d, "fleet_name": %q, "minimum_version": "10.15.0", "deadline": "2021-01-01"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "11.11.11", "deadline": "2022-02-02"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "12.12.12", "deadline": "2023-03-03"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "14.6.1", "deadline": "2021-01-01"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "17.6.1", "deadline": "2022-02-02"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "17.6.1", "deadline": "2023-03-03"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
|
||||
s.assertAppleOSUpdatesDeclaration(&team.ID, mdm.FleetMacOSUpdatesProfileName, macOSUpdates)
|
||||
s.assertAppleOSUpdatesDeclaration(&team.ID, mdm.FleetIOSUpdatesProfileName, iOSUpdates)
|
||||
@@ -3335,16 +3345,16 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
|
||||
// only update the deadlines
|
||||
macOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2025-10-01"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
}
|
||||
iOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("11.11.11"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-02-02"),
|
||||
}
|
||||
iPadOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.12.12"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-03-03"),
|
||||
}
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
@@ -3354,21 +3364,21 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
"ipados_updates": iPadOSUpdates,
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "14.6.1", 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, "17.6.1", 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, "17.6.1", 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, "fleet_id": %d, "fleet_name": %q, "minimum_version": "10.15.0", "deadline": "2025-10-01"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
iOSLastActivity := s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "11.11.11", "deadline": "2024-02-02"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
iPadOSLastActivity := s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "12.12.12", "deadline": "2024-03-03"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
macOSLastActivity := s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "14.6.1", "deadline": "2025-10-01"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
iOSLastActivity := s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "17.6.1", "deadline": "2024-02-02"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
iPadOSLastActivity := s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), fmt.Sprintf(`{"team_id": %d, "team_name": %q, "fleet_id": %d, "fleet_name": %q, "minimum_version": "17.6.1", "deadline": "2024-03-03"}`, team.ID, team.Name, team.ID, team.Name), 0)
|
||||
|
||||
s.assertAppleOSUpdatesDeclaration(&team.ID, mdm.FleetMacOSUpdatesProfileName, macOSUpdates)
|
||||
s.assertAppleOSUpdatesDeclaration(&team.ID, mdm.FleetIOSUpdatesProfileName, iOSUpdates)
|
||||
@@ -3376,16 +3386,16 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
|
||||
// Unchecking the UpdateNewHosts flag should register as an activity
|
||||
macOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("10.15.0"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2025-10-01"),
|
||||
UpdateNewHosts: optjson.SetBool(false),
|
||||
}
|
||||
iOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("11.11.11"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-02-02"),
|
||||
}
|
||||
iPadOSUpdates = &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.12.12"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-03-03"),
|
||||
}
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
@@ -3415,11 +3425,11 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
},
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "14.6.1", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2025-10-01", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, "11.11.11", tmResp.Team.Config.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "17.6.1", tmResp.Team.Config.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-02-02", tmResp.Team.Config.MDM.IOSUpdates.Deadline.Value)
|
||||
require.Equal(t, "12.12.12", tmResp.Team.Config.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "17.6.1", tmResp.Team.Config.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-03-03", tmResp.Team.Config.MDM.IPadOSUpdates.Deadline.Value)
|
||||
require.Equal(t, 10, tmResp.Team.Config.MDM.WindowsUpdates.DeadlineDays.Value)
|
||||
require.Equal(t, 2, tmResp.Team.Config.MDM.WindowsUpdates.GracePeriodDays.Value)
|
||||
@@ -3442,11 +3452,11 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
"macos_updates": nil,
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "14.6.1", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2025-10-01", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, "11.11.11", tmResp.Team.Config.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "17.6.1", tmResp.Team.Config.MDM.IOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-02-02", tmResp.Team.Config.MDM.IOSUpdates.Deadline.Value)
|
||||
require.Equal(t, "12.12.12", tmResp.Team.Config.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "17.6.1", tmResp.Team.Config.MDM.IPadOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-03-03", tmResp.Team.Config.MDM.IPadOSUpdates.Deadline.Value)
|
||||
// no new activity is created
|
||||
s.lastActivityMatches("", "", lastActivity)
|
||||
@@ -3463,7 +3473,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
},
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
require.Equal(t, "10.15.0", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "14.6.1", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2025-10-01", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
// no new activity is created
|
||||
s.lastActivityMatches("", "", lastActivity)
|
||||
@@ -3509,7 +3519,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"macos_updates": map[string]any{
|
||||
"minimum_version": "10.15.0",
|
||||
"minimum_version": "14.6.1",
|
||||
"deadline": "2021-01-01T00:00:00Z",
|
||||
},
|
||||
},
|
||||
@@ -3517,7 +3527,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"ios_updates": map[string]any{
|
||||
"minimum_version": "10.15.0",
|
||||
"minimum_version": "14.6.1",
|
||||
"deadline": "2021-01-01T00:00:00Z",
|
||||
},
|
||||
},
|
||||
@@ -3525,7 +3535,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"ipados_updates": map[string]any{
|
||||
"minimum_version": "10.15.0",
|
||||
"minimum_version": "14.6.1",
|
||||
"deadline": "2021-01-01T00:00:00Z",
|
||||
},
|
||||
},
|
||||
@@ -3535,7 +3545,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"macos_updates": map[string]any{
|
||||
"minimum_version": "10.15.0 (19A583)",
|
||||
"minimum_version": "14.6.1 (19A583)",
|
||||
"deadline": "2021-01-01T00:00:00Z",
|
||||
},
|
||||
},
|
||||
@@ -3543,7 +3553,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"ios_updates": map[string]any{
|
||||
"minimum_version": "10.15.0 (19A583)",
|
||||
"minimum_version": "14.6.1 (19A583)",
|
||||
"deadline": "2021-01-01T00:00:00Z",
|
||||
},
|
||||
},
|
||||
@@ -3551,7 +3561,7 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"ipados_updates": map[string]any{
|
||||
"minimum_version": "10.15.0 (19A583)",
|
||||
"minimum_version": "14.6.1 (19A583)",
|
||||
"deadline": "2021-01-01T00:00:00Z",
|
||||
},
|
||||
},
|
||||
@@ -3607,21 +3617,21 @@ func (s *integrationEnterpriseTestSuite) TestAppleOSUpdatesTeamConfig() {
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"macos_updates": map[string]any{
|
||||
"minimum_version": "10.15.0 (19A583)",
|
||||
"minimum_version": "14.6.1 (19A583)",
|
||||
},
|
||||
},
|
||||
}, http.StatusUnprocessableEntity, &tmResp)
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"ios_updates": map[string]any{
|
||||
"minimum_version": "10.15.0 (19A583)",
|
||||
"minimum_version": "14.6.1 (19A583)",
|
||||
},
|
||||
},
|
||||
}, http.StatusUnprocessableEntity, &tmResp)
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", team.ID), map[string]any{
|
||||
"mdm": map[string]any{
|
||||
"ipados_updates": map[string]any{
|
||||
"minimum_version": "10.15.0 (19A583)",
|
||||
"minimum_version": "14.6.1 (19A583)",
|
||||
},
|
||||
},
|
||||
}, http.StatusUnprocessableEntity, &tmResp)
|
||||
@@ -4363,6 +4373,9 @@ func (s *integrationEnterpriseTestSuite) TestMDMWindowsUpdates() {
|
||||
func (s *integrationEnterpriseTestSuite) TestMDMAppleOSUpdates() {
|
||||
t := s.T()
|
||||
|
||||
// Mock Apple GDMF API (required for validating OS update minimum version settings)
|
||||
mdmtest.StartNewAppleGDMFTestServer(t)
|
||||
|
||||
// keep the last activity, to detect newly created ones
|
||||
var activitiesResp listActivitiesResponse
|
||||
s.DoJSON("GET", "/api/latest/fleet/activities", nil, http.StatusOK, &activitiesResp, "order_key", "a.id", "order_direction", "desc")
|
||||
@@ -4489,64 +4502,64 @@ func (s *integrationEnterpriseTestSuite) TestMDMAppleOSUpdates() {
|
||||
s.DoJSON("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
|
||||
"mdm": {
|
||||
"macos_updates": {
|
||||
"minimum_version": "12.3.1",
|
||||
"minimum_version": "13.6.9",
|
||||
"deadline": "2022-01-01",
|
||||
"update_new_hosts": true
|
||||
},
|
||||
"ios_updates": {
|
||||
"minimum_version": "13.13.13",
|
||||
"minimum_version": "17.6",
|
||||
"deadline": "2023-03-03",
|
||||
"update_new_hosts": true
|
||||
},
|
||||
"ipados_updates": {
|
||||
"minimum_version": "14.14.14",
|
||||
"minimum_version": "17.6",
|
||||
"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, "13.6.9", 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, "17.6", 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, "17.6", 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, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), `{"deadline":"2023-03-03", "minimum_version":"13.13.13", "team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), `{"deadline":"2024-04-04", "minimum_version":"14.14.14", "team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(), `{"deadline":"2022-01-01", "minimum_version":"13.6.9", "team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), `{"deadline":"2023-03-03", "minimum_version":"17.6", "team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), `{"deadline":"2024-04-04", "minimum_version":"17.6", "team_id": null, "team_name": null, "fleet_id": null, "fleet_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"),
|
||||
MinimumVersion: optjson.SetString("13.6.9"), Deadline: optjson.SetString("2022-01-01"),
|
||||
})
|
||||
s.assertAppleOSUpdatesDeclaration(nil, mdm.FleetIOSUpdatesProfileName, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("13.13.13"), Deadline: optjson.SetString("2023-03-03"),
|
||||
MinimumVersion: optjson.SetString("17.6"), Deadline: optjson.SetString("2023-03-03"),
|
||||
})
|
||||
s.assertAppleOSUpdatesDeclaration(nil, mdm.FleetIPadOSUpdatesProfileName, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.14.14"), Deadline: optjson.SetString("2024-04-04"),
|
||||
MinimumVersion: optjson.SetString("17.6"), Deadline: optjson.SetString("2024-04-04"),
|
||||
})
|
||||
|
||||
// get the appconfig
|
||||
acResp = appConfigResponse{}
|
||||
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, "13.6.9", 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, "17.6", 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, "17.6", 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)
|
||||
|
||||
@@ -4555,63 +4568,63 @@ func (s *integrationEnterpriseTestSuite) TestMDMAppleOSUpdates() {
|
||||
s.DoJSON("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
|
||||
"mdm": {
|
||||
"macos_updates": {
|
||||
"minimum_version": "12.3.1",
|
||||
"minimum_version": "13.6.9",
|
||||
"deadline": "2024-01-01",
|
||||
"update_new_hosts": false
|
||||
},
|
||||
"ios_updates": {
|
||||
"minimum_version": "13.13.13",
|
||||
"minimum_version": "17.6",
|
||||
"deadline": "2025-05-05"
|
||||
},
|
||||
"ipados_updates": {
|
||||
"minimum_version": "14.14.14",
|
||||
"minimum_version": "17.6",
|
||||
"deadline": "2026-06-06"
|
||||
}
|
||||
}
|
||||
}`), http.StatusOK, &acResp)
|
||||
require.Equal(t, "12.3.1", acResp.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "13.6.9", 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, "17.6", 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, "17.6", 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, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), `{"deadline":"2025-05-05", "minimum_version":"13.13.13", "team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
lastActivity = s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), `{"deadline":"2026-06-06", "minimum_version":"14.14.14", "team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedMacOSMinVersion{}.ActivityName(), `{"deadline":"2024-01-01", "minimum_version":"13.6.9", "team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIOSMinVersion{}.ActivityName(), `{"deadline":"2025-05-05", "minimum_version":"17.6", "team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
lastActivity = s.lastActivityOfTypeMatches(fleet.ActivityTypeEditedIPadOSMinVersion{}.ActivityName(), `{"deadline":"2026-06-06", "minimum_version":"17.6", "team_id": null, "team_name": null, "fleet_id": null, "fleet_name": null}`, 0)
|
||||
s.assertAppleOSUpdatesDeclaration(nil, mdm.FleetMacOSUpdatesProfileName, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.3.1"), Deadline: optjson.SetString("2024-01-01"),
|
||||
MinimumVersion: optjson.SetString("13.6.9"), Deadline: optjson.SetString("2024-01-01"),
|
||||
})
|
||||
s.assertAppleOSUpdatesDeclaration(nil, mdm.FleetIOSUpdatesProfileName, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("13.13.13"), Deadline: optjson.SetString("2025-05-05"),
|
||||
MinimumVersion: optjson.SetString("17.6"), Deadline: optjson.SetString("2025-05-05"),
|
||||
})
|
||||
s.assertAppleOSUpdatesDeclaration(nil, mdm.FleetIPadOSUpdatesProfileName, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.14.14"), Deadline: optjson.SetString("2026-06-06"),
|
||||
MinimumVersion: optjson.SetString("17.6"), Deadline: optjson.SetString("2026-06-06"),
|
||||
})
|
||||
|
||||
// update something unrelated - the transparency url
|
||||
acResp = appConfigResponse{}
|
||||
s.DoJSON("PATCH", "/api/latest/fleet/config", json.RawMessage(`{"fleet_desktop":{"transparency_url": "customURL"}}`), http.StatusOK, &acResp)
|
||||
require.Equal(t, "12.3.1", acResp.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "13.6.9", acResp.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
require.Equal(t, "2024-01-01", acResp.MDM.MacOSUpdates.Deadline.Value)
|
||||
|
||||
// no activity got created
|
||||
s.lastActivityMatches("", ``, lastActivity)
|
||||
s.assertAppleOSUpdatesDeclaration(nil, mdm.FleetMacOSUpdatesProfileName, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("12.3.1"), Deadline: optjson.SetString("2024-01-01"),
|
||||
MinimumVersion: optjson.SetString("13.6.9"), Deadline: optjson.SetString("2024-01-01"),
|
||||
})
|
||||
s.assertAppleOSUpdatesDeclaration(nil, mdm.FleetIOSUpdatesProfileName, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("13.13.13"), Deadline: optjson.SetString("2025-05-05"),
|
||||
MinimumVersion: optjson.SetString("17.6"), Deadline: optjson.SetString("2025-05-05"),
|
||||
})
|
||||
s.assertAppleOSUpdatesDeclaration(nil, mdm.FleetIPadOSUpdatesProfileName, &fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.14.14"), Deadline: optjson.SetString("2026-06-06"),
|
||||
MinimumVersion: optjson.SetString("17.6"), Deadline: optjson.SetString("2026-06-06"),
|
||||
})
|
||||
|
||||
// clear the apple OS requirements
|
||||
|
||||
@@ -579,7 +579,7 @@ func (s *integrationMDMTestSuite) TestAppleProfileManagement() {
|
||||
"mdm": {
|
||||
"macos_updates": {
|
||||
"deadline": "2023-12-31",
|
||||
"minimum_version": "13.3.7"
|
||||
"minimum_version": "14.6.1"
|
||||
}
|
||||
}
|
||||
}`), http.StatusOK)
|
||||
@@ -587,7 +587,7 @@ func (s *integrationMDMTestSuite) TestAppleProfileManagement() {
|
||||
MDM: &fleet.TeamPayloadMDM{
|
||||
MacOSUpdates: &fleet.AppleOSUpdateSettings{
|
||||
Deadline: optjson.SetString("1992-01-01"),
|
||||
MinimumVersion: optjson.SetString("13.1.1"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
},
|
||||
},
|
||||
}, http.StatusOK)
|
||||
@@ -5275,7 +5275,7 @@ func (s *integrationMDMTestSuite) TestMDMBatchSetProfilesKeepsReservedNames() {
|
||||
},
|
||||
"macos_updates": {
|
||||
"deadline": "2023-12-31",
|
||||
"minimum_version": "13.3.7"
|
||||
"minimum_version": "14.6.1"
|
||||
}
|
||||
}
|
||||
}`), http.StatusOK, &acResp)
|
||||
@@ -5328,7 +5328,7 @@ func (s *integrationMDMTestSuite) TestMDMBatchSetProfilesKeepsReservedNames() {
|
||||
},
|
||||
MacOSUpdates: &fleet.AppleOSUpdateSettings{
|
||||
Deadline: optjson.SetString("2023-12-31"),
|
||||
MinimumVersion: optjson.SetString("13.3.8"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
UpdateNewHosts: optjson.SetBool(true),
|
||||
},
|
||||
},
|
||||
@@ -5340,7 +5340,7 @@ func (s *integrationMDMTestSuite) TestMDMBatchSetProfilesKeepsReservedNames() {
|
||||
require.Equal(t, 4, tmResp.Team.Config.MDM.WindowsUpdates.DeadlineDays.Value)
|
||||
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, "14.6.1", 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))
|
||||
@@ -8814,15 +8814,15 @@ func (s *integrationMDMTestSuite) TestSpecTeamsOSUpdatesDeployToHosts() {
|
||||
Name: teamName,
|
||||
MDM: fleet.TeamSpecMDM{
|
||||
MacOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("14.1.0"),
|
||||
MinimumVersion: optjson.SetString("14.6.1"),
|
||||
Deadline: optjson.SetString("2024-03-01"),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.1.0"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-03-01"),
|
||||
},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.1.0"),
|
||||
MinimumVersion: optjson.SetString("17.6.1"),
|
||||
Deadline: optjson.SetString("2024-03-01"),
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
@@ -8878,11 +8878,11 @@ func (s *integrationMDMTestSuite) TestSpecTeamsOSUpdatesDeployToHosts() {
|
||||
Deadline: optjson.SetString("2025-06-01"),
|
||||
},
|
||||
IOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.3.0"),
|
||||
MinimumVersion: optjson.SetString("16.7.2"),
|
||||
Deadline: optjson.SetString("2025-06-01"),
|
||||
},
|
||||
IPadOSUpdates: fleet.AppleOSUpdateSettings{
|
||||
MinimumVersion: optjson.SetString("17.3.0"),
|
||||
MinimumVersion: optjson.SetString("16.7.2"),
|
||||
Deadline: optjson.SetString("2025-06-01"),
|
||||
},
|
||||
WindowsUpdates: fleet.WindowsUpdates{
|
||||
|
||||
@@ -709,8 +709,8 @@ func (s *integrationMDMTestSuite) SetupSuite() {
|
||||
_, err = w.Write(b)
|
||||
require.NoError(s.T(), err)
|
||||
}))
|
||||
dev_mode.SetOverride("FLEET_DEV_GDMF_URL", s.appleGDMFSrv.URL, s.T())
|
||||
|
||||
s.T().Setenv("FLEET_DEV_GDMF_URL", s.appleGDMFSrv.URL)
|
||||
s.T().Setenv("TEST_FLEETDM_API_URL", fleetdmSrv.URL)
|
||||
s.T().Setenv("FLEET_DEV_STOKEN_AUTHENTICATED_APPS_URL", s.appleVPPProxySrv.URL)
|
||||
|
||||
@@ -7950,7 +7950,7 @@ func (s *integrationMDMTestSuite) TestOrbitConfigNudgeSettings() {
|
||||
mdm:
|
||||
macos_updates:
|
||||
deadline: 2022-01-04
|
||||
minimum_version: 12.1.3
|
||||
minimum_version: 14.6.1
|
||||
`))
|
||||
|
||||
// still empty if MDM is turned off for the host
|
||||
@@ -7971,7 +7971,7 @@ func (s *integrationMDMTestSuite) TestOrbitConfigNudgeSettings() {
|
||||
|
||||
resp = orbitGetConfigResponse{}
|
||||
s.DoJSON("POST", "/api/fleet/orbit/config", json.RawMessage(fmt.Sprintf(`{"orbit_node_key": %q}`, *h.OrbitNodeKey)), http.StatusOK, &resp)
|
||||
wantCfg, err := fleet.NewNudgeConfig(fleet.AppleOSUpdateSettings{Deadline: optjson.SetString("2022-01-04"), MinimumVersion: optjson.SetString("12.1.3")})
|
||||
wantCfg, err := fleet.NewNudgeConfig(fleet.AppleOSUpdateSettings{Deadline: optjson.SetString("2022-01-04"), MinimumVersion: optjson.SetString("14.6.1")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, wantCfg, resp.NudgeConfig)
|
||||
require.Equal(t, wantCfg.OSVersionRequirements[0].RequiredInstallationDate.String(), "2022-01-04 20:00:00 +0000 UTC")
|
||||
@@ -8001,7 +8001,7 @@ func (s *integrationMDMTestSuite) TestOrbitConfigNudgeSettings() {
|
||||
MDM: &fleet.TeamPayloadMDM{
|
||||
MacOSUpdates: &fleet.AppleOSUpdateSettings{
|
||||
Deadline: optjson.SetString("1992-01-01"),
|
||||
MinimumVersion: optjson.SetString("13.1.1"),
|
||||
MinimumVersion: optjson.SetString("13.6.9"),
|
||||
},
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
@@ -8009,7 +8009,7 @@ func (s *integrationMDMTestSuite) TestOrbitConfigNudgeSettings() {
|
||||
|
||||
resp = orbitGetConfigResponse{}
|
||||
s.DoJSON("POST", "/api/fleet/orbit/config", json.RawMessage(fmt.Sprintf(`{"orbit_node_key": %q}`, *h.OrbitNodeKey)), http.StatusOK, &resp)
|
||||
wantCfg, err = fleet.NewNudgeConfig(fleet.AppleOSUpdateSettings{Deadline: optjson.SetString("1992-01-01"), MinimumVersion: optjson.SetString("13.1.1")})
|
||||
wantCfg, err = fleet.NewNudgeConfig(fleet.AppleOSUpdateSettings{Deadline: optjson.SetString("1992-01-01"), MinimumVersion: optjson.SetString("13.6.9")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, wantCfg, resp.NudgeConfig)
|
||||
require.Equal(t, wantCfg.OSVersionRequirements[0].RequiredInstallationDate.String(), "1992-01-01 20:00:00 +0000 UTC")
|
||||
@@ -8031,7 +8031,7 @@ func (s *integrationMDMTestSuite) TestOrbitConfigNudgeSettings() {
|
||||
|
||||
resp = orbitGetConfigResponse{}
|
||||
s.DoJSON("POST", "/api/fleet/orbit/config", json.RawMessage(fmt.Sprintf(`{"orbit_node_key": %q}`, *h2.OrbitNodeKey)), http.StatusOK, &resp)
|
||||
wantCfg, err = fleet.NewNudgeConfig(fleet.AppleOSUpdateSettings{Deadline: optjson.SetString("2022-01-04"), MinimumVersion: optjson.SetString("12.1.3")})
|
||||
wantCfg, err = fleet.NewNudgeConfig(fleet.AppleOSUpdateSettings{Deadline: optjson.SetString("2022-01-04"), MinimumVersion: optjson.SetString("14.6.1")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, wantCfg, resp.NudgeConfig)
|
||||
require.Equal(t, wantCfg.OSVersionRequirements[0].RequiredInstallationDate.String(), "2022-01-04 20:00:00 +0000 UTC")
|
||||
|
||||
Reference in New Issue
Block a user