Migrate Local User to Domain Account

by on January 14, 2010 » Add more comments.

If you are migrating your machines to authenticate via Active Directory, you may need to convert your local user accounts and their home folders to an AD user account and retain the home folder. I had a script posted here but that version was Tiger only because it used NI* commands.

The following script is written in bash and can be run by double clicking (it’s a .command) as a user with sudo rights (all admin users have this right by default). It will prompt for your admin password, then present a list of numbered local users. Enter a number from the list for the user you want to migrate, then it will ask for the network ID. It runs in a loop until you select the option for “Finished” which will exit the script.

This should work with Tiger, Leopard or Snow Leopard and can easily be modified to work with OD user accounts (change the check4AD variable to check for OD instead).

To download the script, click here.

#!/bin/sh
Version=1.0
# Modified 1/14/2009
 
# MigrateLocalUserToDomainAcct.command
# Patrick Gallagher
# http://macadmincorner.com
#
 
# This script should not need any modification in most enviornments. 
# If the script does not execute when run, you may need to 'chmod +x /path/to/thisScript' to make it executable
 
clear
 
netIDprompt="Please enter the network ID for this user: "
listUsers="$(/usr/bin/dscl . list /Users | grep -v eccsadmin | grep -v _ | grep -v root | grep -v uucp | grep -v amavisd | grep -v nobody | grep -v messagebus | grep -v daemon | grep -v www | grep -v Guest | grep -v xgrid | grep -v windowserver | grep -v unknown | grep -v unknown | grep -v tokend | grep -v sshd | grep -v securityagent | grep -v mailman | grep -v mysql | grep -v postfix | grep -v qtss | grep -v jabber | grep -v cyrusimap | grep -v clamav | grep -v appserver | grep -v appowner) FINISHED"
FullScriptName=`basename "$0"`
ShowVersion="$FullScriptName $Version"
check4AD=`/usr/bin/dscl localhost -list . | grep "Active Directory"`
osversionlong=`sw_vers -productVersion`
osvers=${osversionlong:3:1}
 
echo "********* Running $FullScriptName Version $Version *********"
 
# If the machine is not bound to AD, then there's no purpose going any further. 
if [ "${check4AD}" != "Active Directory" ]; then
	echo "This machine is not bound to Active Directory.\nPlease bind to AD first. "; exit 1
fi
 
RunAsRoot()
{
        ##  Pass in the full path to the executable as $1
        if [[ "${USER}" != "root" ]] ; then
                echo
                echo "***  This application must be run as root.  Please authenticate below.  ***"
                echo
                sudo "${1}" && exit 0
        fi
}
 
RunAsRoot "${0}"
 
until [ "$user" == "FINISHED" ]; do
 
	printf "%b" "\a\n\nSelect a user to convert or select FINISHED:\n" >&2
	select user in $listUsers; do
 
		if [ "$user" = "FINISHED" ]; then
			echo "Finshied converting users to AD"
			break
		elif [ -n "$user" ]; then
			if [ `who | grep console | awk '{print $1}'` == "$user" ]; then
				echo "This user is logged in.\nPlease log this user out and log in as another admin"
				exit 1
			fi
 
			# Determine location of the users home folder
			userHome=`/usr/bin/dscl . read /Users/$user NFSHomeDirectory | cut -c 19-`
 
			# Get list of groups
			echo "Checking group memberships for local user $user"
			lgroups="$(/usr/bin/id -Gn $user)"
 
 
			if [[ $? -eq 0 ]] && [[ -n "$(/usr/bin/dscl . -search /Groups GroupMembership "$user")" ]]; then 
			# Delete user from each group it is a member of
				for lg in $lgroups; 
					do
						/usr/bin/dscl . -delete /Groups/${lg} GroupMembership $user >&/dev/null
					done
			fi
			# Delete the primary group
			if [[ -n "$(/usr/bin/dscl . -search /Groups name "$user")" ]]; then
  				/usr/sbin/dseditgroup -o delete "$user"
			fi
			# Get the users guid and set it as a var
			guid="$(/usr/bin/dscl . -read "/Users/$user" GeneratedUID | /usr/bin/awk '{print $NF;}')"
			if [[ -f "/private/var/db/shadow/hash/$guid" ]]; then
 				/bin/rm -f /private/var/db/shadow/hash/$guid
			fi
			# Delete the user
			/usr/bin/dscl . -delete "/Users/$user"
 
 
				# Verify NetID
				printf "\e[1m$netIDprompt"
				read netname
				/usr/bin/killall DirectoryService
				sleep 10
				/usr/bin/id $netname
				# Check if there's a home folder there already, if there is, exit before we wipe it
				if [ -f /Users/$netname ]; then
					echo "Oops, theres a home folder there already for $netname.\nIf you don't want that one, delete it in the Finder first,\nthen run this script again."
					exit 1
				else
					/bin/mv $userHome /Users/$netname
					/usr/sbin/chown -R ${netname} /Users/$netname
					echo "Home for $netname now located at /Users/$netname"			
				fi
			break
		else
			echo "Invalid selection!"
		fi
	done
