Skip to main content

With the increasing trend to stop binding macs to AD, I put together a script to demote mobile accounts to local.

To re-iterate - this one is risky. Please test it carefully if you decide to try it out.

If you find additional attributes that your fleet needed - would be interested to hear.

#!/usr/bin/perl -w

#  mobiletolocal.sh
#  Created by LD
#  Appears safe to run whilst logged in - user keeps existing password :)

my $userlist = `dscl . list /Users`;

chomp $userlist;

my @excludedusers = split(" ","root daemon nobody _amavisd _appleevents _appowner _appserver _ard _assetcache _astris _atsserver _avbdeviced _calendar _ces _clamav _coreaudiod _coremediaiod _cvmsroot _cvs _cyrus _devdocs _devicemgr _displaypolicyd _distnote _dovecot _dovenull _dpaudio _eppc _ftp _gamecontrollerd _geod _iconservices _installassistant _installer _jabber _kadmin_admin _kadmin_changepw _krb_anonymous _krb_changepw _krb_kadmin _krb_kerberos _krb_krbtgt _krbfast _krbtgt _launchservicesd _lda _locationd _lp _mailman _mbsetupuser _mcxalr _mdnsresponder _mysql _netbios _netstatistics _networkd _nsurlsessiond _nsurlstoraged _ondemand _postfix _postgres _qtss _sandbox _screensaver _scsd _securityagent _serialnumberd _softwareupdate _spotlight _sshd _svn _taskgated _teamsserver _timezone _tokend _trustevaluationagent _unknown _update_sharing _usbmuxd _uucp _warmd _webauthserver _windowserver _www _wwwproxy _xserverdocs");

my @userslist = split("
", $userlist);
my @users;
my $result = "";

foreach my $u (@userslist) {

   my $match = 0;

   foreach my $e (@excludedusers) {
      if ("$u" eq "$e") {
         $match = 1;
      }
   }

   if ($match == 0) {
      push(@users, $u);
    }
}

my $dsconfigad = `/usr/sbin/dsconfigad -show`;
chomp $dsconfigad;

unless ($dsconfigad eq "") {
   printf "Removing AD bind
";
   system "/usr/sbin/dsconfigad -remove -force -u none -p none";
}

foreach my $username (@users) {

   printf "Username is: $username
";
   my $accounttype = `/usr/bin/dscl . -read /Users/$username OriginalNodeName`;

   unless ($accounttype =~ //Active Directory//) {
       printf "Next: $username is not a mobile account
";
       next;
   }

   printf "$username has an AD mobile account - converting to local
";

   #Get Hash of existing password

   my $shadowhash = `/usr/bin/dscl . -read /Users/$username AuthenticationAuthority | grep " ;ShadowHash;HASHLIST:<"`;
   chomp $shadowhash;

   #printf "AuthenticationAuthority is: $shadowhash
";

   system "/usr/bin/dscl . -delete /users/$username cached_groups";
   system "/usr/bin/dscl . -delete /users/$username SMBPrimaryGroupSID";
   system "/usr/bin/dscl . -delete /users/$username OriginalAuthenticationAuthority";
   system "/usr/bin/dscl . -delete /users/$username OriginalNodeName";
   system "/usr/bin/dscl . -delete /users/$username AuthenticationAuthority";
   system "/usr/bin/dscl . -create /users/$username AuthenticationAuthority '$shadowhash'";
   system "/usr/bin/dscl . -delete /users/$username SMBSID";
   system "/usr/bin/dscl . -delete /users/$username SMBScriptPath";
   system "/usr/bin/dscl . -delete /users/$username SMBPasswordLastSet";
   system "/usr/bin/dscl . -delete /users/$username SMBGroupRID";
   system "/usr/bin/dscl . -delete /users/$username PrimaryNTDomain";
   system "/usr/bin/dscl . -delete /users/$username AppleMetaRecordName";
   system "/usr/bin/dscl . -delete /users/$username PrimaryNTDomain";
   system "/usr/bin/dscl . -delete /users/$username MCXSettings";
   system "/usr/bin/dscl . -delete /users/$username MCXFlags";
   system "/usr/bin/dscl . -delete /users/$username AppleMetaRecordName";
   system "/usr/bin/dscl . -delete /users/$username dsAttrTypeNative:cached_auth_policy";
   system "/usr/bin/dscl . -delete /Users/$username dsAttrTypeStandard:CopyTimestamp";
   system "/usr/sbin/dseditgroup -o edit -a $username -t user admin";

}

exit 0;

Worked on my test machine, macOS 12.5.1.  My AD environment is a bit dated though, 2012, not sure if that's a factor.

Updated the logging, now logs to /var/log/mobile.to.local.log.  Reviewing that may shed some light on what's (or what's not) going on.  How did you launch the app, what switches.


