1

We have a small network using 389 Directory Server for LDAP. We make LDAP users, those users log on to various machines in the network, and then sometimes we delete those users. However, after deleting an LDAP user, artifacts remain on each system that user accessed. I don't even know everything that's left behind, but I've identified the following: home directory, sssd cache entries, and AccountsService cache entries. Besides leftovers on the file system, this results in deleted users showing up on the gdm login screen, and if a new LDAP user is created with the same uid or username as a deleted user it causes problems (wrong name displayed or can't create home directory and gdm goes back to the login screen). How do you cleanup each local system after deleting an LDAP user?

This is what I have so far: kill all of their processes, delete their home directory, sss_cache -E, systemctl restart sssd, systemctl restart accounts-daemon. What else am I missing or is there a better way?

Even if you have a full cleanup procedure or script, do you manually run it on every system? Is there a good way to automate cleanup on LDAP deletion? I tried making a 389 Directory Server Post-Operation plug-in with a post-delete callback, but I couldn't get 389 Directory Server to load the plug-in. When I try to use ldapmodify to add the plug-in, it fails: ldap_add: Server is unwilling to perform (53) additional info: Invalid plugin path myplugin.so - failed to open library. The first time I saw this error, I found systemd log entries showing SELinux was blocking execution, but after taking the recommended actions, I now see nothing useful in systemd nor dirsrv logs, so I have no idea why it's failing.

0

My solution is to manually run a script on user deletion and have a cron job regularly run the script on each host, just in case a host was disconnected at the time of deletion. My script:

#!/bin/bash

purge() { # usage: purge <USER_NAME> <USER_ID>
    local USER_NAME=$1
    local USER_ID=$2
    if loginctl | awk '{print $2}' | grep -q $USER_ID
    then
        loginctl kill-user $USER_ID
    fi
    /usr/sbin/sss_cache -u $USER_NAME
    rm -rf /home/$USER_NAME
    rm -f /var/lib/AccountsService/users/$USER_NAME
    USERS_PURGED=true
    {
        sleep 10
        if loginctl | awk '{print $2}' | grep -q $USER_ID
        then
            loginctl terminate-user $USER_ID
        fi
        pkill -u $USER_ID
        echo "Purged user $USER_NAME" | systemd-cat -t ldap-cleanup
    } &
}

# Require root
if [ "$UID" != 0 ]
then
    >&2 echo "Please run this script as root."
    exit 1
fi

# Get LDAP users
LDAP_RESULT=$(ldapsearch -x -LLL uid=* uid uidNumber)
if [[ $? != 0 ]]
then
    >&2 echo "LDAP query failed"
    exit 1
fi

declare -A LDAP_USERS
LDAP_USER_NAMES=($(echo "$LDAP_RESULT" | sed -n 's/uid: //p'))
LDAP_UIDS=($(echo "$LDAP_RESULT" | sed -n 's/uidNumber: //p'))
if [[ ${#LDAP_USER_NAMES[@]} != ${#LDAP_UIDS[@]} ]]
then
    # This shouldn't happen
    >&2 echo "LDAP user name and UID arrays are different lengths!"
    exit 1
fi

for i in ${!LDAP_USER_NAMES[@]}
do
    LDAP_USERS["${LDAP_USER_NAMES[$i]}"]="${LDAP_UIDS[$i]}"
done

# Check local users against LDAP users
HOME_DIRS=$(ls -n /home | tail -n +2 )
LOCAL_USER_NAMES=($(echo "$HOME_DIRS" | awk '{print $9}'))
LOCAL_UIDS=($(echo "$HOME_DIRS" | awk '{print $3}'))
for i in ${!LOCAL_USER_NAMES[@]}
do
    USER_NAME=${LOCAL_USER_NAMES[$i]}
    USER_ID=${LOCAL_UIDS[$i]}
    if [[ ! ${LDAP_USERS[$USER_NAME]+x} ]]
    then
        if ! grep -q "^${USER_NAME}:" /etc/passwd
        then
            # Defunct LDAP user (user not in /etc/passwd nor LDAP)
            purge $USER_NAME $USER_ID
        fi
    elif [[ $USER_ID != ${LDAP_USERS[$USER_NAME]} ]]
    then
        if ! grep -q "^${USER_NAME}:" /etc/passwd
        then
            # Recreated LDAP user (different UID)
            purge $USER_NAME $USER_ID
        else
            >&2 echo "User ${USER_NAME} has a different UID in LDAP: local UID: $USER_ID, LDAP: ${LDAP_USERS[$USER_NAME]}"
        fi
    fi
done

if [ "$USERS_PURGED" = true ]
then
    # This should clean up the gdm user selection screen
    systemctl restart sssd
    systemctl restart accounts-daemon
fi

I'm not saying it's great, but it's good enough for my needs. Note that it assumes all users' home directories are in /home.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.