Flushing out dscl on logout for lab machine

pblake
Contributor II

I know this is an odd question, but I hope someone out in the JNation can assist. I am trying to setup a lab station build. On this build people login against our LDAP to a locked down profile. When they logout the profile is deleted.

The hiccup I am having is that our LDAP doesn't have a UniqueID to map to. I was hoping to map every user who logs in to #601 or something. What I need to know is how to I flush that record during logout so the next user can login using the same UniqueID? I assume I have to run some sort of dscl command before I delete the home folder.

Any help would be greatly appreciated!!!

1 ACCEPTED SOLUTION

nessts
Valued Contributor II

OK then why not set LDAP up properly and have a unique UID field per user. Or is that completely out of the question? Or why use LDAP at all and just put a local account on the computer, and have the home directory get erased every logout then the next person that logs in gets a fresh home. Sorry if I missed this above as I have tried to read and understand the problem. I do not see the benefit of using an LDAP solution if it is not setup properly and if nothing on the machine ever needs saved what is the benefit of using different login names?

View solution in original post

33 REPLIES 33

mm2270
Legendary Contributor III

Are you just asking how you would remove the user account in directory services that matches the UID you've specified for the locked down account?
Or do you mean something else?

pblake
Contributor II

I want to flush all records of the logged in user. Currently if I map UniqueID to #601 the first person can log in. The next logs in gets an error saying it cannot create a home folder. I imagine it is because there is a record on the computer for the first user with the same uniqueid

pblake
Contributor II

I tried adding a dscl . Delete /Users/$user to the logout script. I have user=$1 which is working for the rm /Users/$user.

mm2270
Legendary Contributor III

dscl . delete /Users/$user + rm'ing the home directory should actually do what you want since that should purge the directory services record for that account and delete the home folder. I'm not certain if something gets left behind that is causing the Mac to not allow the next account to log in though.

pblake
Contributor II

@mm2270 That is what I have scripted now. dscl . delete /Users/$user
rm -rf /Users/$user

It is not working. It is deleting the home folder, but next user cannot log in with the same UniqueID. This is in 10.10, there must be some sort of cache that is stuck around that needs to be deleted as well.

BOBW
Contributor II

not sure if it helps too much but I need to do the same sort of thing deleting any users who have not logged in for 24 hours - you might be able to adjust this script :

!/bin/sh

userList=dscl . list /Users UniqueID | awk '$2 > 1000 {print $1}'

echo "Deleting account and home directory for the following users..."

for a in $userList ; do find /Users -type d -maxdepth 1 -mindepth 1 -not -name "." -mtime +1 | grep "$a" if [[ $? == 0 ]]; then echo $a fi
done

it takes any user of UID above 1000 (generally non admin users) and deletes them at the mtime 1 being 1 day. So if you change +1 to 0 and set this as a log out script it might just work AND keep the admin accounts for you

mm2270
Legendary Contributor III

I wonder if restarting DirectoryService would help?
killall DirectoryService
Not sure, but maybe it needs to be restarted in order for it to release that UID for the next login.

BTW, how exactly are you mapping that each LDAP user that logs in to the same UID? I've never seen that done before, so was curious how you were going about that? Or, was this all experimental at the moment and you aren't doing that yet?

rhysforrester
New Contributor
/usr/sbin/jamf deleteAccount -username $1 -deleteHomeDirectory

I've had issues in the past when simply running an rm across the last logged in user.

Wouldn't it be better to randomize the UID rather than mapping each account to the same one?

calumhunter
Valued Contributor

can you not add a unique UID for each user record in ldap? Like use a script to populate an ldap attribute with a unique id and map to that? That would probably be the best solution

@mm2270 you can statically map UID's like this

6b9331b4e615429ca8bb10796bbab271

Thats some old school type stuff I remember doing when I was integrating 10.2 with Novel and needing to do custom LDAP mappings

pblake
Contributor II

@mm2270 We currently do not have a unique number in our LDAP for every object. That is the main issue. So we are trying work around that by using the same number for everyone because I do not know how to make it randomly assign one. @rhysforrester do you know how to make it random? In the screenshot above, it is that UniqueID mapping I would need to map to something that says randomize. @c0up3 I tried you settings with the +0 they didn't work. Is there more to that script? I don't see what part of it would delete the accounts.

BOBW
Contributor II

here is full script: sorry i dont know why it didn't copy correctly. Don't forget though, my script deletes any non admin (>1000) account if you have not logged in for 7 days.

I didn't write this and wish I could remember where I got this to give them kudos....

#!/bin/sh
userList=`dscl . list /Users UniqueID | awk '$2 > 1000 {print $1}'`

