#!/usr/bin/env bash # Remove previous keys # base folder for all data BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/"; # config folder CONFIG_BASE="${BASE_FOLDER}../config/"; # previous public key SSH_PUBLIC_KEYS_PREVIOUS="${BASE_FOLDER}../ssh-public-keys/admin-previous/"; # list of admin user names, if username does not match this only update the user entry ADMIN_USERS=(admin ubuntu ec2-user) DRY_RUN=0; GO=0; HOST_ONLY=""; USER_ONLY=""; # while getopts ":h:u:ng" opt; do case "${opt}" in h) # hostname HOST_ONLY="${OPTARG}"; ;; u) # username USER_ONLY="${OPTARG}"; ;; n) # dry-run DRY_RUN=1; ;; g) # go GO=1; ;; \?) echo -e "\n Option does not exist: ${OPTARG}\n"; echo "-h override single host name"; echo "-u override user name for a host"; echo "-f force key change"; echo "-n dry run"; echo "-g flag for actual change call"; echo "" exit 1; ;; esac done if [ ! -d "${SSH_PUBLIC_KEYS_PREVIOUS}" ]; then echo "Missing ssh public keys previous folder: ${SSH_PUBLIC_KEYS_PREVIOUS}"; exit; fi # load config if [ ! -f "${CONFIG_BASE}settings.ini" ]; then echo "Missing 'settings.ini' file in ${CONFIG_BASE}"; exit; fi # shellcheck source=../config/settings.ini # shellcheck disable=SC1094 source <(grep "=" "${CONFIG_BASE}settings.ini" | sed 's/ *= */=/g') if [ -z "${key_age}" ]; then echo "A minimnum key age in days must be set in the settings"; exit; fi if [ -z "${server_list}" ]; then echo "No server list is defined in the settings"; exit; fi; # we must have "server_list" set and file must be in config folder if [ ! -f "${CONFIG_BASE}${server_list}" ]; then echo "Cannot find ${server_list} file in the config folder"; exit fi # abort if go not set if [ ${GO} -eq 0 ] && [ ${DRY_RUN} -eq 1 ]; then GO=1; elif [ ${GO} -eq 0 ]; then echo "No -g (go) parameter set. aborting. For testing set -n for dry run" exit; fi # default ssh command # -t is needed for systens when "Defaults requiretty" is set SSH="ssh -a -x -n"; remove_ssh_key() { AUTH_KEY_FILE="${1}"; PUB_KEY_FILE="${2}"; RMV_CHATTR_I="chattr -i" ADD_CHATTR_I="chattr +i" RMV_CHMOD_UW="chmod u-w" ADD_CHMOD_UW="chmod u+w" pub_key=$(cat "${PUB_KEY_FILE}"); # we need to escape for sed pub_key_escaped=$(printf '%s\n' "$pub_key" | sed -e 's/[]\/$*.^[]/\\&/g'); # the -z `tail ...` checks for a trailing newline. The echo adds one if was missing (from ssh-copy-id) UNINSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF if [ -f "${AUTH_KEY_FILE}" ] && grep "${pub_key}" "${AUTH_KEY_FILE}" >> /dev/null; then ${RMV_CHATTR_I} "${AUTH_KEY_FILE}"; ${ADD_CHMOD_UW} "${AUTH_KEY_FILE}"; sed -i "/${pub_key_escaped}/d" "${AUTH_KEY_FILE}"; ${RMV_CHMOD_UW} "${AUTH_KEY_FILE}"; ${ADD_CHATTR_I} "${AUTH_KEY_FILE}"; else echo "[!] Already removed"; fi; EOF ); # to defend against quirky remote shells: use 'exec sh -c' to get POSIX; printf "exec sudo sh -c '%s'" "${UNINSTALLKEYS_SH}" } uninstall_ssh_key() { HOSTNAME="${1}"; USERNAME="${2}"; PUB_KEY_FILE="${3}"; AUTH_KEY_FILE="${4}"; echo "[.] Remove from auth file: ${AUTH_KEY_FILE}"; if [ ${DRY_RUN} -eq 0 ]; then # find the pub key in the file and remove this line only ${SSH} "${USERNAME}"@"${HOSTNAME}" "$(remove_ssh_key "${AUTH_KEY_FILE}" "${PUB_KEY_FILE}")" else echo "${SSH} \"${USERNAME}\"@\"${HOSTNAME}\" \"\$(remove_ssh_key \"${AUTH_KEY_FILE}\" \"${PUB_KEY_FILE}\")\""; fi } # find last public in remote server and remove it while read -r line; do if [[ "${line}" =~ ^\# ]]; then continue; fi # hostname is on pos 1 hostname=$(echo "${line}" | cut -d "," -f 1); # if hostname opt set and not matching skip if [ -n "${HOST_ONLY}" ] && [ "${HOST_ONLY}" != "${hostname}" ]; then continue; fi # login user name username=$(echo "${line}" | cut -d "," -f 2); # if username opt set and not matching skip if [ -n "${USER_ONLY}" ] && [ "${USER_ONLY}" != "${username}" ]; then continue; fi # flags: (not used at the moment) flags=$(echo "${line}" | cut -d "," -f 3); # auth key settings (in front of auth key) # settings=$(echo "${line}" | cut -d "," -f 4); # ssh key names SSH_KEY_PUB_FILE="${hostname}_${username}.pem.pub"; # previous public key does not exist, skip if [ ! -f "${SSH_PUBLIC_KEYS_PREVIOUS}${SSH_KEY_PUB_FILE}" ]; then echo "[!] No previous public key file ${SSH_KEY_PUB_FILE} for ${username}@${hostname}"; echo "[_] ............... SKIP"; continue; fi echo "[-] Remove previous key for: ${username}@${hostname} with flags '${flags}'"; # find in master key and $admin user if [[ ${ADMIN_USERS[*]} =~ $username ]]; then # find in "/etc/ssh/authorized_keys--master"; uninstall_ssh_key "${hostname}" "${username}" "${SSH_PUBLIC_KEYS_PREVIOUS}${SSH_KEY_PUB_FILE}" "/etc/ssh/authorized_keys--master"; fi uninstall_ssh_key "${hostname}" "${username}" "${SSH_PUBLIC_KEYS_PREVIOUS}${SSH_KEY_PUB_FILE}" "/etc/ssh/authorized_keys/${username}" # remove old key echo "[-] Remove previous public key: ${SSH_KEY_PUB_FILE}"; if [ ${DRY_RUN} -eq 0 ]; then rm "${SSH_PUBLIC_KEYS_PREVIOUS}${SSH_KEY_PUB_FILE}"; else echo "rm \"${SSH_PUBLIC_KEYS_PREVIOUS}${SSH_KEY_PUB_FILE}\";"; fi; echo "[=] ............... DONE"; done <<<"$(sed 1d "${CONFIG_BASE}${server_list}")"; # __END__