I've confirmed the Big-RAT solution is working on 12.5.1

https://github.com/BIG-RAT/mobile_to_local 

- Put the latest app version in /private/var/tmp, used composer to package the app.
- Created a Jamf policy, add the app package, and added the following command (with switches) to "Files and Processes" payload.
        - sudo /private/var/tmp/Mobile\\ to\\ Local.app/Contents/MacOS/Mobile\\ to\\ Local -mode silent -userType standard -unbind true; sleep 10; cat /private/var/log/mobile.to.local.log; sleep 5; rm -rf /private/var/tmp/Mobile\\ to\\ Local.app; sleep 3; rm -rf /private/var/log/mobile.to.local.log

Account switched from "mobile" to "standard".  No issues with account password, user was still FileVault enabled and the policy was ran while logged into the users account.

One thing I did notice is the Mobile to Local app window pops up for like 3 seconds, then goes away even though I had the "mode" switch set to "silent".  Not sure if thats is expected or not.


I've confirmed the Big-RAT solution is working on 12.5.1

https://github.com/BIG-RAT/mobile_to_local 

- Put the latest app version in /private/var/tmp, used composer to package the app.
- Created a Jamf policy, add the app package, and added the following command (with switches) to "Files and Processes" payload.
        - sudo /private/var/tmp/Mobile\\ to\\ Local.app/Contents/MacOS/Mobile\\ to\\ Local -mode silent -userType standard -unbind true; sleep 10; cat /private/var/log/mobile.to.local.log; sleep 5; rm -rf /private/var/tmp/Mobile\\ to\\ Local.app; sleep 3; rm -rf /private/var/log/mobile.to.local.log

Account switched from "mobile" to "standard".  No issues with account password, user was still FileVault enabled and the policy was ran while logged into the users account.

One thing I did notice is the Mobile to Local app window pops up for like 3 seconds, then goes away even though I had the "mode" switch set to "silent".  Not sure if thats is expected or not.


 

Getting the following when running it with your payload.

 

Running command sudo /Applications/Utilities/Mobile\\ to\\ Local.app/Contents/MacOS/Mobile\\ to\\ Local -mode silent -userType standard -unbind true; sleep 10; cat /private/var/log/mobile.to.local.log; sleep 5; rm -rf /Applications/Utilities/Mobile\\ to\\ Local.app sleep 3; rm -rf /private/var/log/mobile.to.local.log... Result of command: /bin/sh: - : invalid option Usage: /bin/sh [GNU long option] [option] ... /bin/sh [GNU long option] [option] script-file ... GNU long options: --debug --debugger --dump-po-strings --dump-strings --help --init-file --login --noediting --noprofile --norc --posix --protected --rcfile --restricted --verbose --version --wordexp Shell options: -irsD or -c command or -O shopt_option (invocation only) -abefhkmnptuvxBCHP or -o option

 

 


Nevermind I got to work but is there a way to add a script "After" to turn the logged in user into a Standard user into an Admin?

#!/bin/bash while read useraccount; do /usr/sbin/dseditgroup -o edit -a $useraccount -t user admin done < <(dscl . list /Users UniqueID | awk '$2 >= 1000 {print $1}')

But it doesn't seem to work.


Nevermind it required a Restart. All is well in the shire.

Thank You.


Nevermind it required a Restart. All is well in the shire.

Thank You.


Good to hear.  You can also set the migrated user as an admin by using:

-userType admin

If your goal is to make all users admins your script should be fine.


I've confirmed the Big-RAT solution is working on 12.5.1

https://github.com/BIG-RAT/mobile_to_local 

- Put the latest app version in /private/var/tmp, used composer to package the app.
- Created a Jamf policy, add the app package, and added the following command (with switches) to "Files and Processes" payload.
        - sudo /private/var/tmp/Mobile\\ to\\ Local.app/Contents/MacOS/Mobile\\ to\\ Local -mode silent -userType standard -unbind true; sleep 10; cat /private/var/log/mobile.to.local.log; sleep 5; rm -rf /private/var/tmp/Mobile\\ to\\ Local.app; sleep 3; rm -rf /private/var/log/mobile.to.local.log

Account switched from "mobile" to "standard".  No issues with account password, user was still FileVault enabled and the policy was ran while logged into the users account.

One thing I did notice is the Mobile to Local app window pops up for like 3 seconds, then goes away even though I had the "mode" switch set to "silent".  Not sure if thats is expected or not.


duplicate post. sorry


Last time I tried to do this it did not work but I will try again with that switch also if I didn't want the mode to be silent what other switch can be used and what would it look like on the users end?


@leslie_h  Do you know or have you encountered an issue where the account was migrated successfully, you restart and login with no issues but when trying to change the password is completely locks you out of the machine and nothing works. Trying to reset the password via Recovery and there are no accounts present on the drive. This is an M1 mac.