AWS user account management scripts updates

- start option for create users (-g)
- delete user script
- update documentation
- user lock user script in check user flow output
- create user has check for valid username/group name
This commit is contained in:
Clemens Schwaighofer
2023-08-07 07:29:24 +09:00
parent eb194c2f1c
commit 571ddcc717
10 changed files with 323 additions and 47 deletions

View File

@@ -8,7 +8,7 @@ SKIP_USERS=();
while getopts ":gls:" opt; do
case "${opt}" in
g|go)
# default we
# default we test
TEST=0;
;;
s|skip)

View File

@@ -16,8 +16,7 @@ max_age_create=30;
# one day in seconds
day=86400;
# delete account strings
delete_accounts="";
user_group_tpl="gpasswd -d %s %s;gpasswd -a %s %s;";
lock_accounts="";
# log base folder
LOG="${BASE_FOLDER}/../log";
# auth log file user;date from collect_login_data script
@@ -48,7 +47,7 @@ echo "Checking Group : ${ssh_group}";
continue;
fi;
account_age=0;
delete_user=0;
lock_user=0;
out_string="";
#echo "* Checking user ${username}";
# check user create time, if we have set it in comment
@@ -80,7 +79,7 @@ echo "Checking Group : ${ssh_group}";
last_login=$(awk '{printf("%.0f\n",($1-$2)/$3)}' <<<"${now} ${last_login_date} ${day}");
if [ ${last_login} -gt ${max_age_login} ]; then
out_string="[!] last ssh log in ${last_login} days ago";
delete_user=1;
lock_user=1;
else
out_string="OK [ssh]";
fi;
@@ -93,7 +92,7 @@ echo "Checking Group : ${ssh_group}";
last_login=$(awk '{printf("%.0f\n",($1-$2)/$3)}' <<<"${now} ${last_login_date} ${day}");
if [ ${last_login} -gt ${max_age_login} ]; then
out_string="[!] last terminal log in ${last_login} days ago";
delete_user=1;
lock_user=1;
else
out_string="OK [lastlog]";
fi;
@@ -105,7 +104,7 @@ echo "Checking Group : ${ssh_group}";
account_age=$(awk '{printf("%.0f\n",($1-$2)/$3)}' <<<"${now} ${user_create_date} ${day}");
if [ ${account_age} -gt ${max_age_create} ]; then
out_string="[!] Never logged in, account created ${account_age} days ago";
delete_user=1;
lock_user=1;
else
out_string="OK [first login]";
fi;
@@ -113,8 +112,8 @@ echo "Checking Group : ${ssh_group}";
out_string="[!!!] Never logged in and we have no create date";
fi;
# build delete output
if [ ${delete_user} = 1 ]; then
delete_accounts="${delete_accounts}"$(printf "${user_group_tpl}" "${username}" "${ssh_group}" "${username}" "${ssh_reject_group}")$'\n';
if [ ${lock_user} = 1 ]; then
lock_accounts="${lock_accounts} ${username}"
fi;
printf "* Checking user %-20s: %s\n" "${username}" "${out_string}";
done;
@@ -124,11 +123,11 @@ echo "Showing current SSH Reject users:"
for user in $(cat /etc/group|grep "${ssh_reject_group}:" | cut -d ":" -f 4 | sed -e 's/,/ /g'); do
echo "${user}";
done;
if [ ! -z "${delete_accounts}" ]; then
if [ ! -z "${lock_accounts}" ]; then
echo "--------------------->"
echo "% Run list below to move users to reject ssh group";
echo "% Run script below to move users to reject ssh group";
echo "";
echo "${delete_accounts}";
echo "bin/lock_user.sh ${lock_accounts}";
fi;
echo "[END] ===============>"

View File

