OT - domain migration user login woes

acdesigntech
Contributor II

All,

We're testing a domain migration from AD-A to AD-B. Basically the workflow I am using is:

dsconfigad -remove to remove the Mac from the old domain, then dsconfigad -add <options> to bind to the new domain. This all works fine.

The issue I'm running into is when the user account (migrated with ADMT from old domain A to new domain B) tries to log in after the domain move. I get the "Unable to create mobile account" error on login. Usually this has meant permissions aren't set right on the users homefolder, but not in this case.

I thought maybe the cached AD account on the Mac might be causing a problem, so I've been moving the homefolder outside of users, then using dscl . -delete to remove the user account, then moving the homefolder back and setting permissions on it. I still get the error message. If I don't move the homefolder back the Mac creates a new mobile profile just fine, so it's definitely something inside the homefolder.

I've tried removing the user's Keychains and Caches and still nadda. Can anyone with this experience help me out?

2 ACCEPTED SOLUTIONS

tlarkin
Honored Contributor

Hey acdesign,

I have done about a dozen or so of these exact migrations. I wrote a couple of bash scripts that did all of it on the client side. I can tell you, there is always a margin of failure and some machines will most likely have to be touched by a human when or if they fail. However, that is not always the case. This is basically how I tackled it:

1) - Obtain a CSV file the old computer name (current), and the new name for the device record in AD, as well as a CSV for old domain user name, and new domain user name. It should be formatted in a manner where it would look like this - oldusername,newusername and the computer name CSV would be the same - oldcomputer,newcomputername

2) - use a script that does the following: i ) removes old AD binding from old Domain ii ) grabs the current computer name from the device and parses the computer name CSV file iii ) once a match is found, it renames the computer to what new device record should be in the new domain iv ) Once the computer name is found, and change, trigger an AD BIND v ) repeat with end user name, same logic with the CSV, end user cannot be logged in, and it will use the mv command to rename the home folder vi ) set proper ownership and permissions to new account, so when user logs in with their new domain creds, it just works vii ) deletes old user record from the BSD database via dscl viii ) end user logs in with new AD creds, bound to new AD server, with a home folder renamed to their new user name and permissions set for them to already own it.

3 - script had fail logic in it that wrote to a log file, then triggered a recon immediately so extension attributes could track failures, track what failed, and give you real time results and then sort those into smart groups by specific failure. For example, unsupported version of OS X, computer record or username not found, unable to BIND to server, etc.

4 - set policy to run said scripts, and then track failures and address hot fixes or reattempt to smart groups based on failure.

Unfortunately, these were custom development scripts so I won't be allowed to share any of the code. Hopefully you can take this basic work flow though and build your own. I can tell you that you will need to test this probably 50+ times before going into production because every time I did one, I always found one new little snag here or there regarding these work flows.

View solution in original post

bentoms
Release Candidate Programs Tester

@acdesigntech, if the users username is staying the same post migration to the new domain... Then this may work: http://macmule.com/2013/02/18/correct-ad-users-home-mobile-home-folder-permissions/

It'll look up their UID (using the home folder name) against the NEW domain & will set the permissions on the home folder correctly.

View solution in original post

23 REPLIES 23

nessts
Valued Contributor II

try removing .account from the users home.

acdesigntech
Contributor II

@nessts, I'm not seeing a .account file... at ~ ?

stevewood
Honored Contributor II
Honored Contributor II

Have you tried repairing permissions on the Mac? I've found that if I do not repair disk permissions immediately after running dsconfigad, I have problems creating the mobile account on the Mac.

acdesigntech
Contributor II

yeah, this mac was all messed up. reimaging it now since reimaging takes about 30 minutes. I'll be able to post back with results after I know things are all well and good, at least on the OS side of things.

mm2270
Legendary Contributor III

Have you checked to make sure the account from AD-B isn't generating a new GUID for the account when it migrates? I know nothing about ADMT, though my assumption would be that the tool is simply migrating the account as is from AD-A, not generating new information for the account. But, you know where assuming gets you don't you? :)

As I understand it, Apple's AD plugin can use the Active Directory GUID to generate the local UID for the account on the Mac. I would make sure its not seeing it as a different account, despite the account home directory having the same name. I think. a different UID will cause some issues, because the Apple AD plug-in isn't just looking at an account home folder name to match up with. it tries to use the UID and if these aren't the same I believe it will attempt to create a new cached local account.

