Posted on 12-17-2016 10:32 AM
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;
Posted on 12-17-2016 10:33 AM
There were a couple of people who helped me with this. Not sure whether to publicly call them out - who gave advice on how to deploy it. I was scared. Who also helped with figuring out which attributes needed modification.
Posted on 12-19-2016 11:52 AM
Does this also work with OpenLDAP?
Posted on 12-19-2016 05:12 PM
You could possibly use the same approach - though I suspect some of the attributes to change will be different.
Compare dscl output against user accounts.
Posted on 12-21-2016 09:52 AM
@rtrouton Has worked his magic, and made an interactive version with some extra features.
https://derflounder.wordpress.com/2016/12/21/migrating-ad-mobile-accounts-to-local-user-accounts/
Posted on 12-21-2016 09:54 AM
Nice! Thank you both!
Posted on 01-05-2017 03:20 PM
@lisacherie THANK YOU! This is a huge life saver for me. Deployed it to a our test group of Enterprise Connect users (all logged in and using their systems) and had zero issues. Will continue using it as we migrate more folks to Enterprise Connect.
Posted on 07-31-2017 03:38 PM
@perrinbw are you deploying the script via jamf? if so, how do you get the terminal to pop up so i can choose the options?
Thanks
Posted on 07-31-2017 07:05 PM
@ant89 There are two versions of the script.
The version I shared does not require interaction, or Rich's version does. Try out each and see which method you prefer. The silent version suited the workflow I had as the process was invisible and non disruptive to end users.
Please test it out before trying - each AD is a bit different and there are macOS dot releases since then.
Posted on 08-01-2017 09:52 AM
@lisacherie thank you! the script you provided works in our environment. QQ - Anyway to determine which laptops have mobile accounts? I've created an EA that looks for accounts that have a UID over 1000. but your script does not change the UID. If this script was ran, i have no way of determining if it is still a mobile account or not. Any ideas?
Posted on 08-01-2017 10:21 AM
@ant89 try using this to determine which Macs need to be in scope.
https://www.jamf.com/jamf-nation/discussions/22292/mobile-and-local-accounts
Posted on 08-01-2017 10:22 AM
-
Posted on 08-01-2017 11:31 AM
@lisacherie awsome. thank you!
Posted on 11-21-2017 02:01 PM
Just started testing this myself - first test was perfect, so that's very encouraging. Thank you @lisacherie !
Posted on 03-08-2018 08:26 PM
So, this is probably going to sound dumb, but has anyone used this with High Sierra? With Apple Script editor it is not running and having issues. Most of this is over my head, but I would love to test this out! Any pointers would be great!
Posted on 03-09-2018 09:42 AM
It did work with early builds of High Sierra - but you will need to test to ensure there are no differences with your environment and it still works with the current builds.
To run the script you need to use terminal and the following command:
sudo ./scriptname.sh
Good luck - hope it works out for you.
Posted on 03-27-2018 12:29 PM
@lisacherie has anyone gotten this or @rtrouton 's version of the script to work using JAMF Helper's Prompt Message feature? It would be nice to deploy this to machines that need AD accounts converted to local that are provisioned with DEP. Thus preventing future keychain and FV2 password sync problems.
Posted on 03-27-2018 12:35 PM
The version I wrote was designed to run silently and convert all accounts in one policy run, regardless of whether the user is active at the time. This is a sanitized version some specific lines to that environment were removed, however this version also worked.
I used it successfully with my previous employer, however each AD is different, and there are many OS updates since then, so please test before deployment.
Posted on 03-27-2018 12:46 PM
Thank you @lisacherie I am rebuilding a machine to test the script on now.
Posted on 06-08-2018 07:50 AM
@lisacherie I was able to use the script to unbind a mac and convert the account from a mobile account to a local account, however I've noticed that I cannot change the password on the local account now. Have you seen this behaviour before?
Posted on 06-20-2018 09:29 AM
@rtrouton has updated the version of this he wrote. Please take care to obtain the new version: https://derflounder.wordpress.com/2018/06/16/updated-migrateadmobileaccounttolocalaccount-script-now...
Note the perl version is using a string within a string for the “system” function to execute the dscl command rather than as a command in bash.
At first look the perl version may not be impacted due to the way strings are handled/quoted.
More testing is needed to confirm.
Posted on 01-07-2019 04:51 PM
I also had success with this code. It prompts for a desired user to convert via calling a system event. Then if it's not an AD account, it exits. If so, it follows the steps that @lisacherie outlines above. No unbinding from AD in this script. I decided to call that separately so that I can unbind with AD credentials and do these separately as needed. Here's that script:
#!/bin/bash
#Freddie Cox for Knox County Schools
#Edited by Justin Ellis
#Arranged by Ethan Delavan for Jamf environment
#2012
#
#Ask user for the target user to convert
netname=`/usr/bin/osascript <<EOT
tell application "System Events"
activate
set netname to text returned of (display dialog "Please Input Target User Name" default answer "first.last" with icon 1)
end tell
EOT`
#Test to see if the target account is currently logged in.
if [[ "$netname" = `python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "
");'` ]]; then
#Exit if target user is currently logged in
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "$netname is logged in, and we shouldn't mess with it now. Log in as admin and try again." with icon 2 buttons {"Cancel"} default button 1 with hidden answer
end tell
EOT
exit 1
fi
accounttype=`/usr/bin/dscl . -read /Users/"$netname" AuthenticationAuthority | head -2 | awk -F'/' '{print $2}' | tr -d '
'`
if [[ "$accounttype" = "Active Directory" ]]; then
mobileusercheck=`/usr/bin/dscl . -read /Users/"$netname" AuthenticationAuthority | head -2 | awk -F'/' '{print $1}' | tr -d '
' | sed 's/^[^:]*: //' | sed s/;/""/g`
if [[ "$mobileusercheck" = "LocalCachedUser" ]]; then
#/usr/bin/printf "$netname has an AD mobile account.
Converting to a local account with the same username and UID.
"
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "$netname is a Local Cached User via AD. Click to begin conversion" with icon 1 buttons {"Continue"} default button 1 with hidden answer
end tell
EOT
else
#/usr/bin/printf "The $netname account is not a AD mobile account
"
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "The $netname account is not a Local Cashed User." with icon 2 buttons {"Cancel"} default button 1 with hidden answer
end tell
EOT
exit 1
fi
else
#/usr/bin/printf "The $netname account is not a AD mobile account
"
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "The $netname account is not an Active Directory account." with icon 2 buttons {"Cancel"} default button 1 with hidden answer
end tell
EOT
exit 1
fi
#Now do the deeds
# Preserve the account password by backing up password hash
shadowhash=$(/usr/bin/dscl -plist . -read /Users/$netname AuthenticationAuthority | xmllint --xpath 'string(//string[contains(text(),"ShadowHash")])' -)
# Remove the account attributes that identify it as an Active Directory mobile account
/usr/bin/dscl . -delete /users/$netname cached_groups
/usr/bin/dscl . -delete /users/$netname cached_auth_policy
/usr/bin/dscl . -delete /users/$netname CopyTimestamp
/usr/bin/dscl . -delete /users/$netname AltSecurityIdentities
/usr/bin/dscl . -delete /users/$netname SMBPrimaryGroupSID
/usr/bin/dscl . -delete /users/$netname OriginalAuthenticationAuthority
/usr/bin/dscl . -delete /users/$netname OriginalNodeName
/usr/bin/dscl . -delete /users/$netname AuthenticationAuthority
/usr/bin/dscl . -create /users/$netname AuthenticationAuthority "${shadowhash}"
/usr/bin/dscl . -delete /users/$netname SMBSID
/usr/bin/dscl . -delete /users/$netname SMBScriptPath
/usr/bin/dscl . -delete /users/$netname SMBPasswordLastSet
/usr/bin/dscl . -delete /users/$netname SMBGroupRID
/usr/bin/dscl . -delete /users/$netname PrimaryNTDomain
/usr/bin/dscl . -delete /users/$netname AppleMetaRecordName
/usr/bin/dscl . -delete /users/$netname PrimaryNTDomain
/usr/bin/dscl . -delete /users/$netname MCXSettings
/usr/bin/dscl . -delete /users/$netname MCXFlags
# Refresh Directory Services
if [[ ${osvers} -ge 7 ]]; then
/usr/bin/killall opendirectoryd
else
/usr/bin/killall DirectoryService
fi
#Pause
sleep 20
#Test for success
accounttype=`/usr/bin/dscl . -read /Users/"$netname" AuthenticationAuthority | head -2 | awk -F'/' '{print $2}' | tr -d '
'`
if [[ "$accounttype" = "Active Directory" ]]; then
/usr/bin/printf "Something went wrong with the conversion process.
The $netname account is still an AD mobile account.
"
/usr/bin/osascript <<EOT
tell application "System Events"
activate
display dialog "Something went wrong with the conversion process. The $netname account is still an AD mobile account." with icon 2 buttons {"Cancel"} default button 1 with hidden answer
end tell
EOT
exit 1
else
/usr/bin/printf "Conversion process was successful.
The $netname account is now a local account.
"
fi
#Update home folder permissions
homedir=`/usr/bin/dscl . -read /Users/"$netname" NFSHomeDirectory | awk '{print $2}'`
if [[ "$homedir" != "" ]]; then
/bin/echo "Home directory location: $homedir"
/bin/echo "Updating home folder permissions for the $netname account"
/usr/sbin/chown -R "$netname" "$homedir"
fi
# Add user to the staff group on the Mac
/bin/echo "Adding $netname to the staff group on this Mac."
/usr/sbin/dseditgroup -o edit -a "$netname" -t user staff
#Echo user info
/bin/echo "Displaying user and group information for the $netname account"
/usr/bin/id $netname
exit 0
Posted on 01-08-2019 07:25 AM
Thanks for sharing your script too.
The script in the OP still works last tried 10.13.6 if looking for a silent way to convert all accounts via policy on the Mac in one go.
If wanting to keep the AD bind - can comment out the few rows which remove it.
Posted on 01-10-2019 01:18 PM
@ethan.delavan Does your script with work with Macs that are on Mojave?
Posted on 01-10-2019 11:59 PM
For Mojave you can also use nomad login if script above is not working
Posted on 06-21-2019 12:25 PM
This doesn't work for mobile Open Ldap accounts. I get "The user is not an AD user" error. Any chance this could work with not just AD?
Posted on 06-23-2019 04:46 PM
@CardFlightIT - Afraid I don't have any Open LDAP accounts to test against, but if you're interested in testing here is another mobile to local project: https://github.com/BIG-RAT/mobile_to_local
Posted on 11-14-2019 10:05 PM
Hi @lisacherie
Thanks for that script. I made it work with MacOS 10.13, but when I try it for the latest version of Mojave, for some reason the password of the user is not being stored, because when I try to login after a restart after the script ran, it doesn't allow me to login with the same password. I haven't been able to figure it out, but do you know if maybe the password hash storage path has been changed or if there is something I should modified for this to happen?
I am newbie in scripting so a help could be very useful here.
Thanks,
Hugo Quinte
Posted on 11-27-2019 09:33 AM
I haven't actually needed to use this script since 10.13.something... it was working at that point.
Since I no longer have access to an active directory environment, I'd do a dscl output prior to the change, and then afterwards. Also compare dscl fields with a local user (that was never an AD mobile account). That will help see what fields might now be different. If you have that output, I can look quickly - however not much I can do without an AD environment.
Posted on 05-05-2020 07:53 AM
Just wondering if anyone has gotten any variant of this to work with Catalina!
Posted on 05-05-2020 10:09 AM
@arepko - Was the following not converting accounts?
https://github.com/BIG-RAT/mobile_to_local
Posted on 05-06-2020 08:53 AM
@leslie It didn't do anything, though I was referring to the original script. I'll give that link (and app) you just linked a go!
Posted on 05-08-2020 06:48 AM
@leslie The App seems to work like a champ! Thanks!
Posted on 06-01-2020 09:24 AM
@rtrouton Has worked his magic, and made an interactive version with some extra features. https://derflounder.wordpress.com/2016/12/21/migrating-ad-mobile-accounts-to-local-user-accounts/
Can confirm that the Der Flounder script works with 10.14 and 10.15
Posted on 06-11-2020 10:17 AM
@leslie This was an amazing find, THANK YOU! https://github.com/BIG-RAT/mobile_to_local
Posted on 10-05-2020 10:09 AM
Running the Der Flounder script, I get this output:
Running mobileToLocalAccount.sh Version 1.4 **
This machine is bound to Active Directory.
Do you want to unbind this Mac from AD?
1) Yes
2) No
AD binding has been removed.
Select a user to convert or select FINISHED:
1) mdesmar5
2) FINISHED
mdesmar5 has an AD mobile account.
Converting to a local account with the same username and UID.
warning: failed to load external entity "–xpath"
warning: failed to load external entity "string(//string[contains(text(),"Kerberosv5")])"
warning: failed to load external entity "–"
warning: failed to load external entity "–xpath"
warning: failed to load external entity "string(//string[contains(text(),"LocalCachedUser")])"
warning: failed to load external entity "–"
Any ideas?
Posted on 11-27-2020 04:27 AM
Update: I worked it out. I got the latest version from GitHub and modified it for the logged on user and then made it a self service policy. Works great now. Great script!
https://github.com/rtrouton/rtrouton_scripts/blob/master/rtrouton_scripts/migrate_ad_mobile_account_to_local_account/MigrateADMobileAccounttoLocalAccount.command
Posted on 03-11-2021 02:02 PM
I tested the OP script on Big Sur 11.2.3 in my VM, which worked and converted from mobile to local and removed the AD bind, but it removed the user from Filevault and the password is changed. I can reset using my other local account, just FYI! I'm trying to work through it, if anyone has an idea on how to prevent that I'd appreciate it, until then it's still a great script that needs a little hands on work.
Posted on 10-25-2021 10:43 AM
Did you ever figure out what was causing this.
08-12-2022 10:33 AM - edited 08-12-2022 10:36 AM
Just ran it on 12.5. Completely removed the user account from System Preferences > Accounts but the profile directory still existed in /Users. It also changed the password and could not sign back in.
It did unbind the machine...