diff --git a/orbit/changes/39252-manual-migration-if-not-dep-capable b/orbit/changes/39252-manual-migration-if-not-dep-capable new file mode 100644 index 0000000000..b2d8fc9193 --- /dev/null +++ b/orbit/changes/39252-manual-migration-if-not-dep-capable @@ -0,0 +1 @@ +* Fixed an issue where the automatic migration preview would show when the device was not MDM-enrolled and not enrolled via DEP. \ No newline at end of file diff --git a/orbit/pkg/profiles/profiles_darwin.go b/orbit/pkg/profiles/profiles_darwin.go index 8cdd08d823..4832dbdd61 100644 --- a/orbit/pkg/profiles/profiles_darwin.go +++ b/orbit/pkg/profiles/profiles_darwin.go @@ -127,7 +127,10 @@ func IsEnrolledInMDM() (bool, string, error) { return true, enrollmentURL, nil } -func IsManuallyEnrolledInMDM() (bool, error) { +// ParseMDMEnrollmentStatus runs the `profiles` command to get the current MDM +// enrollment information and reports if the host is enrolled via DEP or not. +// Which is used to check for manual enrollment or not. +func ParseMDMEnrollmentStatus() (enrolledViaDEP bool, err error) { out, err := getMDMInfoFromProfilesCmd() if err != nil { return false, fmt.Errorf("calling /usr/bin/profiles: %w", err) @@ -141,21 +144,21 @@ func IsManuallyEnrolledInMDM() (bool, error) { // MDM server: https://test.example.com/mdm/apple/mdm // ``` // - // If the host is not enrolled into an MDM, the last line is ommitted, + // If the host is not enrolled into an MDM, the last line is omitted, // so we need to check that: // - // 1. We've got three rows - // 2. Whether the first line contains "Yes" or "No" + // 1. We've got two rows + // 2. The first row contains "Yes" or "No" lines := bytes.Split(bytes.TrimSpace(out), []byte("\n")) - if len(lines) < 3 { - return false, nil + if len(lines) < 2 { + return false, fmt.Errorf("Got %d lines of output, when expected at least 2 or more", len(lines)) } if strings.Contains(string(lines[0]), "Yes") { - return false, nil + return true, nil } - return true, nil + return false, nil } // getMDMInfoFromProfilesCmd is declared as a variable so it can be overwritten by tests. diff --git a/orbit/pkg/profiles/profiles_darwin_test.go b/orbit/pkg/profiles/profiles_darwin_test.go index 1f4cf91a55..81192ea4f8 100644 --- a/orbit/pkg/profiles/profiles_darwin_test.go +++ b/orbit/pkg/profiles/profiles_darwin_test.go @@ -327,6 +327,45 @@ MDM server: https://valid.com/mdm/apple/mdm } } +func TestParseMDMEnrollmentStatus(t *testing.T) { + cases := []struct { + cmdOut *string + cmdErr error + want bool + wantErr bool + }{ + {nil, errors.New("test error"), false, true}, + {ptr.String(""), nil, false, true}, + {ptr.String("Enrolled via DEP: No\nMDM Enrollment: No"), nil, false, false}, + {ptr.String("Enrolled via DEP: Yes\nMDM Enrollment: No"), nil, true, false}, + {ptr.String("Enrolled via DEP: No\nMDM Enrollment: Yes (User Approved)"), nil, false, false}, + {ptr.String("Enrolled via DEP: No\nMDM Enrollment: Yes (User Approved)\nMDM Server: https://mdm.example.com"), nil, false, false}, + {ptr.String("Enrolled via DEP: Yes\nMDM Enrollment: Yes\nMDM Server: https://mdm.example.com"), nil, true, false}, + } + + origCmd := getMDMInfoFromProfilesCmd + t.Cleanup(func() { getMDMInfoFromProfilesCmd = origCmd }) + for _, c := range cases { + getMDMInfoFromProfilesCmd = func() ([]byte, error) { + if c.cmdOut == nil { + return nil, c.cmdErr + } + + var buf bytes.Buffer + buf.WriteString(*c.cmdOut) + return buf.Bytes(), nil + } + + got, err := ParseMDMEnrollmentStatus() + if c.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + require.Equal(t, c.want, got) + } +} + func TestCheckAssignedEnrollmentProfile(t *testing.T) { fleetURL := "https://valid.com" cases := []struct { diff --git a/orbit/pkg/useraction/mdm_migration_darwin.go b/orbit/pkg/useraction/mdm_migration_darwin.go index ad2fd40fe8..c4e487419d 100644 --- a/orbit/pkg/useraction/mdm_migration_darwin.go +++ b/orbit/pkg/useraction/mdm_migration_darwin.go @@ -406,7 +406,7 @@ func (m *swiftDialogMDMMigrator) waitForUnenrollment(isADEMigration bool) error func (m *swiftDialogMDMMigrator) renderMigration() error { log.Debug().Msg("checking current enrollment status") - isCurrentlyManuallyEnrolled, err := profiles.IsManuallyEnrolledInMDM() + enrolledViaDEP, err := profiles.ParseMDMEnrollmentStatus() if err != nil { return err } @@ -418,10 +418,10 @@ func (m *swiftDialogMDMMigrator) renderMigration() error { return fmt.Errorf("getting migration type: %w", err) } - isManualMigration := isCurrentlyManuallyEnrolled || previousMigrationType == constant.MDMMigrationTypeManual + isManualMigration := !enrolledViaDEP || previousMigrationType == constant.MDMMigrationTypeManual isADEMigration := previousMigrationType == constant.MDMMigrationTypeADE - log.Debug().Bool("isManualMigration", isManualMigration).Bool("isADEMigration", isADEMigration).Bool("isCurrentlyManuallyEnrolled", isCurrentlyManuallyEnrolled).Str("previousMigrationType", previousMigrationType).Msg("props after assigning") + log.Debug().Bool("isManualMigration", isManualMigration).Bool("isADEMigration", isADEMigration).Bool("enrolledViaDEP", enrolledViaDEP).Str("previousMigrationType", previousMigrationType).Msg("props after assigning") vers, err := m.getMacOSMajorVersion() if err != nil { @@ -465,7 +465,7 @@ func (m *swiftDialogMDMMigrator) renderMigration() error { if !m.props.IsUnmanaged { // show the loading spinner - m.renderLoadingSpinner(isPreSonoma, isCurrentlyManuallyEnrolled) + m.renderLoadingSpinner(isPreSonoma, isManualMigration) // send the API call if notifyErr := m.handler.NotifyRemote(); notifyErr != nil { @@ -498,7 +498,7 @@ func (m *swiftDialogMDMMigrator) renderMigration() error { switch { case isPreSonoma: if err := m.mrw.SetMigrationFile(constant.MDMMigrationTypePreSonoma); err != nil { - log.Error().Str("migration_type", constant.MDMMigrationTypeADE).Err(err).Msg("set migration file") + log.Error().Str("migration_type", constant.MDMMigrationTypePreSonoma).Err(err).Msg("set migration file") } log.Info().Msg("showing instructions after pre-sonoma unenrollment")