Rich has write up here that may help with repairing account permissions after such a move.
http://derflounder.wordpress.com/2013/11/20/fixing-permissions-after-changing-directory-services/
Edit: in looking at his post again it seems this is more about correcting permissions on files/folders created with the previous account on filesystems, but it may still be useful to you anyway.

As for why it errors when it tries to create a new mobile account, @stevewood][/url][/url][/url][/url][/url's suggestion may help out. But I'm guessing you don't really want it creating a new mobile account anyway.

slb
New Contributor

What about booting from the Recovery partition and resetting the User's ACL's?

acdesigntech
Contributor II

I am assured that a new GUID is not being generated by ADMT, but ditto on the knowing nadda about it. But I did take a look at the UID generated by the OS before and after the migration, and they are different. Not sure if that's because of a different GUID being created or not. Regardless, removing the mobile account and letting it get recreated SHOULD work, but it's not.

I've run into this issue many times in the past when peoples' AD names change - not a surname change, mind you, but an account change say for example from a contractor ID to an employee ID. We have to essentially remove the users' old account via dscl . -delete and then rename the home folder and repair permissions. Then, when the user logs in with their new account it re-attaches to the renamed homefolder. Works like a charm, but this is in the same domain.

I've never done an inter-domain migration before, so this is all new to me. I was hoping the same methodology would apply here as above, but not so much. I'll try Rich's article and see if that gets me anywhere.

It's also no help that our test domains are not behaving the same as our production domains (ex: no .account file is created in test while it is in production. lesigh)

acdesigntech
Contributor II

we have to keep this as unattended as possible, so a reboot to another drive probably wouldn't help here. Once I get another account migrated I'll try out Rich's article.

tlarkin
Honored Contributor

Hey acdesign,

I have done about a dozen or so of these exact migrations. I wrote a couple of bash scripts that did all of it on the client side. I can tell you, there is always a margin of failure and some machines will most likely have to be touched by a human when or if they fail. However, that is not always the case. This is basically how I tackled it:

1) - Obtain a CSV file the old computer name (current), and the new name for the device record in AD, as well as a CSV for old domain user name, and new domain user name. It should be formatted in a manner where it would look like this - oldusername,newusername and the computer name CSV would be the same - oldcomputer,newcomputername

2) - use a script that does the following: i ) removes old AD binding from old Domain ii ) grabs the current computer name from the device and parses the computer name CSV file iii ) once a match is found, it renames the computer to what new device record should be in the new domain iv ) Once the computer name is found, and change, trigger an AD BIND v ) repeat with end user name, same logic with the CSV, end user cannot be logged in, and it will use the mv command to rename the home folder vi ) set proper ownership and permissions to new account, so when user logs in with their new domain creds, it just works vii ) deletes old user record from the BSD database via dscl viii ) end user logs in with new AD creds, bound to new AD server, with a home folder renamed to their new user name and permissions set for them to already own it.

3 - script had fail logic in it that wrote to a log file, then triggered a recon immediately so extension attributes could track failures, track what failed, and give you real time results and then sort those into smart groups by specific failure. For example, unsupported version of OS X, computer record or username not found, unable to BIND to server, etc.

4 - set policy to run said scripts, and then track failures and address hot fixes or reattempt to smart groups based on failure.

Unfortunately, these were custom development scripts so I won't be allowed to share any of the code. Hopefully you can take this basic work flow though and build your own. I can tell you that you will need to test this probably 50+ times before going into production because every time I did one, I always found one new little snag here or there regarding these work flows.

slb
New Contributor

Wanted to see if that helped at all in order to narrow down the possibilities.

tlarkin
Honored Contributor

Yes, also I forgot to mention, I wiped out the end users keychain in these scripts because they will be tied to the old account information and passwords will probably not match up.

rtrouton
Release Candidate Programs Tester

As it happens, I'm also doing a domain migration. Here's what I'm doing:

http://derflounder.wordpress.com/2013/11/27/using-deploystudio-as-an-active-directory-domain-migrati...

My method uses DeployStudio instead of Casper, and we're touching each machine. As part of it, I'm migrating the user profiles using a script based on this one:

https://github.com/rtrouton/rtrouton_scripts/tree/master/rtrouton_scripts/migrate_local_user_to_AD_d...

