#!/usr/bin/env bash # Rename user # - rename user name # - rename home folder + owner # - rename public key file in /etc/ssh/ # - rename in user_list.txt # - rename created public key file TEST=0; # do not run any actions OLD_USERNAME=""; NEW_USERNAME=""; while getopts ":to:n:" opt; do case "${opt}" in t) # test TEST=1; ;; o) # old-user if [ -z "${OLD_USERNAME}" ]; then OLD_USERNAME="${OPTARG}"; fi; ;; n) # new-user if [ -z "${NEW_USERNAME}" ]; then NEW_USERNAME="${OPTARG}"; fi; ;; \?) echo -e "\n Option does not exist: ${OPTARG}\n"; echo "Use -t for test"; echo "-o: Current user"; echo "-n: New username"; exit 1; ;; esac; done; shift "$((OPTIND-1))" if [ "$(whoami)" != "root" ]; then if [ ${TEST} -eq 0 ]; then echo "Script must be run as root user"; exit; else echo "!!!! Script must be run as root user !!!!"; fi; fi; error=0; host=$(hostname); # timestamp=$(date +%Y%m%d-%H%M%S); # character to set getween info blocks separator="#"; # base folder for all data BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/"; ROOT_FOLDER="${BASE_FOLDER}../"; SSH_KEYGEN_FOLDER_CREATED_PUB='ssh-keygen-created-pub/'; input_file='user_list.txt'; user_list_file="${ROOT_FOLDER}${input_file}"; default_ssh_keytype='ed25519'; ssh_keytype=''; # ignore users (root and admin users) ignore_users=('root' 'ec2-user' 'ubuntu' 'admin'); # detect ssh authorized_keys setting SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=''; # SSH_AUTHORIZED_FILE=''; # shellcheck disable=SC2013 for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do if echo "$cf" | grep -q "%u"; then SSH_CENTRAL_AUTHORIZED_FILE_FOLDER="${cf/%%u//}"; if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}"; exit; fi; fi; done; if [ ! -f "${user_list_file}" ]; then echo "${input_file} is missing"; error=1; fi; if [ -z "${OLD_USERNAME}" ] || [ -z "${NEW_USERNAME}" ]; then echo "[!!!] Current and new username must be provided"; error=1; fi; if [ "${OLD_USERNAME}" = "${NEW_USERNAME}" ]; then echo "[!!!] Current and new username cannot be the same"; error=1; fi; if ! [[ "${NEW_USERNAME}" =~ ^[a-z0-9]+([.a-z0-9_-]+[a-z0-9])?$ ]]; then echo "User name can only be a-z 0-9 - _ . and cannot start or end with - . or _: ${NEW_USERNAME}"; error=1; fi; # skip ignore users, note that if a user is not in the sshallow list anyway # we skip them too, this is just in case check if [[ " ${ignore_users[*]} " =~ [[:space:]]${OLD_USERNAME}[[:space:]] ]]; then echo "[!] User ${OLD_USERNAME} is in the ignore user list"; error=1; fi; if [[ " ${ignore_users[*]} " =~ [[:space:]]${NEW_USERNAME}[[:space:]] ]]; then echo "[!] User ${NEW_USERNAME} is in the ignore user list"; error=1; fi; # user must exist in user_list.txt and /etc/passwd # if missing in or another do not continue if ! id "${OLD_USERNAME}" &>/dev/null; then # not in passwd echo "[!!!] User ${OLD_USERNAME} does not exist in /etc/passwd"; error=1; fi; if id "${NEW_USERNAME}" &>/dev/null; then # not in passwd echo "[!!!] User ${NEW_USERNAME} exists in /etc/passwd"; error=1; fi; if [ -f "${user_list_file}" ]; then user_list_entry=$(grep "${OLD_USERNAME}" "${user_list_file}"); if [ -z "${user_list_entry}" ]; then echo "[!!!] User ${OLD_USERNAME} does not exist in user_list.txt file"; error=1; fi; # if the old user exists but as DELETED -> no go if ! echo "${user_list_entry}" | grep -q "#DELETED-"; then echo "[!!!] User ${OLD_USERNAME} has been flagged as deleted"; error=1; fi; # if new user name already exists in user list file for whatever reason if grep -q "${NEW_USERNAME}" "${user_list_file}"; then echo "[!!!] User ${NEW_USERNAME} exists in user_list.txt file"; error=1; fi; fi; # exit on any error if [ $error -eq 1 ]; then exit; fi; # log file LOG="${BASE_FOLDER}/../log/user_management.log"; function write_log() { text="${1}"; do_echo="${2}"; log_prefix=""; # log prefix if [ ${TEST} -eq 1 ]; then log_prefix="TEST"; fi; if [ -n "${log_prefix}" ]; then log_prefix="[${log_prefix}] "; fi; echo "[$(date +"%F %T")] [$0] ${log_prefix}${text}" >> "${LOG}"; if [ "${do_echo}" = "1" ]; then echo "${text}"; fi; } write_log "START SCRIPT RUN"; # parse user list entry for group/hostname/ssh type key to build ssh key list # POS 3: groups _group=$(echo "${user_list_entry}" | cut -d ";" -f 3 | tr '[:upper:]' '[:lower:]' | tr -d ' '); group=$(echo "${_group}" | cut -d "," -f 1); # POS 6: override host name, lowercase and spaces removed _hostname=$(echo "${user_list_entry}" | cut -d ";" -f 6 | tr '[:upper:]' '[:lower:]' | tr -d ' '); if [ -z "${_hostname}" ]; then hostname=${host}; else hostname=${_hostname}; fi; # POS 7: ssh keytype override _ssh_keytype=$(echo "${user_list_entry}" | cut -d ";" -f 7 | tr '[:upper:]' '[:lower:]' | tr -d ' '); if [ "${_ssh_keytype}" = "rsa" ]; then ssh_keytype="${_ssh_keytype}"; else ssh_keytype=${default_ssh_keytype}; fi; write_log "* Rename ${OLD_USERNAME} to ${NEW_USERNAME}" "1"; old_home_dir=$(getent passwd "${OLD_USERNAME}" | cut -d: -f6); new_home_dir=$(echo "${old_home_dir}" | sed -e "s/\/${OLD_USERNAME}$/\/${NEW_USERNAME}/"); # rename user if [ $TEST -eq 0 ]; then echo "usermod with ${new_home_dir}"; usermod -l "${NEW_USERNAME}" -m -d "${new_home_dir}" "${OLD_USERNAME}"; else echo "$> usermod -l ${NEW_USERNAME} -m -d \"${new_home_dir}\" ${OLD_USERNAME};"; fi # check that home folder is renamed and owned by new user # check if spool exists if [ -f "/var/spool/mail/${OLD_USERNAME}" ]; then if [ $TEST -eq 0 ]; then echo "rename to /var/spool/mail/${NEW_USERNAME}"; mv "/var/spool/mail/${OLD_USERNAME}" "/var/spool/mail/${NEW_USERNAME}"; else echo "$> mv \"/var/spool/mail/${OLD_USERNAME}\" \"/var/spool/mail/${NEW_USERNAME}\";"; fi fi; # check if crontab exists if [ -f "/var/spool/cron/crontabs/${OLD_USERNAME}" ]; then if [ $TEST -eq 0 ]; then echo "rename to /var/spool/cron/crontabs/${NEW_USERNAME}"; mv "/var/spool/cron/crontabs/${OLD_USERNAME}" "/var/spool/cron/crontabs/${NEW_USERNAME}"; else echo "$> mv \"/var/spool/cron/crontabs/${OLD_USERNAME}\" \"/var/spool/cron/crontabs/${NEW_USERNAME}\";"; fi fi; # public key files user must be renamed OLD_SSH_AUTHORIZED_FILE="${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}${OLD_USERNAME}"; NEW_SSH_AUTHORIZED_FILE="${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}${NEW_USERNAME}"; if [ -f "${OLD_SSH_AUTHORIZED_FILE}" ]; then if [ $TEST -eq 0 ]; then write_log "rename to ${NEW_SSH_AUTHORIZED_FILE}" "1"; chattr -i "${OLD_SSH_AUTHORIZED_FILE}"; mv "${OLD_SSH_AUTHORIZED_FILE}" "${NEW_SSH_AUTHORIZED_FILE}"; chattr +i "${NEW_SSH_AUTHORIZED_FILE}"; else echo "$> chattr -i \"${OLD_SSH_AUTHORIZED_FILE}\";"; echo "$> mv \"${OLD_SSH_AUTHORIZED_FILE}\" \"${NEW_SSH_AUTHORIZED_FILE}\";"; echo "$> chattr +i \"${NEW_SSH_AUTHORIZED_FILE}\";"; fi; else write_log "[?] ${OLD_SSH_AUTHORIZED_FILE} is missing" "1"; fi; # rename keygen public file OLD_ssh_keygen_pub="${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}${hostname}${separator}${group}${separator}${OLD_USERNAME}${separator}${ssh_keytype}.pem.pub"; NEW_ssh_keygen_pub="${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}${hostname}${separator}${group}${separator}${NEW_USERNAME}${separator}${ssh_keytype}.pem.pub"; if [ -f "${OLD_ssh_keygen_pub}" ]; then if [ $TEST -eq 0 ]; then write_log "rename to ${NEW_ssh_keygen_pub}" "1"; mv "${OLD_ssh_keygen_pub}" "${NEW_ssh_keygen_pub}"; else echo "$> mv \"${OLD_ssh_keygen_pub}\" \"${NEW_ssh_keygen_pub}\";"; fi; else write_log "[?] ${OLD_ssh_keygen_pub} is missing" "1"; fi; # rename entry in user list txt file if [ $TEST -eq 0 ]; then echo "update ${user_list_file}"; sed -i -e "s/^\([A-Za-z0-9]\{1,\}\);${OLD_USERNAME};/\1;${NEW_USERNAME};/" "${user_list_file}"; else # just as is print the sed command from above # shellcheck disable=SC2028 echo "$> sed -i -e \"s/^\([A-Za-z0-9]\{1,\}\);${OLD_USERNAME};/\1;${NEW_USERNAME};/\" \"${user_list_file}\";"; fi; # __END__