echo "Deleting account and home directory for the following users..."

for a in $userList ; do
        find /Users -type d -maxdepth 1 -mindepth 1 -not -name "*.*" -mtime +7 | grep "$a"
        if [[ $? == 0 ]]; then
            dscl . delete /Users/"$a"  #delete the account
            rm -r /Users/"$a"  #delete the home directory
        fi
done

pblake
Contributor II

@rhysforrester - How would you randomize the UID? Do you know how?

pblake
Contributor II

@calumhunter So your screenshot is exactly what I am trying to do. It works for one user. The next user logs in and has permission errors. It seems it is not clearing out the record of the old user with the same UID.

My logout script has the following in it to help clear out the record of the logged in user:

USER=$1
userHomeDir=/Users/$USER

dscl . -delete /User/$USER
/bin/rm -rf $userHomeDir
/usr/bin/kill all -u $USER
/usr/bin/killall Directory Service - This seems to make things worse, may remove.

What else can I add to remove all records of the first user logging in with the same UID.

nessts
Valued Contributor II

maybe typos are your problem? Here are two that stand out to me.
dscl . -delete users/$USER
killall -u $USER
I would not killall directory service, which really probably is not working because you need to escape the space in that command.

nessts
Valued Contributor II

and why map the UID at all and not just let different users login and let the UID get created automatically?

calumhunter
Valued Contributor

@nessts the OP is connecting to an LDAP server, the UID needs to be mapped to an attribute in LDAP or statically mapped via the mappings in the LDAP plugin in Directory Access. The UID does not automatically get created.

@pblake what OS are you doing this on? 10.10?

How are you running the logout script?

