Converting AD Mobile Accounts to Local

lisacherie
Contributor II

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;
58 REPLIES 58

leslie
Contributor II
Contributor II

Just updated mobile_to_local to be universal. Tested (albeit minimally) on Big Sur with no issues. If you get a chance to test let me know how it goes/have any suggestions.

Can this be run silently?  Our goal would be to use it without user interaction.

Yes. Something like the following will run silently.

sudo /path/to/Mobile\ to\ Local.app/Contents/MacOS/Mobile\ to\ Local -mode silent

Worked perfect!  The only issue we encountered is that it didn't unbind the machine but we'll use another script for that for now until we can figure out what is up.

Below is what we used:

sudo /Applications/Utilities/Mobile\ to\ Local.app/Contents/MacOS/Mobile\ to\ Local -unbind true -mode silent

-allowNewUsername: whether or not to allow the user to change their current shortname. Either true of false.
-userType: type of account to migrate to. Either standard or admin.
-unbind: whether or not to unbind after migrating. Either true or false.
-mode: whether or not to prompt the user for input. If mode is silent the user will not be prompted for input.

leslie
Contributor II
Contributor II

Just noticed you did use the -unbind.  I'll have to look into that.

Let me know what if anything I can do to help.  We got huge kudos for the effectiveness of this.

Heavy_D
Contributor III

Is this the BIG-RAT still working?

I just tried using it, as we been tasked to convert our fleet to local profiles and non bind (YAY!) and it still shows as a mobile profile in preferences and will no longer give me the checkbox to change the name either is this working at all on 12.5?

lisacherie
Contributor II

I wouldn't know if this still works, and from the recent posts sounds like it's not. The work was originally done back in 2016, and it's been many years since I have worked on an AD environment, along with a number of OS changes since then.

If you manage to make changes to the code to get it to work again, I'm sure others will be appreciative to you. I have no environment to test or continue development.

leslie
Contributor II
Contributor II

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.

Heavy_D
Contributor III
sudo /Applications/Utilities/Mobile\ to\ Local.app/Contents/MacOS/Mobile\ to\ Local -unbind true -mode silent -userType admin -allowNewUsernamwe true

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.

Heavy_D
Contributor III

 

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

 

 

duplicate post. sorry

Heavy_D
Contributor III

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.

Heavy_D
Contributor III

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.

Heavy_D
Contributor III

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?

Heavy_D
Contributor III

@leslie  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.