This particular script is for migrating a local user to an AD mobile user. That said, it works just as well to move someone from an AD mobile user account to a new AD mobile user account.

bentoms
Release Candidate Programs Tester

@acdesigntech, if the users username is staying the same post migration to the new domain... Then this may work: http://macmule.com/2013/02/18/correct-ad-users-home-mobile-home-folder-permissions/

It'll look up their UID (using the home folder name) against the NEW domain & will set the permissions on the home folder correctly.

acdesigntech
Contributor II

Wow, thanks for all of the responses everybody! I'll definitely be trying these out over the next week or so. I'll keep updating here.

@bentoms, yes the usernames are sticking - with the exception that if the migration causes a collision with our current domain then the name changes, but I should have that info beforehand.

Computer names are all sticking too, so that helps!

acdesigntech
Contributor II

well, so far so good. I used portions of @bentoms script to lookup the GUID of the user account after it is migrated, and set permissions accordingly. Users are able to log in properly! Yayyy!!!!

It seems that since ADMT was generating a new GUID for the AD account, I needed to use dscl to look up the GUID on the NEW domain. It wasn't enough to just give it the short name of the user.

Thanks for all the help guys!

bentoms
Release Candidate Programs Tester

Awesome, awesome, awesome.

Especially like mine & @tlarkin being marked as resolutions, as that poor guy is one of the main reasons I can script & share them too!

mm2270
Legendary Contributor III

Glad you got that worked out @acdesigntech! I had a feeling a new GUID was being generated and the AD plug-in can get confused by that kind of stuff. Its more than just an account name that it uses for permissions.

acdesigntech
Contributor II

Yes, apparently intRAdomain moves do not generate a new guid, but intERdomain moves do. Pronunciation is important ;)

I'll be doing both as part of this project so fun fun fun.

tlarkin
Honored Contributor

Hey Everyone,

Some of the methods I have used in doing such things, is using CSV files of old domain user name and new one, as well as the computer names. I have also used the /Search syntax in dscl, to look up the domain user once the client is bound to the new domain server.

I actually never used any third party products (except Casper) to accomplish this. I used shell scripts and extension attributes (to track failures) and policy and BIND objects from Casper. If migrating a local account to a domain account I used the createmobileaccount binary in the Managed Client app built into OS X. If the process called for an actual paper trail (HR requirement I guess) I did a self service model where it prompted you for your credentials while logged in as local admin and migrated the home folder and did the BIND accordingly.