@@ -25,10 +25,13 @@
# They pem pub key must follow the set rules above
# SET TO 1 to TEST [will not create user/group/folder]
TEST=0; # no creation except ssh keys
TEST=0; # no actions will be run
INFO=0; # no creation of anything, just print info strings
GO=1; # without this flag the script will exit with an info box
while getopts ":tih:" opt; do
case "${opt}" in
g|go)
GO=1;
t|test)
TEST=1;
;;
@@ -41,6 +44,7 @@ while getopts ":tih:" opt; do
\?)
echo -e "\n Option does not exist: ${OPTARG}\n";
echo "Use -t for test and -i for info";
echo "Use -g for actually creation run";
echo "Override default /home/ folder location with -h <base>";
exit 1;
;;
@@ -153,6 +157,14 @@ if [ $(whoami) != "root" ]; then
echo "!!!! Script must be run as root user !!!!";
fi;
fi;
# exit if not -g parameter set
if [ $GO -eq 0 ]; then
echo "Script has to be run with -g option for actual user creation.";
echo "It is recommended to run -t for testing prior to user creation.";
exit;
fi;
# create users
cat "${ROOT_FOLDER}${input_file}" |
while read i; do
@@ -162,6 +174,13 @@ while read i; do
fi;
# POS 2: make lower case, remove spaces
username=$(echo "${i}" | cut -d ";" -f 2 | tr A-Z a-z | tr -d ' ');
# check username is alphanumeric with .
if ! [[ "${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 _: ${username}";
if [ ${TEST} -eq 0 ]; then
break;
fi;
fi;
# POS 3: groups
_group=$(echo "${i}" | cut -d ";" -f 3 | tr A-Z a-z | tr -d ' ');
group=$(echo "${_group}" | cut -d "," -f 1);
@@ -175,7 +194,9 @@ while read i; do
fi;
if [ $ssh_forward_ok -eq 0 ] && [ "${ssh_access_type}" = "forward" ]; then
echo "[!!!] sshforward group does not exsts, cannot set user ${username}";
break;
if [ ${TEST} -eq 0 ]; then
break;
fi;
fi;
ssh_group="ssh${ssh_access_type}";
# sshallow group is always added
@@ -206,7 +227,21 @@ while read i; do
if [ -z "${username}" ] || [ -z "${_group}" ]; then
echo "[!!!!!] Missing user or group entry for ${username}/${_group}";
echo "[*** ABORT RUN ***]"
break;
if [ ${TEST} -eq 0 ]; then
break;
fi;
else
group_error=0;
# check group names valid
for create_group in ${_group//,/ }; do
if ! [[ "${create_group}" =~ ^[a-z0-9]+([a-z0-9_-]+[a-z0-9])?$ ]]; then
echo "Group name can only be a-z 0-9 - _ and cannot start or end with - or _: ${create_group}";
group_error=1;
fi;
done;
if [ $group_error -eq 1 ] && [ ${TEST} -eq 0 ]; then
break;
fi;
fi;
# SSH file name part without folder
ssh_keygen_id="${hostname}${separator}${group}${separator}${username}${separator}${ssh_keytype}.pem";

185
bin/delete_user.sh Executable file
View File

@@ -0,0 +1,185 @@
#!/usr/bin/env bash
# Delete user
# - Backup
# - delete user
# - delete home
# - remove ssh-keygen-created-pub files
# - remove ssh central auth data if exits
# - update user_list.txt and comment (#) line for this user
# - write delete log
# This will permaently remove the user
TEST=0; # do not run any actions
GO=1; # without this flag the script will exit with an info box
BACKUP=1;
while getopts ":tih:" opt; do
case "${opt}" in
g|go)
GO=1;
;;
t|test)
TEST=1;
;;
b|nobackup)
BACKUP=0;
;;
\?)
echo -e "\n Option does not exist: ${OPTARG}\n";
echo "Use -t for test";
echo "Use -g for actually creation run";
echo "Use -b to not make a backup of the home folder and public key"
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;
if [ $# -eq 0 ]; then
echo "Must give at least one user name";
exit;
fi;
# check tar, bzip2 is installed if backup = 1
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}../";
backup_folder="${BASE_FOLDER}../backup/";
SSH_KEYGEN_FOLDER_CREATED_PUB='ssh-keygen-created-pub/';
input_file='user_list.txt';
user_list_file="${root_folder}${input_file}";
# log file
LOG="${BASE_FOLDER}/../log/delete_user."$(date +"%F_%H%m%S");
if [ ${TEST} -eq 0 ]; then
LOG="${LOG}.log";
else
LOG="${LOG}.test.log";
fi;
# 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='';
for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do
if [ ! -z $(echo "${cf}" | grep "%u") ]; then
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=$(echo "${cf}" | sed -e 's/%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";
exit;
fi;
# $1 ... $n
for username in "$@"; do
# skip if there is an option hidden
if [[ ${_arg:0:1} = "-" ]]; then
continue;
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[*]} " =~ " ${username} " ]]; then
echo "[!] User ${username} is in the ignore user list";
continue;
fi;
# user must exist in user_list.txt and /etc/passwd
# if missing in or another do not continue
if ! id "${username}" &>/dev/null; then
# not in passwd
echo "[!!!] User ${username} does not exist in /etc/passwd";
if [ ${TEST} -eq 0 ]; then
break;
fi;
fi;
user_list_entry=$(grep "${username}" "${user_list_file}");
if [ -z "${user_list_entry}" ]; then
echo "[!!!] User ${username} does not exist in user_list.txt file";
if [ ${TEST} -eq 0 ]; then
break;
fi;
elif [[ "${user_list_entry}" =~ ^#DELETED ]]; then
echo "[!!!] User ${username} is flagged as deleted in user_list.txt file";
if [ ${TEST} -eq 0 ]; then
break;
fi;
fi;
echo "=> Delete: ${username}";
# ssh authorized file
SSH_AUTHORIZED_FILE="${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}${username}";
# make backup from /home
if [ ${BACKUP} -eq 1 ]; then
home_folder=$(getent passwd ${username} | cut -d ":" -f 6);
backup_file="${backup_folder}${host}${separator}${username}.${timestamp}.tar.bz2";
files_list="${home_folder}";
if [ -f "${SSH_AUTHORIZED_FILE}" ]; then
files_list="${files_list} ${SSH_AUTHORIZED_FILE}";
fi;
echo "[0] Backup ${files_list} to ${backup_file}";
if [ ${TEST} -eq 0 ]; then
tar cfjp "${backup_file}" ${file_list};
else
echo "$> tar cfjp \"${backup_file}\" ${files_list};";
fi;
fi;
echo "[1] Remove user + home dir";
if [ ${TEST} -eq 0 ]; then
userdel -r ${username}
else
echo "$> userdel -r ${username}";
fi;
# remove ssh files in pub
echo "[2] Remove SSH Public key";
# Note, we keep the public key in the -created-pub folder
if [ -f "${SSH_AUTHORIZED_FILE}" ]; then
if [ ${TEST} -eq 0 ]; then
chattr -i "${SSH_AUTHORIZED_FILE}";
rm "${SSH_AUTHORIZED_FILE}";
else
echo "$> chattr -i \"${SSH_AUTHORIZED_FILE}\";";
echo "$> rm \"${SSH_AUTHORIZED_FILE}\";"
fi;
else
# Not critical error
echo "[?] Cannot find ${SSH_AUTHORIZED_FILE}";
fi;
# Update user_list.txt file and add # for the line
echo "[3] Update user_list.txt file";
# eg n;foo -> #DELETED-YYYYMMDD_HHmmss:n;foo ...
delete_date=$(date +%Y%m%d_%H%M%S)
if [ ${TEST} -eq 0 ]; then
sed -i -e "s/^\([A-Za-z0-9]\{1,\};${username};\)/#DELETED-${delete_date}:\1/" "${user_list_file}";
else
echo "$> sed -i -e \"s/^\([A-Za-z0-9]\{1,\};${username};\)/#DELETED-${delete_date}:\1/\" \"${user_list_file}\";";
fi;
echo $(date +"%F %T")";${host};${username}" >> "${LOG}";
done;
# __END__

View File

@@ -52,17 +52,17 @@ for username in "$@"; do
# 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[*]} " =~ " ${username} " ]]; then
echo "[!] User $username is in the ignore user list";
echo "[!] User ${username} is in the ignore user list";
continue;
fi;
# check that user exists in passwd
if ! id "${username}" &>/dev/null; then
echo "[!] User $username does not exists in /etc/passwd file";
echo "[!] User ${username} does not exists in /etc/passwd file";
continue;
fi;
# if not check if in reject list
if id -nGz "${username}" | grep -qzxF "${ssh_reject_group}"; then
echo "[.] User $username already in the ${ssh_reject_group} list";
echo "[.] User ${username} already in the ${ssh_reject_group} list";
continue;
fi;
# check if user is in sshallow/forward list
@@ -73,14 +73,14 @@ for username in "$@"; do
# if user is in ssh allow group and ALSO in ssh forward group -> bad
if id -nGz "${username}" | grep -qzxF "${ssh_forward_group}"; then
if [ ! -z "${ssh_remove_group}" ]; then
echo "[!!!! ERROR !!!!] User $username exists in both ${ssh_allow_group} and ${ssh_forward_group} group which should not be allowed. Remove user from one group and run script again.";
echo "[!!!! ERROR !!!!] User ${username} exists in both ${ssh_allow_group} and ${ssh_forward_group} group which should not be allowed. Remove user from one group and run script again.";
break;
fi;
ssh_remove_group="${ssh_forward_group}";
fi;
if [ ! -z "${ssh_remove_group}" ]; then
# remove user from ssh group and add to reject groups
echo "[*] User $username will be removed from ${ssh_remove_group}";
echo "[*] User ${username} will be removed from ${ssh_remove_group}";
if [ ${TEST} -eq 1 ]; then
printf "${user_group_tpl}" "${username}" "${ssh_remove_group}" "${username}" "${ssh_reject_group}";
else
@@ -89,7 +89,7 @@ for username in "$@"; do
fi;
else
# skip not ssh user
echo "[?] User $username not in any ssh allow/foward groups";
echo "[?] User ${username} not in any ssh allow/foward groups";
fi;
done;

43
bin/rename_user.sh Normal file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# Rename user
# - rename user name
# - rename home folder + owner
# - rename public key file in /etc/ssh/
TEST=0; # do not run any actions
GO=1; # without this flag the script will exit with an info box
BACKUP=1;
while getopts ":tih:" opt; do
case "${opt}" in
g|go)
GO=1;
;;
t|test)
TEST=1;
;;
\?)
echo -e "\n Option does not exist: ${OPTARG}\n";
echo "Use -t for test";
echo "Use -g for actually creation run";
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;
if [ $# -eq 0 ]; then
echo "Must give at least one user name";
exit;
fi;
# __END__

View File

@@ -66,21 +66,21 @@ for username in "$@"; do
# 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[*]} " =~ " ${username} " ]]; then
echo "[!] User $username is in the ignore user list";
echo "[!] User ${username} is in the ignore user list";
continue;
fi;
# check that user exists in passwd
if ! id "${username}" &>/dev/null; then
echo "[!] User $username does not exists in /etc/passwd file";
echo "[!] User ${username} does not exists in /etc/passwd file";
continue;
fi;
# check if already in OK groups
if id -nGz "${username}" | grep -qzxF "${ssh_allow_group}"; then
echo "[.] User $username already in the ${ssh_allow_group} list";
echo "[.] User ${username} already in the ${ssh_allow_group} list";
continue;
fi;
if id -nGz "${username}" | grep -qzxF "${ssh_forward_group}"; then
echo "[.] User $username already in the ${ssh_forward_group} list";
echo "[.] User ${username} already in the ${ssh_forward_group} list";
continue;
fi;
# try to find user in user_list.txt and get the allow/forward flag from there,
@@ -98,7 +98,7 @@ for username in "$@"; do
# check if user is in reject group remove
if id -nGz "${username}" | grep -qzxF "${ssh_reject_group}"; then
# remove user from ssh group and add to reject groups
echo "[*] User $username will be added to ${ssh_add_group}";
echo "[*] User ${username} will be added to ${ssh_add_group}";
if [ ${TEST} -eq 1 ]; then
printf "${user_group_tpl}" "${username}" "${ssh_reject_group}" "${username}" "${ssh_add_group}";
else
@@ -107,7 +107,7 @@ for username in "$@"; do
fi;
else
# skip not ssh user
echo "[?] User $username not in the ssh reject group";
echo "[?] User ${username} not in the ssh reject group";
fi;
done;