--- /dev/null
+#!/bin/bash
+
+set -e
+set -u
+
+BASE_NAME="$( basename ${0} )"
+MY_REAL_NAME=$( readlink -f $0 )
+BIN_DIR=$( dirname "${MY_REAL_NAME}" )
+BASE_DIR=$( dirname "${BIN_DIR}" )
+
+VERSION="0.1"
+
+if [[ -f "${BIN_DIR}/functions.rc" ]] ; then
+ . "${BIN_DIR}/functions.rc"
+else
+ echo "Bash resource file '${BIN_DIR}/functions.rc' not found" >&2
+ exit 5
+fi
+
+cd "${BASE_DIR}" || exit 99
+
+declare -a INSTANCES=()
+INSTANCES+=( 'dpx-legacy' )
+INSTANCES+=( 'dpx-prd' )
+INSTANCES+=( 'dpx-dev' )
+INSTANCES+=( 'spk-prd' )
+INSTANCES+=( 'spk-dev' )
+
+declare -a USED_INSTANCES=()
+YES="n"
+
+declare -A LDAP_URLS=()
+LDAP_URLS['dpx-legacy']="ldap://ldap-legacy.pixelpark.com"
+LDAP_URLS['dpx-prd']="ldaps://prd-ds.pixelpark.com"
+LDAP_URLS['dpx-dev']="ldaps://dev-ldap2.pixelpark.com"
+LDAP_URLS['spk-prd']="ldaps://live-ldap.spk.pixelpark.net"
+LDAP_URLS['spk-dev']="ldaps://stage-ldap.spk.pixelpark.net"
+
+declare -A BIND_DNS=()
+BIND_DNS['dpx-legacy']="cn=admin"
+BIND_DNS['dpx-prd']="cn=admin"
+BIND_DNS['dpx-dev']="cn=admin"
+BIND_DNS['spk-prd']="cn=admin"
+BIND_DNS['spk-dev']="cn=admin"
+
+declare -A BIND_PW_FILES=()
+BIND_PW_FILES['dpx-legacy']="${HOME}/.private/ldap-admin-wonl.txt"
+BIND_PW_FILES['dpx-prd']="${HOME}/.private/dirsrv-prd-dpx-admin-pwd-wonl.txt"
+BIND_PW_FILES['dpx-dev']="${HOME}/.private/dirsrv-dev-dpx-admin-pwd-wonl.txt"
+BIND_PW_FILES['spk-prd']="${HOME}/.private/dirsrv-live-spk-admin-pwd-wonl.txt"
+BIND_PW_FILES['spk-dev']="${HOME}/.private/dirsrv-stage-spk-admin-pwd-wonl.txt"
+
+declare -A SUFFIXES=()
+SUFFIXES['dpx-legacy']="o=isp"
+SUFFIXES['dpx-prd']="o=isp"
+SUFFIXES['dpx-dev']="o=isp"
+SUFFIXES['spk-prd']="dc=spk,dc=pixelpark,dc=net"
+SUFFIXES['spk-dev']="dc=spk,dc=pixelpark,dc=net"
+
+declare -a USERS=()
+
+detect_color
+
+DESCRIPTION=$( cat <<-EOF
+ Sets the value of inetUserStatus of the given user to 'Active', 'Inactive' or 'Deleted'.
+
+ EOF
+)
+
+TMP_LDIF_FILE=
+
+USER=
+INSTANCE=
+LDAP_URL=
+BIND_DN=
+BIND_PW_FILE=
+SUFFIX=
+USER_DN=
+USER_CN=
+USER_MAIL=
+USER_NAME=
+REQUESTED_STATUS=
+
+#------------------------------------------------------------------------------
+draw_line() {
+ if [[ "${QUIET}" == "y" ]] ; then
+ return 0
+ fi
+ echo "---------------------------------------------------"
+}
+
+#------------------------------------------------------------------------------
+empty_line() {
+ if [[ "${QUIET}" == "y" ]] ; then
+ return 0
+ fi
+ echo
+}
+
+#------------------------------------------------------------------------------
+usage() {
+
+ local inst_out=""
+ local inst=
+ local i=0
+
+ for inst in "${INSTANCES[@]}" ; do
+ i=$(( $i + 1 ))
+ if [[ "${i}" != "1" ]] ; then
+ if [[ "${i}" == "${#INSTANCES[*]}" ]] ; then
+ inst_out+=" and "
+ else
+ inst_out+=", "
+ fi
+ fi
+ inst_out+="'${inst}'"
+ done
+
+ cat <<-EOF
+ Usage: ${BASE_NAME} [Common Options] [-i INSTANCE] -i ...] <[-A] | [-I] | [-D]> USER1 [USER2 ...]
+ ${BASE_NAME} [-h|--help]
+ ${BASE_NAME} [-V|--version]
+
+ Options:
+ -i|--instance INSTANCE
+ The LDAP instance to use as the target of this script. If left empty, all instances are changed.
+ May be one or more of ${inst_out}.
+ -A|--active Set the user status to 'Active'. Mutually exclusive to '-I' and '-D'.
+ -I|--inactive Set the user status to 'Inactive'. Mutually exclusive to '-A' and '-D'.
+ -D|--deleted Set the user status to 'Deleted'. Mutually exclusive to '-A' and '-I'.
+
+ Common Options:
+ EOF
+
+ echo "${STD_USAGE_MSG}"
+
+}
+
+#------------------------------------------------------------------------------
+get_options() {
+
+ local tmp=
+ local short_options="i:AIDy${STD_SHORT_OPTIONS}"
+ local long_options="inst:,instance:,active,inactive,deleted,yes,${STD_LONG_OPTIONS}"
+ local inst=
+
+ set +e
+ tmp=$( getopt -o "${short_options}" --long "${long_options}" -n "${BASE_NAME}" -- "$@" )
+ ret="$?"
+ if [[ "${ret}" != 0 ]] ; then
+ echo "" >&2
+ echo -e "$( usage )" >&2
+ exit 1
+ fi
+ set -e
+
+ # Note the quotes around `$TEMP': they are essential!
+ eval set -- "${tmp}"
+ eval_common_options "$@"
+ if [[ "${DEBUG}" == 'y' ]] ; then
+ declare -p REMAINING_OPTS
+ declare -p REMAINING_ARGS
+ fi
+
+ local len="${#REMAINING_OPTS[*]}"
+ local i="0"
+ local j=
+ local arg=
+ while [[ "$i" -lt "${len}" ]] ; do
+
+ arg="${REMAINING_OPTS[$i]}"
+
+ case "${arg}" in
+ -i|--inst|--instance)
+ j=$(( $i + 1 ))
+ USED_INSTANCES+=("${REMAINING_OPTS[$j]}" )
+ i=$(( $i + 2 ))
+ ;;
+ -A|--active)
+ if [[ -n "${REQUESTED_STATUS}" ]] ; then
+ error "Requested status was already set to '${RED}${REQUESTED_STATUS}${NORMAL}'."
+ echo "" >&2
+ echo -e "$( usage )" >&2
+ exit 1
+ fi
+ REQUESTED_STATUS="Active"
+ i=$(( i + 1 ))
+ ;;
+ -I|--inactive)
+ if [[ -n "${REQUESTED_STATUS}" ]] ; then
+ error "Requested status was already set to '${RED}${REQUESTED_STATUS}${NORMAL}'."
+ echo "" >&2
+ echo -e "$( usage )" >&2
+ exit 1
+ fi
+ REQUESTED_STATUS="Inactive"
+ i=$(( i + 1 ))
+ ;;
+ -D|--deleted)
+ if [[ -n "${REQUESTED_STATUS}" ]] ; then
+ error "Requested status was already set to '${RED}${REQUESTED_STATUS}${NORMAL}'."
+ echo "" >&2
+ echo -e "$( usage )" >&2
+ exit 1
+ fi
+ REQUESTED_STATUS="Deleted"
+ i=$(( i + 1 ))
+ ;;
+ -y|--yes)
+ YES="y"
+ i=$(( i + 1 ))
+ ;;
+ *) echo -e "Internal error - option '${RED}${arg}${NORMAL} was wrong!"
+ exit 1
+ ;;
+ esac
+ done
+
+ for user in "${REMAINING_ARGS[@]}"; do
+ if [[ "${user}" == '--' ]] ; then
+ continue
+ fi
+ USERS+=( "${user}" )
+ done
+
+ if [[ "${#USED_INSTANCES[*]}" == 0 ]] ; then
+ for inst in "${INSTANCES[@]}" ; do
+ USED_INSTANCES+=( "${inst}" )
+ done
+ fi
+
+ local instances_ok='y'
+ for inst in "${USED_INSTANCES[@]}" ; do
+ if [[ ! -v "LDAP_URLS[${inst}]" ]] ; then
+ instances_ok='n'
+ error "Given instance '${RED}${inst}${NORMAL}' is invalid."
+ fi
+ done
+ if [[ "${instances_ok}" == "n" ]] ; then
+ echo >&2
+ echo -e "$( usage )" >&2
+ exit 1
+ fi
+
+ if [[ "${#USERS[*]}" == "0" ]] ; then
+ echo >&2
+ warn "No user to set inetUserStatus given."
+ echo >&2
+ echo -e "$( usage )" >&2
+ exit 1
+ fi
+
+ if [[ -z "${REQUESTED_STATUS}" ]] ; then
+ echo >&2
+ error "No requested inetUserStatus given."
+ echo >&2
+ echo -e "$( usage )" >&2
+ exit 1
+ fi
+
+
+ info "Setting ${CYAN}inetUserStatus${NORMAL} for all given users to '${GREEN}${REQUESTED_STATUS}${NORMAL}."
+
+ if [[ "${SIMULATE}" == "y" ]] ; then
+ echo
+ echo -e "${CYAN}---------------------------------------------${NORMAL}"
+ echo -e " ${YELLOW}Simulation mode${NORMAL}"
+ echo -e " ${CYAN}Nothing will be done in real.${NORMAL}"
+ echo -e "${CYAN}---------------------------------------------${NORMAL}"
+ sleep 0.5
+ fi
+
+}
+
+#------------------------------------------------------------------------------
+cleanup_tmp_file() {
+ if [[ -n "${LDIF_FILE}" ]] ; then
+ if [[ -e "${LDIF_FILE}" ]] ; then
+ debug "Removing temporary file '${CYAN}${LDIF_FILE}${NORMAL}' ..."
+ RM_force "${LDIF_FILE}"
+ fi
+ fi
+}
+
+#------------------------------------------------------------------------------
+yes_or_no() {
+
+ local msg="$1"
+ local timeout="5"
+ if [[ "$#" -gt 1 ]] ; then
+ timeout="$2"
+ fi
+
+ if [[ "${YES}" == "y" ]] ; then
+ return 0
+ fi
+
+ local answer=
+ debug "Trying to get an answer with a timeout of ${timeout} seconds."
+ printf "${msg}"
+ if read -t "${timeout}" answer ; then
+ debug "Got an answer: '${answer}'"
+ else
+ echo
+ return 1
+ fi
+
+ local first_letter=$( echo "${answer}" | tr '[:upper:]' '[:lower:]' | sed -e 's/^\(.\).*/\1/' )
+ if [[ "${first_letter}" == 'y' || "${first_letter}" == 'j' ]] ; then
+ return 0
+ else
+ return 1
+ fi
+
+}
+
+#------------------------------------------------------------------------------
+get_user_dn() {
+
+ debug "Trying to detect the DN uf user '${CYAN}${USER}${NORMAL}' ..."
+
+ if [[ ! -f "${BIND_PW_FILE}" ]] ; then
+ error "Did not found password file '${RED}${BIND_PW_FILE}${NORMAL}' of Bind DN '${CYAN}${BIND_DN}${NORMAL}' of LDAP instance '${GREEN}${INSTANCE}${NORMAL}'."
+ empty_line
+ exit 5
+ fi
+
+ USER_DN=''
+ USER_CN=
+ USER_MAIL=
+ USER_NAME=
+ filter="(&(objectClass=*)(uid=${USER}))"
+ cmd="ldapsearch -x -LLL -o ldif-wrap=no -H '${LDAP_URL}' "
+ cmd+="-b \"${SUFFIX}\" -x -D \"${BIND_DN}\" -y \"${BIND_PW_FILE}\" "
+ cmd+="\"${filter}\" dn cn mail uid"
+ # cmd+="\"${filter}\" dn cn mail | grep '^dn:' | sed -e 's/^dn:[ ][ ]*//i' | head -n 1"
+ debug "Executing: ${cmd}"
+ local user_info=$( eval ${cmd} )
+
+ local count=$( echo "${user_info}" | grep '^dn:' | wc -l )
+ if [[ "${count}" == "0" ]] ; then
+ warn "Did not found DN of uid '${YELLOW}${USER}${NORMAL}'."
+ return 1
+ fi
+ if [[ "${count}" -gt 1 ]] ; then
+ warn "User Id '${YELLOW}${USER}${NORMAL}' is not unique."
+ return 1
+ fi
+
+ USER_DN=$( echo "${user_info}" | grep '^dn:' | sed -e 's/^dn:[ ][ ]*//i' )
+ USER_CN=$( echo "${user_info}" | grep '^cn:' )
+ if echo "${USER_CN}" | grep -q '^cn::' ; then
+ USER_CN=$( echo "${USER_CN}" | sed -e 's/^cn::[ ][ ]*//i' | base64 -d )
+ else
+ USER_CN=$( echo "${USER_CN}" | sed -e 's/^cn:[ ][ ]*//i' )
+ fi
+ USER_MAIL=$( echo "${user_info}" | grep '^mail:' | sed -e 's/^mail:[ ][ ]*//i' | head -n 1 )
+
+ if [[ -n "${USER_CN}" ]] ; then
+ USER_NAME="${USER_CN}"
+ else
+ USER_NAME=$( echo "${user_info}" | grep '^uid:' | sed -e 's/^uid:[ ][ ]*//i' | head -n 1 )
+ fi
+
+ local question="Do you want to set inetUserStatus for User '${CYAN}${USER_NAME}${NORMAL}' (${CYAN}${USER_DN}${NORMAL}) [${RED}y${NORMAL}|${YELLOW}N${NORMAL}] ? "
+ if yes_or_no "${question}" ; then
+ info "Setting inetUserStatus for user '${CYAN}${USER_NAME}${NORMAL}' (${CYAN}${USER_DN}${NORMAL})."
+ return 0
+ fi
+ info "User '${CYAN}${USER_NAME}${NORMAL}' (${CYAN}${USER_DN}${NORMAL}) will be left untouched."
+ return 1
+
+}
+
+#------------------------------------------------------------------------------
+setting_user_status() {
+
+ local filter=
+ local cmd=
+ local user_info=
+ local cur_user_status=
+ local req_user_status=
+
+ info "Setting inetUserStatus of '${CYAN}${USER_NAME}${NORMAL}' to '${CYAN}${REQUESTED_STATUS}${NORMAL}' ..."
+
+ req_user_status=$( echo "${REQUESTED_STATUS}" | tr '[:upper:]' '[:lower:]' )
+
+ filter="(inetUserStatus=*)"
+ cmd="ldapsearch -x -LLL -o ldif-wrap=no -H '${LDAP_URL}' "
+ cmd+="-b \"${USER_DN}\" -s base -D \"${BIND_DN}\" -y \"${BIND_PW_FILE}\" "
+ cmd+="\"${filter}\" inetUserStatus"
+ debug "Executing: ${cmd}"
+ user_info=$( eval ${cmd} )
+ cur_user_status=$( echo "${user_info}" | \
+ grep -i '^inetUserStatus:' | \
+ sed -e 's/^[a-z]*: *//i' | \
+ tr '[:upper:]' '[:lower:]' )
+
+ debug "Cur_user_status: ${cur_user_status}, req_user_status: ${req_user_status}"
+
+ if [[ -z "${cur_user_status}" ]] ; then
+ warn "Entry '${YELLOW}${USER_DN}${NORMAL}' does not have the attribute '${CYAN}inetUserStatus${NORMAL}'."
+ return
+ fi
+ if [[ "${req_user_status}" == "${cur_user_status}" ]] ; then
+ info "Entry '${CYAN}${USER_DN}${NORMAL}' has already the inetUserStatus '${CYAN}${REQUESTED_STATUS}${NORMAL}'."
+ return
+ fi
+
+ cat > "${LDIF_FILE}" <<-EOF
+ dn: ${USER_DN}
+ changetype: modify
+ replace: inetUserStatus
+ inetUserStatus: ${REQUESTED_STATUS}
+ -
+
+ EOF
+
+ if [[ "${VERBOSE}" == "y" ]] ; then
+ debug "Resulting LDIF:"
+ cat "${LDIF_FILE}"
+ fi
+
+ cmd="ldapmodify -H \"${LDAP_URL}\" -x -D \"${BIND_DN}\" -y \"${BIND_PW_FILE}\""
+ cmd+=" -f \"$( readlink -f "${LDIF_FILE}" )\""
+ debug "Executing: ${cmd}"
+ if [[ "${SIMULATE}" != "y" ]] ; then
+ eval $cmd
+ fi
+ debug "Done."
+
+}
+
+#------------------------------------------------------------------------------
+perform_instance() {
+
+ empty_line
+ draw_line
+ info "Setting inetUserStatus of user '${GREEN}${USER}${NORMAL}' in LDAP instance '${GREEN}${INSTANCE}${NORMAL}'."
+ empty_line
+ sleep 2
+
+ if get_user_dn ; then
+ :
+ else
+ return 0
+ fi
+
+ debug "Continue ..."
+ setting_user_status
+
+}
+
+#------------------------------------------------
+main() {
+
+ get_options "$@"
+
+ debug "Creating temporary LDIF file ..."
+ LDIF_FILE=$( mktemp disable-user.XXXXXXXX.ldif )
+ debug "Temporary file is '${CYAN}${LDIF_FILE}${NORMAL}'."
+
+ trap cleanup_tmp_file INT TERM EXIT ABRT
+
+ empty_line
+ info "Checking existence of necessary password files ..."
+ local all_files_there="y"
+ for INSTANCE in "${USED_INSTANCES[@]}" ; do
+ BIND_PW_FILE="${BIND_PW_FILES[${INSTANCE}]}"
+ debug "Checking for '${CYAN}${BIND_PW_FILE}${NORMAL}'."
+ if [[ -f "${BIND_PW_FILE}" && -r "${BIND_PW_FILE}" ]] ; then
+ debug "Password file '${CYAN}${BIND_PW_FILE}${NORMAL}' exists and is readable."
+ else
+ error "Password file '${RED}${BIND_PW_FILE}${NORMAL}' does not exists or is not redable."
+ all_files_there="n"
+ fi
+ done
+ empty_line
+
+ if [[ "${all_files_there}" == "n" ]] ; then
+ exit 6
+ fi
+
+ for USER in "${USERS[@]}" ; do
+ for INSTANCE in "${USED_INSTANCES[@]}" ; do
+ LDAP_URL="${LDAP_URLS[${INSTANCE}]}"
+ BIND_DN="${BIND_DNS[${INSTANCE}]}"
+ BIND_PW_FILE="${BIND_PW_FILES[${INSTANCE}]}"
+ SUFFIX="${SUFFIXES[${INSTANCE}]}"
+ perform_instance
+ done
+ done
+
+ empty_line
+ info "Finished."
+
+}
+
+main "$@"
+
+# vim: et list