mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
check for DEP capable migration before showing automatic preview (#41274)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #39252 I couldn't find any other code path that would resolve to automatic other than the device not being MDM enrolled, and we naively assumed 3 lines for manual migration, so I added the new IsDEPCapable method which checks if the first line returned by profiles status is No or Yes, to check if the device was enrolled via ABM/DEP, if not and not MDM enrolled then show the manual. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ## fleetd/orbit/Fleet Desktop - [x] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [x] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes - [x] Verified that fleetd runs on macOS, Linux and Windows - [x] Verified auto-update works from the released version of component to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))
This commit is contained in:
parent
bae3f022e2
commit
4149c22ae4
4 changed files with 56 additions and 13 deletions
1
orbit/changes/39252-manual-migration-if-not-dep-capable
Normal file
1
orbit/changes/39252-manual-migration-if-not-dep-capable
Normal file
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in a new issue