To determine if user accounts were local or domain users I would check their UID. In OS X by default (it has been this way since I think 10.0 and hasn't changed) all local users would have a UID range of 501 ~ 999, where domain users would be 1001 to whatever the maximum number a UID can be (UID 1000 is reserved for the directory administrator account in OD). So, by checking the UID I could tell if it was either a local account, or a domain user (mobile account, etc). I also took into consideration any local accounts that may be used for local administration via the IT department. I would put those in exception lists that got ignored.

All you really have to do is make sure the computer name is proper for the BIND to AD since it will create a computer record, and that the user being migrated is not logged in. Then really all you do is move the folder (rename it) to the new domain user and set permissions so when they log in, they assume complete ownership of that home folder.

Let us know how this pans out, as it is never really a fun or clean process. I spent many hours doing all of my migrations and I always ran into that weird problem here and there that never popped up during testing.

Thanks,
Tom

acdesigntech
Contributor II

the thing I'm most worried about is the "name collisions." Apparently there are about 30 names that already exist in our AD so those are getting changed on the fly. Should make some interesting migrations.

If it's anything like the exchange migrations, it's going to be a long story, full of sighs.

I did notice that bentoms script assumes only a single domain in a forest. As luck would have it, we have 4 domains under a single forest, so this line:

adNodeName=`dscl /Search read /Groups/Domain Users | awk '/^AppleMetaNodeLocation:/,/^AppleMetaRecordName:/' | head -2 | tail -1 | cut -c 2-`

yields some severely odd results.

Luckily I can grep for the correct domain instead of using the head command and get the expected results:

adNodeName=`dscl /Search read /Groups/Domain Users | awk '/^AppleMetaNodeLocation:/,/^AppleMetaRecordName:/' | grep fqdn.goes.here | tail -1 | cut -c 2-`

Just an FYI for any of ya'll who might be using this to migrate to a multi-domain forest. And in the interest of making all our lives more difficult, the multi-domain forest is being collapsed into a fewer-but-still-multi-domain forest at the same time as we are migrating the external domain to our forest. So the switch on the head command would have tochange midway through the migration ANYWAY (without warning, mind you), so grep looks like the safer bet here.

acdesigntech
Contributor II

So, update on this.... I have the following block of code

accountUniqueID=`dscl . -read /Users/"$USER_ID" 2>/dev/null |?grep UniqueID | cut -c 11-`
    if [ "$USER_ID" == "Shared" -o "$USER_ID" == "Guest" ]; then ## If we've hit the /User/Shared folder, skip. We can't migrate this
        echo "$USER_ID: /Users/Shared folder or Guest account. Skipping."
        echo "---"
    elif [ "$accountUniqueID" -lt "1000" ]; then  ## If the UID is below 1000 we have a local user, we do not need to migrate. Skip
        echo "$USER_ID: This is a local account. Skipping."
        echo "---"
    elif [ "$accountUniqueID" == "" ]; then ## If dscl comes back with no ID, try going to AD. If still no ID, we've hit a garbage folder. Skip
        echo "$USER_ID: No local account associated with $USER_ID on this Mac. This might be a network only account, checking Active Directory..."
        accountUniqueID=`dscl "$adNodeName" -read /Users/"$USER_ID" 2>/dev/null | grep UniqueID | awk '{ print $2}'`
        if [ "$accountUniqueID" == "" ]; then
            echo "$USER_ID: No Active Directory account either. Skipping to next user."
            echo "---"
        else
            echo "$USER_ID: Found in $adNodeName. Continue migrating $USER_ID. This account will now be a mobile account on this Mac."
            fMigrateUser
        fi
    else ## Anything else is a mobile user account - continue processing
        echo "$USER_ID is a mobile account. Continue migration."
        fMigrateUser
    fi

That keeps showing a failure when doing the -lt comparison on a user account: "/private/tmp/DomainMove.sh: line 61: [: -lt: unary operator expected". I only get this error when running the script through Casper. When I run the commands locally on the Mac, it works just fine...

I've tested with both ```
elif [ "$accountUniqueID" -lt "1000" ]; then

and

elif [ $accountUniqueID -lt 1000 ]; then
``` and get the same result

HALP PLZ

acdesigntech
Contributor II

:/ hrm... apparently nevermind? I added a few sleep statements to the script, namely a sleep 120 at the beginning - just after a forced logout, then a sleep 120 after the dsconfigad -add command, just to be safe. seems to have made the rest of the script work... weird but i'll take it.

I did notice that when it was failing with the unary operator error, it WASN'T able to do a dscl lookup of the user against active directory yet... (dscl <domain> -read /Users/<ADUser> etc etc). Maybe it wasn't able to contact the domain yet? So it would return a blank for the lookup, and cause the unary operator error since the variable $accountUniqueID was blank.

tlarkin
Honored Contributor

Hey acdesign,

I have ran into similar things as well. Especially with older versions of OS X. I found out through testing, and this was mainly with 10.6.8 Macs, that the BIND action would take a long time, and cause look ups to time out. Also, if you notice the older AD BIND plugin would actually execute 5 times, and then time out after the 5th time. This must have been some sort of magic number, because in my testing I would find a lot of Macs to time out 4 times in a row, but on the 5th time the BIND worked. No idea if that was just coincidence or not.

So, what I would do, is something like this:

for i in {1..5}; do
jamf policy -trigger my_ad_bind_trigger
done

That for loop will run a manual trigger policy 5 times. I also added in a bit of logic later within a function, that could do all of it at once. The extra logic would also do the AD account look up before proceeding, and if it failed, it would run the first function over and it would trickle back down and run the later functions, but after it ran 5 times it just gave up and would echo out an error message to a file, which later I would use an extension attribute to track failures.

You can also verify that you can look up the AD user once you are bound. To test this out, simply do this:

dscl /Search read /Users/tlarkin

Once your Mac is bound, dscl can search all domains it is bound to and try to look up the user. For example, I can plug in my co-workers AD user names (who have never logged into my Mac) and pull their basic AD info dscl stores by doing so.

One last thing, when doing conditional statements in bash, you can almost always use the double brackets, ie the "[[" and "]]," since single brackets are only used for strict POSIX environments.

I hope this helps you out.

Thanks,
Tom