#!/usr/bin/env bash # shellcheck disable=SC2059 # check if we need to move the users authorized keys to the central location TEST=1; LIST=0; SKIP_USERS=(); while getopts ":gls:" opt; do case "${opt}" in g) # go # default we test TEST=0; ;; s) # skip SKIP_USERS+=("${OPTARG}"); ;; l) # list LIST=1; ;; \?) echo -e "\n Option does not exist: ${OPTARG}\n"; echo "Use -g for go (run) and -s for users to skip"; exit 1; ;; esac; done; # check if authorized keys is actually enabled # detect ssh authorized_keys setting SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=''; SSH_MASTER_AUTHORIZED_FILE=''; # 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 [ -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then echo "No central authorized_keys file detected, no change check needed"; exit; fi; # shellcheck disable=SC2013 for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep -- "--master"); do if ! echo "${cf}" | grep -q -- "--master"; then SSH_MASTER_AUTHORIZED_FILE="${cf}"; if [ ! -f "${SSH_MASTER_AUTHORIZED_FILE}" ]; then echo "ssh master authorized_file could not be found: ${SSH_MASTER_AUTHORIZED_FILE}"l exit; fi; fi; done; if [ -z "${SSH_MASTER_AUTHORIZED_FILE}" ]; then echo "No master authorized_key file detected, no change check needed"; exit; fi; echo "SSH Master Authorized Key file: ${SSH_MASTER_AUTHORIZED_FILE}"; echo "SSH Authorized Keys file folder: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}"; if [ ${LIST} -eq 1 ]; then ls -l "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}"; lsattr "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}"; exit; fi; # base folder BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/"; # output printf PRINTF_INFO="%-8s [%3s]: %-25s: %s\n"; # list of user accounts we will never touch NO_ACTION=(root); # move, but must check that master is set # master key is the first in the authorized keys list for the below users MASTER_KEY=(admin ec2-user ubuntu); # skip user file IGNORE_USER_FILE="../config/authorized_key_location_change.ignore" # list of users to skip from file IGNORE_USER=(); if [ -f "${BASE_FOLDER}${IGNORE_USER_FILE}" ]; then readarray -t IGNORE_USER < "${BASE_FOLDER}${IGNORE_USER_FILE}"; echo "Reading ${IGNORE_USER_FILE}"; fi; LOG="${BASE_FOLDER}/../log/user_management.log"; function write_log() { text="${1}"; do_echo="${2}"; log_prefix=""; # log prefix for testing if [ ${TEST} -eq 1 ]; then log_prefix="[TEST] "; fi; # write log not in info run echo "[$(date +"%F %T")] [$0] ${log_prefix}${text}" >> "${LOG}"; if [ "${do_echo}" = "1" ]; then echo "${text}"; fi; } write_log "START SCRIPT RUN"; # loop over passwd file # if not in no action then check if .ssh/authorized_keys file exists cut -d ":" -f 1,6 /etc/passwd | while read -r user_home; do username=$(echo "${user_home}" | cut -d ":" -f 1); master_user=0; # skip admin usernames if [[ " ${NO_ACTION[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then printf "${PRINTF_INFO}" "NO ACT" "!" "${username}" "user in NO ACTION list"; write_log "[NO ACT] ${username} in NO ACTION list"; continue; fi; if [[ " ${SKIP_USERS[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then printf "${PRINTF_INFO}" "SKIP" "*" "${username}" "skip forced via command line"; write_log "[SKIP] ${username} skip forced via command line"; continue; fi; if [[ " ${IGNORE_USER[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then printf "${PRINTF_INFO}" "SKIP" "**" "${username}" "skip from ignore config file"; write_log "[SKIP] ${username} skip from ignore config file"; continue; fi; home_folder=$(echo "${user_home}" | cut -d ":" -f 2); # skip no .ssh/authorized_ekys if [ ! -f "${home_folder}/.ssh/authorized_keys" ]; then # but do we have an auth folder, if yes -> exist skip if [ -f "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}" ]; then printf "${PRINTF_INFO}" "DONE" "." "${username}" "already moved"; write_log "[DONE] ${username} already moved"; else printf "${PRINTF_INFO}" "IGNORE" "?" "${username}" "no authorized_keys file"; write_log "[IGNORE] ${username} no authorized_keys file"; fi; continue; fi; # check those keys are in the master key list if [[ " ${MASTER_KEY[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then master_user=1; ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_MASTER_AUTHORIZED_FILE}"); if [ -n "${ssh_key_diff}" ]; then printf "${PRINTF_INFO}" "ABORT" "!!!" "${username}" "authorized key is not matching the master key file"; write_log "[ABORT] ${username} authorized key is not matching the master key file"; exit; fi; fi; # check if this user public key(s) exist in AuthorizedKeysFile target if [ -f "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}" ]; then ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"); if [ -z "${ssh_key_diff}" ]; then printf "${PRINTF_INFO}" "REMOVE" "-" "${username}" ".ssh/authorized_keys"; write_log "[REMOVE] ${username} .ssh/authorized_keys"; if [ ${master_user} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then rm "${home_folder}/.ssh/authorized_keys"; else echo "$> rm \"${home_folder}/.ssh/authorized_keys\""; fi; else write_log "[!] No delete for master user, must be done manually" "1"; fi; continue; fi; # No update, alert printf "${PRINTF_INFO}" "DIFF" "???" "${username}" "Different authorized keys in home dir, SKIPPED"; write_log "[DIFF] ${username} Different authorized keys in home dir, SKIPPED"; continue; fi; printf "${PRINTF_INFO}" "MOVE" ">" "${username}" "Move SSH Key to central location"; write_log "[MOVE] ${username} Move SSH Key to central location"; # move public keys over if [ ${TEST} -eq 0 ]; then cat "${home_folder}/.ssh/authorized_keys" > "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"; # secure new folder: chown/chmod/chattr chown "${username}" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"; chmod 400 "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"; chattr +i "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"; # confirm ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"); if [ -n "${ssh_key_diff}" ]; then printf "${PRINTF_INFO}" "ERROR" "!!!" "${username}" "Move problem ${ssh_key_diff}"; write_log "[ERROR] ${username} Move problem ${ssh_key_diff}"; break; fi; # remove home .ssh/authorized_keys (do not remove folder) if [ ${master_user} -eq 0 ]; then rm "${home_folder}/.ssh/authorized_keys"; else write_log "=> No delete for master user, must be done manually" "1"; fi; else echo "[START] ====>"; echo "$> cat \"${home_folder}/.ssh/authorized_keys\" > \"${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}\""; echo "$> chown ${username} \"${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}\""; echo "$> chmod 400 \"${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}\""; echo "$> chattr +i \"${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}\""; if [ ${master_user} -eq 0 ]; then echo "$> rm \"${home_folder}/.ssh/authorized_keys\""; else echo "[!] No delete for master user, must be done manually"; fi; echo "[END ] ====>"; fi; done; # __END__