done

Find more like this: AD Integration, Directory Services, Mac, Scripting , , , , , ,


62 Responses to Migrate Local User to Domain Account

  • MIke says:

    Can anyone give *exact* steps for running this in Lion? i.e. – should we run it in a local admin account only? Should the machine already be bound to AD or not? I ran this once (haphazardly since the outcome didn’t matter much) and while the files and folders did migrate, the user had lost permissions to just about everything. Restoring those permissions on all of the folders and in more than too many cases, sub-folders as well, was no fun.

    Kudos to the script author(s) though. This was sorely needed…

  • Timothy says:

    This script worked for me, sort of. It orphaned the existing local admin account and all its content. I was obliged to set perms on the orphaned account and populate them down through that structure, then copy over content from Documents to AD user Documents, Pictures to Pictures, Movies to Movies…. How was this script helpful then?

  • Patrick says:

    @Timothy

    That’s not the normal result of this script. I haven’t used this script in a long time so it’s possible it needs to be updated for Lion. We mainly used it while we were migrating to AD, that’s long done now and all our new deployments start off with AD.

    One thing that stands out is that Lion now has the opendirectoryd process instead of DirectoryService so that bit would need to be updated in this script.

  • vasco says:

    @Patrick

    I had the same effect in Lion Timothy mentoined. Is there any chance that you goint to update the script or can you give us any advice? 🙂

    Thank’s!

  • Craig Richardson says:

    See my post earlier in the thread for changes to make to the script for Lion. I’ve run this on about a hundred Macs now and its working just fine.

    One tip though with Lion. Don’t run this immediately after binding the machine to AD. Bind the machine however you normally would (script or manually) then restart it and perform at least one login as a network user.

    Then logout, login as a local admin to migrate all the other local user accounts on the Mac.

  • John Inciarrano says:

    Tried using this script and it doesn’t seem to like my company’s username convention of First Last is there an edit to the script that will get this to work with usernames with spaces in them? I really don’t want to migrate 500 macs manually =(

  • Elliot Wilen says:

    This script has worked well for us in converting to AD. Thank you very much!

    One problem we’ve had, though, is that chown -R generates a bunch of errors due to locked files, and those files are then left with no owner. This can be cleaned up by hand, but I think a better solution may be to insert

    /usr/bin/chflags -R nouchg /Users/$netname

    right before

    /usr/sbin/chown -R ${netname} /Users/$netname

  • Mauricio Klagenberg says:

    Hello

    “sleep 50” is necessary before “/usr/sbin/chown -R ${netname} /Users/$netname”, cause sometimes “mv” command processing too long.

  • Adam says:

    Hi Patrick,
    I love this script and it has helped me immensely.

    Quick question: I’ve bound all Macs in my department to the company AD, and now the company is changing their AD domain name. It’s not just a name change, it’s a new server box, so I’m thinking I’ll need to re-run this script on all the Macs again after I’ve bound them to the new domain. Does that sound right?

    I’ve done a bit of testing, and it doesn’t appear to be as easy as unbinding from the old and binding to the new domain because the local user accounts aren’t able to authenticate…

    Have you ever come across this situation?

  • Jean says:

    What is the network ID? is the domain user name or the computer name on the network?

  • Patrick F. Segovia says:

    Do you have an updated script for Mountian Lion? Also what type of value is the network ID asking for?

    Thx, Patrick

  • Nicole says:

    Wil this work for El Capitan?

Leave a Reply

Your email address will not be published. Required fields are marked *