#!/bin/bash # # A simple script to add users and their group to ldap, as well as a kerberos principal. # set -eu usage(){ cat <<EOF Usage: $(basename "$0") adduser <uid> <password> <group>|none <given name> <family name> $(basename "$0") adduser <uid> <password> [<group>] $(basename "$0") deluser <uid> $(basename "$0") delhost <hostname> $(basename "$0") ldapvi $(basename "$0") <file> <uid>: User ID (login name) <password>: Password <group>: If given and not "none", the user is added to this posix group (in addition to his personal group). The group must already exist in the LDAP DT. <given name>, <family name>: LDAP attributes 'givenName' and 'sn'. If omitted, <uid> is used. <file>: File containing lines of the form: adduser <uid 1> <password 1> <group 1> <given name 1> <family name 1> adduser <uid 2> <password 2> <group 2> <given name 2> <family name 2> … deluser <uid n> deluser <uid n+1> … Every line is processed like a single call to the $(basename "$0") program. EOF } BASEDN="{{ basedn }}" LDAPADMIN="cn=admin,$BASEDN" ADPASSWD="$(cat {{ ldap_admin_pwd_file }})" if [ $# -lt 2 ] ; then if [ $# = 0 ] ; then usage exit 1 elif [ "$1" = ldapvi ] ; then exec ldapvi -m -h ldapi:/// -D "$LDAPADMIN" -b "$BASEDN" -w "$ADPASSWD" elif [ -r "$1" ]; then ## recursively call this program: while read -r LINE ; do $0 $LINE done < "$1" ## reset cache after mass import/deletion: which sss_cache > /dev/null && sss_cache -U -G exit 0 else usage exit 1 fi elif [ "$1" = adduser ] && [ $# -lt 3 ] ; then echo "Error: Password missing." usage exit 1 fi ## Range of user and personal group IDs: MINID={{ min_id }} MAXID={{ max_id }} ## Range to cover in a single ldap search (must be smaller than 'olcSizeLimit' in cn=config): RANGE=399 HOMES="{{ lan_homes }}" COMMAND="$1" id="$2" pw="${3:-""}" grp="${4:-""}" gn="${5:-$2}" sn="${6:-$2}" domain="$(hostname -d)" if [ -x /usr/sbin/kadmin.local ] ; then KRB5=true pwEntry="" else KRB5=false pwEntry="userPassword: $pw" fi ################################################################################################## nextnum(){ local id=$MINID local bsta bend all uids gids num ## Search for the next pair of identical free IDs: while [ "$id" -le "$MAXID" ] ; do bsta=$id bend=$(( bsta + RANGE )) all="$(seq "$bsta" "$bend")" uids="$(ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b "ou=people,$BASEDN" "(&(objectClass=posixAccount)(uidNumber>=$bsta)(uidNumber<=$bend))" \ uidNumber 2>/dev/null | grep "uidNumber: " | cut -f2 -d ' ' | sort -g | uniq)" gids="$(ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b "ou=groups,$BASEDN" "(&(objectClass=posixGroup)(gidNumber>=$bsta)(uidNumber<=$bend))" \ gidNumber 2>/dev/null | grep "gidNumber: " | cut -f2 -d ' ' | sort -g | uniq)" fuids="$(comm -13 <(echo "$uids") <(echo "$all"))" fgids="$(comm -13 <(echo "$gids") <(echo "$all"))" num=$(comm -12 <(echo "$fuids") <(echo "$fgids") | head -1) if [ -n "$num" ] ; then echo "$num" return else id=$(( bend + 1 )) fi done ## something went wrong: exit 1 } add-user(){ local id="$1" local pwEntry="$2" local grp="$3" local gn="$4" local sn="$5" local uidNumber local gidNumber if ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b "ou=people,$BASEDN" "(&(objectClass=posixAccount)(uid=$id))" uid 2>/dev/null \ | grep -q "uid: $id" ; then echo "User '$id' exists already, skipping." return fi uidNumber=$(nextnum) gidNumber=$uidNumber if [ "$uidNumber" -ge "$MAXID" ] || [ "$gidNumber" -ge "$MAXID" ] ; then echo "Error: $uidNumber and/or $gidNumber exceed max ID number ${MAXID}." exit 1 fi cat <<EOF | ldapadd -H ldapi:/// -D "$LDAPADMIN" -w "$ADPASSWD" | sed '/^$/d' ############## LDIF ############## dn: uid=${id},ou=people,$BASEDN objectClass: inetOrgPerson objectClass: posixAccount uidNumber: ${uidNumber} gidNumber: ${gidNumber} homeDirectory: ${HOMES}/${id:0:1}/${id} loginShell: /bin/bash cn: ${gn} ${sn} givenName: ${gn} sn: ${sn} gecos: ${gn} ${sn} ${pwEntry} dn: cn=${id},ou=groups,$BASEDN objectClass: posixGroup gidNumber: ${gidNumber} ################################## EOF if [ -n "$grp" ] && [ "$grp" != "none" ] ; then cat <<EOF | ldapmodify -H ldapi:/// -D "$LDAPADMIN" -w "$ADPASSWD" | sed '/^$/d' ############## LDIF ############## dn: cn=${grp},ou=groups,$BASEDN add: memberUid memberUid: ${id} ################################## EOF fi if [ "$KRB5" = "true" ] ; then kadmin.local -q "add_principal -policy default -pw \"$pw\" -x dn=\"uid=${id},ou=people,$BASEDN\" ${id}" \ | sed '/Authenticating as principal/d' if [ ! -e "${HOMES}/${id:0:1}/${id}" ] ; then echo "uidNumber: ${uidNumber} gidNumber: ${gidNumber}" mkdir -p "${HOMES}/${id:0:1}/" cp -r /etc/skel "${HOMES}/${id:0:1}/${id}" chown -R "${uidNumber}:${gidNumber}" "${HOMES}/${id:0:1}/${id}" #chmod -R o= ${HOMES}/${id:0:1}/${id} ls -nld "${HOMES}/${id:0:1}/${id}" fi fi } del-user(){ local id="$1" local KEEPDIR if [ $KRB5 ] ; then ## Remove all kerberos attributes from LDAP, then the whole DN below. The latter should be sufficient. kadmin.local -q "delete_principal -force ${id}" \ | sed -e '/Authenticating as principal/d' -e '/Make sure that you have removed/d' fi ldapdelete -v -H ldapi:/// -D "$LDAPADMIN" -w "$ADPASSWD" "uid=${id},ou=people,$BASEDN" "cn=${id},ou=groups,$BASEDN" 2>&1 \ | sed '/ldap_initialize/d' for grp in $(ldapsearch -Y EXTERNAL -H ldapi:/// -LLL -b "ou=groups,$BASEDN" "(&(objectClass=posixGroup)(memberUid=${id}))" cn 2>/dev/null \ | grep cn: | cut -d ' ' -f2) ; do cat <<EOF | ldapmodify -H ldapi:/// -D "$LDAPADMIN" -w "$ADPASSWD" | sed '/^$/d' ############## LDIF ############## dn: cn=${grp},ou=groups,$BASEDN delete: memberUid memberUid: ${id} ################################## EOF done if [ -d "${HOMES}/${id:0:1}/${id}" ] ; then KEEPDIR="${HOMES}/${id:0:1}/rm_$(date '+%Y%m%d')_${id}" mv "${HOMES}/${id:0:1}/${id}" "${KEEPDIR}" chown -R root:root "${KEEPDIR}" ls -ld "$KEEPDIR" fi } del-host(){ local id="$1" if [ $KRB5 ] ; then ## Remove kerberos principals from LDAP. kadmin.local -q "delete_principal -force host/${id}.${domain}" \ | sed -e '/Authenticating as principal/d' -e '/Make sure that you have removed/d' kadmin.local -q "delete_principal -force nfs/${id}.${domain}" \ | sed -e '/Authenticating as principal/d' -e '/Make sure that you have removed/d' fi } ############################## ########### main ############# ############################## which sss_cache > /dev/null && sss_cache -U -G ## clear cache echo "==== $* ====" case $COMMAND in adduser) add-user "${id}" "${pwEntry}" "${grp}" "${gn}" "${sn}" ;; deluser) del-user "${id}" ;; delhost) del-host "${id}" ;; *) usage ;; esac