can you post your exact logout script with correct formatting? (HINT: theres a button in the post response window that looks like > _ click that and put your script between those tags and it will format it nicely

pblake
Contributor II

@nessts - the typos were here not in the script.

@calumhunter Below is the script. I am using iHook so some of the echo stuff is from that.

#!/bin/bash

USER=$1
manageDir=/Library/Management
scriptDir=${manageDir}/bin
backupDir=${manageDir}/UserBackups
scriptLogFile=${manageDir}/bin/log/logout-wrapper.log
activityLogFile=${manageDir}/bin/log/activity.log
usageLogFile=/Users/$USER"/Library/Preferences/*Usage.log"
usageLogDir=${manageDir}/bin/log/usage
labUser=labuser
labGroup=labgroup
userHomeDir=/Users/$USER
templateHomeDir=/Users/labuser

echo %WINDOWLEVEL HIGH
echo %UIMODE AUTOCRATIC

echo "Logging Out..."

if [ -z "$USER" ] 
then
    echo "No user specified!" >> $scriptLogFile
    exit 0
fi

if [ $USER = "admin" -o $USER = "labuser" ]
then
    exit 0
fi

# tar up files of user logging out to a backup directory 
cd /Users/$USER && tar zcf ${backupDir}/$USER.`date "+%F_%H.%M.%S"`.tgz Desktop Documents Downloads
cd /

dscl . -delete /Users/$USER
/bin/rm -rf $userHomeDir

/usr/bin/killall -u $USER

echo "$USER logged out at $(date) on $(hostname)" >> $activityLogFile
echo %100

calumhunter
Valued Contributor

os version?

calumhunter
Valued Contributor
dscl . -delete /User/$USER

should be

dscl . -delete /Users/$USER

what are you user names? do they contain spaces? special characters? I generally always double quote my variables just in case ie.

userHomeDir="/Users/$USER"

and

/bin/rm -rf "$userHomeDir"

pblake
Contributor II

@calumhunter There are no spaces or special characters in the usernames.
That typo of Users/$USER was only above, not in the actual script.

I am testing with a few accounts:

pt2415
pt2419
pt2421

pt2415 will work fine. Then the next ones who log in get a permissions error.

"The home foler for user "pt2419" isn't located in the usual place or cannot be accessed."

I have UniqueID mapped to #99999998. It seems the dscl . delete doesn't remove all records of that being used by pt2415 the first time.

pblake
Contributor II

10.10.3

nessts
Valued Contributor II

OK then why not set LDAP up properly and have a unique UID field per user. Or is that completely out of the question? Or why use LDAP at all and just put a local account on the computer, and have the home directory get erased every logout then the next person that logs in gets a fresh home. Sorry if I missed this above as I have tried to read and understand the problem. I do not see the benefit of using an LDAP solution if it is not setup properly and if nothing on the machine ever needs saved what is the benefit of using different login names?

NightFlight
New Contributor III

@pblake

As per nessts, there's a core implementation error here.

nessts
Valued Contributor II

glad I am not the only one who thinks so. :D

pblake
Contributor II

@chris.hotte & @nessts

I agree with you but this is the mandate from my Identity Management team, I don't control LDAP. I wish I worked in an Active Directory world, but I dont :(

I need to find a way to either flush the previous login or set it to randomly generate uid on login.

NightFlight
New Contributor III
#!/bin/bash
function delete_local_user {
    if [ -z "$1" ]; then return; fi
    dscl . -delete /Users/${1}  &>/dev/null;
    if [ -d /Users/${1} ]; then echo deleting local account: /Users/${1}; rm -rf /Users/${1}; fi
}


function create_local_user {
    delete_local_user $1
        echo  - Creating local account: $1

    # Generate a new UniqueID
    aUID=99             # 99 = nobody
    while [ ! -z "`dscl . -search /Users UniqueID $aUID`" ]
    do 
        aUID=$RANDOM
        aUID=$((aUID % 100))    # Mod 100 keeps the value between 0-100
        aUID=$((aUID + 500))    # Add 500 = 500 - 599
    done
    # Create the local directory entry
    dscl . -create /Users/$1
    dscl . -create /Users/$1 UniqueID $aUID
    dscl . -create /Users/$1 RealName "$3"
    dscl . -create /users/$1 NFSHomeDirectory /Users/$1
    dscl . -create /Users/$1 UserShell /dev/null
#   dscl . -create /Users/$1 UserShell /bin/bash
    dscl . -create /Users/$1 PrimaryGroupID 20

    # Create the Home folder from template
    cp -a /System/Library/User Template/English.lproj /Users
    mv /Users/English.lproj /Users/$1

    # Set the password
    dscl . -passwd /Users/$1 $2

    # Fix the rights.
    chown -R ${1} /Users/${1}
    find /Users/${1}/Library -type f -exec chmod a-x {} ;

}


# Call the function:

create_local_user username userpass "User Name"

calumhunter
Valued Contributor

Have you tried kill opendirectoryd as part of your logout script?

Or

Perhaps you can change the UID of the account on the fly with some of what chris has suggested

aUID=$RANDOM
aUID=$((aUID % 100))    # Mod 100 keeps the value between 0-100
aUID=$((aUID + 500))    # Add 500 = 500 - 599

dscl . -change /Users/$1 UniqueID $old_static_mapped_UID $aUID

With Per's LoginScriptPlugin
you can run Login Scripts as root pre home directory mounting this might give you a chance to change the UID to a random number for the user logging in before their home directory is created and mounted.

check out

https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/Cus...

specifically:

Authentication Plug-Ins

Authentication plug-ins are the recommended way to perform tasks during the login process. An authentication plug-in executes while the user is logging in, and is guaranteed to complete before the user is allowed to actually interact with his or her account.

You might write an authentication plug-in if you need to programmatically reset an account to a predetermined state, perform some administrative task such as deleting caches to reduce server utilization, and so on.

To learn more about writing an authentication plug-in, read Running At Login.

pblake
Contributor II

@calumhunter & @chris.hotte

Thanks for the scripts I will play with them tomorrow and see what sticks. I appreciate the help. I have to figure out exactly how your suggestions work, but I will play around.

Thanks!

rhysforrester
New Contributor

Ahh the joys of being down under. g/l

NightFlight
New Contributor III

All the issues you will encounter repeatedly creating local accounts with randomly generated UID's are (hopefully) taken into account with the function. It works like this:

  • Expect 3 parameters passed in.
  • Delete the user name passed in from the local directory
  • While loop the random number generator test generated UID for conflict.
  • Create user in the local directory as per parameters passed in.
  • Copy the user template.
  • Assign ownership to the copied template to the newly created user.

I use this function for generic accounts with a known password for when a users directory account is unavailable for whatever reason. Its a limited account and counter policy, but it allows work to continue in a squeeze.

bentoms
Esteemed Contributor
Esteemed Contributor

@pblake You might want to find a different approach come 10.11

NightFlight
New Contributor III

I've found cached AD mobile accounts very troublesome, since after password change time they do not appear to update correctly and in my environment at least - results in consistent/frequent account lockouts. Thus my Kludge for this issue has been to clear the cached user account on the logout hook.

pblake
Contributor II

Turns out there was a unique field in the LDAP, but I have to obtain a privileged service account to read it. Once I got that, I was able to map it to a unique number.

Thanks all for the help!
Special Shouts to:
@chris.hotte @nessts @c0up3 @mm2270 @rhysforrester @calumhunter