Compare commits

...

7 Commits

Author SHA1 Message Date
Clemens Schwaighofer
c801ef40b4 Switch from lastlogin to lsogins
Debian 13 dropped lastlogin, replaced with lastlogin2 which is an extra install.
Switch to lslogins, which also makes parsing much easier
2025-09-12 10:16:05 +09:00
Clemens Schwaighofer
125cb27de8 Remove URLs from ReadMe 2025-03-14 22:28:19 +09:00
Clemens Schwaighofer
e45b89c582 AWS Delete user, remove all secondary groups first.
To make sure tha on delete the user is removed from all secondary groups
unset them first before running the userdel command.

-r might not be enought to do that in some situations
2025-01-06 13:45:51 +09:00
Clemens Schwaighofer
4a8dab7b01 Add base folder for lock user aws script 2024-12-16 15:44:09 +09:00
Clemens Schwaighofer
fa47178ed1 Add central logging for all actions done
log file "user_management.log"

Each line is
[YYYY-MM-DD HH:mm:ss] [script name] [TEST] ...

[TEST] is only set if we are in a test run

for create user, if info flag is set, we do not write a log
2024-12-09 11:37:37 +09:00
Clemens Schwaighofer
4629b58a7e Skip empty group on login check 2024-11-11 17:06:24 +09:00
Clemens Schwaighofer
d8cd628ddd Fix for check last login script
the data reading was split with " " (space) which in the while read kept
it as one row, changed the split character to "\n"
2024-10-24 13:57:04 +09:00
8 changed files with 275 additions and 92 deletions

View File

@@ -11,14 +11,11 @@ The folder holding the script must be owned by *root* and have *600* permissions
```sh
cd /root/
git clone http://gitlab-ap.factory.tools/scripts-collections/aws-user-create.git users
git clone <UrlToGitRepository> users
chown root. users
chgrp 600 users
```
Alternate download:
`git clone https://git.tequila.jp/ScriptsCollections/AwsUserCreate.git users`
## Folders
Inside the base folder there are
@@ -269,7 +266,7 @@ If not set it defaults to allow, if a user_list.txt file with this user exist it
There are two scripts that can be user to check if and when the user has logged in the last time.
Because of users who do not open shells (for example sftp users) we cannot rely on lastlog, so a script called `collect_login_data.sh` exists that parses the systemd logind info or /var/log/secure for user authentication data.
Because of users who do not open shells (for example sftp users) we cannot rely on lslogins, so a script called `collect_login_data.sh` exists that parses the systemd logind info or /var/log/secure for user authentication data.
Data is stored in `auth-log/user_auth.log` folder as `user;last login date`
@@ -281,7 +278,7 @@ This script should be run every day via crontab as root:
The script `check_last_login.sh` will go through the ssh allow groups (sshallow/sshforward) users and flag out those that have not logged in, in the last 60 days and recommend to lock them. The script will also check for user accounts that never logged in and where created in the last 30 days and recomment to lock them too.
This script will first check the `auth-log/user_auth.log` file, then lastlog output and finally check for creation time in passwd file or home director for when the user was created.
This script will first check the `auth-log/user_auth.log` file, then lslogins output and finally check for creation time in passwd file or home director for when the user was created.
Currently only information is printed out and no action is done itself.

View File

@@ -88,6 +88,24 @@ if [ -f "${BASE_FOLDER}${IGNORE_USER_FILE}" ]; then
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 |
@@ -97,14 +115,17 @@ while read -r user_home; do
# 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);
@@ -113,8 +134,10 @@ while read -r user_home; do
# 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;
@@ -124,6 +147,7 @@ while read -r user_home; do
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;
@@ -132,6 +156,7 @@ while read -r user_home; do
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";
@@ -139,15 +164,17 @@ while read -r user_home; do
echo "$> rm \"${home_folder}/.ssh/authorized_keys\"";
fi;
else
echo "[!] No delete for master user, must be done manually";
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}";
@@ -159,13 +186,14 @@ while read -r user_home; do
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
echo "=> No delete for master user, must be done manually";
write_log "=> No delete for master user, must be done manually" "1";
fi;
else
echo "[START] ====>";

View File

@@ -44,6 +44,11 @@ if [ -z "$(command -v jq)" ]; then
echo "Missing jq application, aborting";
error=1;
fi;
# use lslogins instead of last log
if [ -z "$(command -v lslogins)" ]; then
echo "Missing lslogins application, aborting";
error=1;
fi;
if [ $error -eq 1 ]; then
exit;
fi;
@@ -76,7 +81,7 @@ account_id=$(echo "${instance_data}" | jq .accountId)
region=$(echo "${instance_data}" | jq .region)
if [ "${OUTPUT_TARGET}" = "text" ]; then
LOG="${LOG}/check_ssh_user.$(date +"%F_%H%m%S").log";
LOG="${LOG}/check_ssh_user.$(date +"%F_%H%M%S").log";
exec &> >(tee -a "${LOG}");
echo "[START] =============>";
echo "AWS ID : ${account_id}";
@@ -111,6 +116,10 @@ for ssh_group in "${ssh_groups[@]}"; do
fi;
fi;
while read -r username; do
# skip empty, if group exists but has no users
if [ "${username}" = "" ]; then
continue;
fi;
# check that user exists in passwd
if ! id "${username}" &>/dev/null; then
out_string="[!] User $username does not exists in /etc/passwd file";
@@ -183,10 +192,18 @@ for ssh_group in "${ssh_groups[@]}"; do
# below only works if the user logged in, a lot of them are just file upload
# users. Use the collect script from systemd-logind or /var/log/secure
# Username Port From Latest
# user pts/35 10.110.160.230 Wed Nov 2 09:40:35 +0900 2022
last_login_string=$(lastlog -u "${username}" | sed 1d);
search="Never logged in";
# for the rest use lslogin, returns ":" separted list, not set is never logged in
# LAST LOGIN :FAILED LOGIN
# 2025-09-12T09:56:22+09:00:
last_login_string=$(
lslogins \
-c --noheadings --notruncate \
--time-format=iso \
-o LAST-LOGIN,FAILED-LOGIN \
-l "${username}"
);
last_login_date=$(echo "${last_login_string}" | cut -d ":" -f 1);
# search="Never logged in";
never_logged_in="false";
found="";
login_source="";
@@ -223,12 +240,10 @@ for ssh_group in "${ssh_groups[@]}"; do
login_source="ssh";
# rewrite to Y-M-D, aka
last_login_date="${last_login_date_string}"
elif [ -n "${last_login_string##*"$search"*}" ]; then
elif [ -n "${last_login_date}" ]; then
# if we have "** Never logged in**" the user never logged in
# find \w{3} \w{3} [\s\d]{2} \d{2}:\d{2}:\d{2} \+\d{4} \d{4}
# awk '{for(i=4;i<=NF;++i)printf $i FS}'
last_login_date=$(echo "${last_login_string}" | awk '{for(i=4;i<=NF;++i)printf $i FS}' | date +"%s" -f -);
# date -d "Wed Nov 2 09:40:35 +0900 2022" +%s
# we get an ISO DATE with timezone
last_login_date=$(echo "${last_login_string}" | date +"%s" -f -);
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";
@@ -241,7 +256,7 @@ for ssh_group in "${ssh_groups[@]}"; do
out_string="OK [lastlog, ${last_login} days ago]";
fi;
login_source="lastlog";
last_login_date=$(echo "${last_login_string}" | awk '{for(i=4;i<=NF;++i)printf $i FS}' | date +"%F %T" -f -)
last_login_date=$(echo "${last_login_string}" | date +"%F %T" -f -)
elif [ -n "${user_create_date}" ]; then
if [ "${account_age}" -gt ${max_age_create} ]; then
out_string="[!] Never logged in: account created ${account_age} days ago";
@@ -294,7 +309,7 @@ for ssh_group in "${ssh_groups[@]}"; do
printf "${CSV_LINE}" "${account_id}" "${region}" "${instance_id}" "$(hostname)" "${username}" "${main_group}" "${ssh_group}" "${user_create_date_out}" "${account_age}" "${last_login_date}" "${last_login}" "${never_logged_in}" "${login_source}" "${out_string}"
;;
esac;
done <<< "$(grep "${ssh_group}:" /etc/group | cut -d ":" -f 4 | sed -e 's/,/ /g')";
done <<< "$(grep "${ssh_group}:" /etc/group | cut -d ":" -f 4 | sed -e 's/,/\n/g')";
done;
if [ "${OUTPUT_TARGET}" = "text" ]; then
if [ -n "${lock_accounts}" ]; then

View File

@@ -176,6 +176,12 @@ if [ "$(whoami)" != "root" ]; then
fi;
fi;
# do not allow test and info at the same
if [ ${TEST} -eq 1 ] && [ ${INFO} -eq 1 ]; then
echo "Cannot have --test and --info option at the same time";
error=1;
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.";
@@ -187,20 +193,51 @@ if [ $error -eq 1 ]; then
exit;
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
if [ ${INFO} -eq 0 ]; then
echo "[$(date +"%F %T")] [$0] ${log_prefix}${text}" >> "${LOG}";
fi;
if [ "${do_echo}" = "1" ]; then
echo "${text}";
fi;
}
write_log "START SCRIPT RUN";
# used for test run only
overall_run_error=0;
# MARK: LOOP START
# create users
while read -r i; do
# run error for one row
run_error=0;
# skip rows start with # (comment)
if [[ "${i}" =~ ^\# ]]; then
continue;
fi;
# log create inly on not info
if [ ${INFO} -eq 0 ]; then
write_log "[CREATE] ROW: $i";
fi;
# MARK: VALUES CHECK
# POS 2: make lower case, remove spaces
username=$(echo "${i}" | cut -d ";" -f 2 | tr "[:upper:]" "[:lower:]" | 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;
run_error=1;
write_log "[ERROR] User name can only be a-z 0-9 - _ . and cannot start or end with - . or _: ${username}" "1";
fi;
# POS 3: groups
_group=$(echo "${i}" | cut -d ";" -f 3 | tr "[:upper:]" "[:lower:]" | tr -d ' ');
@@ -223,14 +260,12 @@ while read -r i; do
ssh_access_type=$(echo "${i}" | cut -d ";" -f 4 | cut -d "|" -f 1 | tr "[:upper:]" "[:lower:]" | tr -d ' ');
# if not allow or forward, set to access
if [ "${ssh_access_type}" != "allow" ] && [ "${ssh_access_type}" != "forward" ]; then
echo "[!!] Not valid ssh access type ${ssh_access_type}, set to allow";
ssh_access_type="allow";
run_error=1;
write_log "[ERROR] Not valid ssh access type ${ssh_access_type}" "1";
fi;
if [ $ssh_forward_ok -eq 0 ] && [ "${ssh_access_type}" = "forward" ]; then
echo "[!!!] sshforward group does not exsts, cannot set user ${username}";
if [ ${TEST} -eq 0 ]; then
break;
fi;
write_log "[ERROR] sshforward group does not exsts, cannot set user ${username}" "1";
run_error=1;
fi;
ssh_group="ssh${ssh_access_type}";
# sshallow group is always added
@@ -259,24 +294,35 @@ while read -r i; do
fi;
# user & group not set
if [ -z "${username}" ] || [ -z "${_group}" ]; then
echo "[!!!!!] Missing user or group entry for ${username}/${_group}";
echo "[*** ABORT RUN ***]"
if [ ${TEST} -eq 0 ]; then
break;
fi;
run_error=1;
write_log "[ERROR] Missing user or group entry for ${username}/${_group}" "1";
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}";
write_log "[ERROR] Group name can only be a-z 0-9 - _ and cannot start or end with - or _: ${create_group}" "1";
group_error=1;
fi;
done;
if [ $group_error -eq 1 ] && [ ${TEST} -eq 0 ]; then
break;
if [ $group_error -eq 1 ]; then
run_error=1;
fi;
fi;
# error & test -> break
if [ ${run_error} -eq 1 ]; then
overall_run_error=1;
write_log "[*** ABORT RUN ***]" "1";
# end if not test and not info
if [ ${TEST} -eq 0 ] && [ ${INFO} -eq 0 ]; then
break;
else
continue;
fi;
fi;
# MARK: SSH NAMES SET
# SSH file name part without folder
ssh_keygen_id="${hostname}${separator}${group}${separator}${username}${separator}${ssh_keytype}.pem";
# the full file including folder name
@@ -286,20 +332,21 @@ while read -r i; do
# check existing pub file
ssh_keyfile_check_pub="${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}${ssh_keygen_id}.pub";
# MARK: INFO
if [ ${INFO} -eq 1 ]; then
info_string="User: '${username}:${group}(${sub_group});${ssh_group}', SSH: ${ssh_keygen_id}";
# test if pub file exists or not, test if user exists
echo -n "User: '${username}:${group}(${sub_group});${ssh_group}', SSH: ${ssh_keygen_id}";
if getent passwd "${username}" > /dev/null 2>&1; then
echo -n ", User exists";
info_string="${info_string}, User exists";
fi;
if [ -f "${ssh_keyfile_check_pub}" ]; then
echo -n ", SSH Pub key OK";
info_string="${info_string}, SSH Pub key OK";
fi;
# line break
echo "";
echo "${info_string}";
continue;
fi;
# MARK: CREATE
# add group for each entry in _group
for create_group in ${_group//,/ }; do
if [ ${TEST} -eq 0 ]; then
@@ -311,9 +358,9 @@ while read -r i; do
# check if user is not already created
# if getent passwd ${username} > /dev/null 2>&1; then
if id "${username}" &>/dev/null; then
echo "-- Skip '${username}:${group}(${sub_group})'";
write_log "-- Skip '${username}:${group}(${sub_group})'" "1";
else
echo "++ Create '${username}:${group}(${sub_group})'";
write_log "++ Create '${username}:${group}(${sub_group})'" "1";
params=(
"-c" "$(date +"%F")" "-s" "${user_login_shell}"
"-g" "${group}" "-G" "$(IFS=, ; echo "${sub_group_opt[*]}")"
@@ -349,7 +396,7 @@ while read -r i; do
password=${_password};
fi;
# create SSH key
echo " > Create ssh key-pair '${ssh_keyfile}'";
write_log " > Create ssh key-pair: ${ssh_keyfile}" "1";
if [ ${TEST} -eq 0 ]; then
ssh-keygen \
-t "${ssh_keytype}" \
@@ -366,16 +413,17 @@ while read -r i; do
fi;
if [ -n "${found}" ]; then
skip_ssh=1;
echo "-- Skip SSH Key creation: ${ssh_keygen_id}.pub";
write_log "-- Skip SSH Key creation: ${ssh_keygen_id}.pub" "1";
else
# override previously set with stored one
ssh_keyfile_pub=${ssh_keyfile_check_pub};
echo " < Use existing public ssh key '${ssh_keygen_id}.pub'";
write_log " < Use existing public ssh key: ${ssh_keygen_id}.pub" "1";
# Password already set notification
fi;
password="[ALREADY SET]";
fi;
if [ ${skip_ssh} -eq 0 ]; then
# MARK: SSH CREATE
# write login info to output file
if [ ${TEST} -eq 0 ]; then
create_output_file="${ROOT_FOLDER}${output_file}";
@@ -444,6 +492,8 @@ done <<< "$(cat "${ROOT_FOLDER}${input_file}")";
if [ ${INFO} -eq 1 ]; then
exit;
fi;
# MARK: ZIP FILE CREATE
# check if there are any files in the SSH_KEYGEN_FOLDER, else skip zip file creation and file move
has_pem_files=0;
if (shopt -s nullglob dotglob; f=("${SSH_KEYGEN_FOLDER}"*".pem"*); ((${#f[@]}))); then
@@ -488,4 +538,9 @@ else
echo "$> rm ${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}*";
fi;
# MARK: TEST ERROR INFO
if [ ${TEST} -eq 1 ] && [ ${overall_run_error} -eq 1 ]; then
echo "[ERROR] Some errors occoured during the run, they will prohibit the live run of this script";
fi;
# __END__

View File

@@ -60,20 +60,16 @@ backup_folder="${BASE_FOLDER}../backup/";
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;
HISTORY="${BASE_FOLDER}/../log/delete_user.log";
# 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 [ -n "$(echo "${cf}" | grep "%u")" ]; then
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=$(echo "${cf}" | sed -e 's/%u//');
# 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;
@@ -86,17 +82,39 @@ if [ ! -f "${user_list_file}" ]; then
exit;
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";
# used for test run only
overall_run_error=0;
# $1 ... $n
for username in "$@"; do
error=0;
# skip if there is an option hidden
# shellcheck disable=SC2154
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[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then
echo "[!] User ${username} is in the ignore user list";
write_log "[!] User ${username} is in the ignore user list" "1";
continue;
fi;
@@ -104,31 +122,33 @@ for username in "$@"; do
# 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";
write_log "[ERRPR] User ${username} does not exist in /etc/passwd" "1";
error=1;
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";
write_log "[ERROR] User ${username} does not exist in user_list.txt file" "1";
error=1;
elif [[ "${user_list_entry}" =~ ^#DELETED ]]; then
echo "[!!!] User ${username} is flagged as deleted in user_list.txt file";
write_log "[ERROR] User ${username} is flagged as deleted in user_list.txt file" "1";
error=1;
fi;
if [ $error -eq 1 ]; then
overall_run_error=1;
write_log "[*** ABORT RUN ***]" "1";
if [ ${TEST} -eq 0 ]; then
break;
fi;
fi;
echo "=> Delete: ${username}";
write_log "=> Delete: ${username}" "1";
# 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);
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
@@ -136,7 +156,7 @@ for username in "$@"; do
fi;
echo "[0] Backup ${files_list} to ${backup_file}";
if [ ${TEST} -eq 0 ]; then
tar cfjp "${backup_file}" ${file_list};
tar cfjp "${backup_file}" "${files_list}";
else
echo "$> tar cfjp \"${backup_file}\" ${files_list};";
fi;
@@ -144,9 +164,13 @@ for username in "$@"; do
echo "[1] Remove user + home dir";
if [ ${TEST} -eq 0 ]; then
userdel -r ${username}
# remove all secondary group entries first before we delete the user
# there might be cases where they are left
usermod -G "" "${username}";
userdel -r "${username}";
else
echo "$> userdel -r ${username}";
echo "$> usermod -G \"\" \"${username}\"";
echo "$> userdel -r \"${username}\"";
fi;
# remove ssh files in pub
@@ -162,7 +186,7 @@ for username in "$@"; do
fi;
else
# Not critical error
echo "[?] Cannot find ${SSH_AUTHORIZED_FILE}";
write_log "[?] Cannot find ${SSH_AUTHORIZED_FILE}" "1";
fi;
# Update user_list.txt file and add # for the line
@@ -172,11 +196,17 @@ for username in "$@"; do
if [ ${TEST} -eq 0 ]; then
sed -i -e "s/^\([A-Za-z0-9]\{1,\};${username};\)/#DELETED-${delete_date}:\1/" "${user_list_file}";
else
# shellcheck disable=SC2028
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}";
echo "$(date +"%F %T");${host};${username};${TEST}" >> "${HISTORY}";
done;
# MARK: TEST ERROR INFO
if [ ${TEST} -eq 1 ] && [ ${overall_run_error} -eq 1 ]; then
echo "[ERROR] Some errors occoured during the run, they will prohibit the live run of this script";
fi;
# __END__

View File

@@ -46,27 +46,50 @@ ssh_allow_group="sshallow";
ssh_forward_group="sshforward";
user_group_tpl="gpasswd -d %s %s\ngpasswd -a %s %s\n";
# base folder for all data
BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
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";
echo "--------------------->"
# $1 ... $n
for username in "$@"; do
# skip if there is an option hidden
# shellcheck disable=SC2154
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[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then
echo "[!] User ${username} is in the ignore user list";
write_log "[ERROR] User ${username} is in the ignore user list" "1";
continue;
fi;
# check that user exists in passwd
if ! id "${username}" &>/dev/null; then
echo "[!] User ${username} does not exists in /etc/passwd file";
write_log "[ERROR] User ${username} does not exists in /etc/passwd file" "1";
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";
write_log "[.] User ${username} already in the ${ssh_reject_group} list";
continue;
fi;
# check if user is in sshallow/forward list
@@ -77,14 +100,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 [ -n "${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.";
write_log "[!!!! 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." "1";
break;
fi;
ssh_remove_group="${ssh_forward_group}";
fi;
if [ -n "${ssh_remove_group}" ]; then
# remove user from ssh group and add to reject groups
echo "[*] User ${username} will be removed from ${ssh_remove_group}";
write_log "[*] User ${username} will be removed from ${ssh_remove_group}" "1";
if [ ${TEST} -eq 1 ]; then
# shellcheck disable=SC2059
printf "${user_group_tpl}" "${username}" "${ssh_remove_group}" "${username}" "${ssh_reject_group}";
@@ -94,7 +117,7 @@ for username in "$@"; do
fi;
else
# skip not ssh user
echo "[?] User ${username} not in any ssh allow/foward groups";
write_log "[?] User ${username} not in any ssh allow/foward groups" "1";
fi;
done;

View File

@@ -58,13 +58,6 @@ input_file='user_list.txt';
user_list_file="${ROOT_FOLDER}${input_file}";
default_ssh_keytype='ed25519';
ssh_keytype='';
# log file
LOG="${BASE_FOLDER}/../log/rename_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
@@ -144,6 +137,27 @@ 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
@@ -164,7 +178,7 @@ else
ssh_keytype=${default_ssh_keytype};
fi;
echo "* Rename ${OLD_USERNAME} to ${NEW_USERNAME}";
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}/");
@@ -202,7 +216,7 @@ NEW_SSH_AUTHORIZED_FILE="${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}${NEW_USERNAME}";
if [ -f "${OLD_SSH_AUTHORIZED_FILE}" ]; then
if [ $TEST -eq 0 ]; then
echo "rename to ${NEW_SSH_AUTHORIZED_FILE}";
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}";
@@ -212,7 +226,7 @@ if [ -f "${OLD_SSH_AUTHORIZED_FILE}" ]; then
echo "$> chattr +i \"${NEW_SSH_AUTHORIZED_FILE}\";";
fi;
else
echo "[?] ${OLD_SSH_AUTHORIZED_FILE} is missing";
write_log "[?] ${OLD_SSH_AUTHORIZED_FILE} is missing" "1";
fi;
# rename keygen public file
@@ -221,13 +235,13 @@ NEW_ssh_keygen_pub="${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}${hostname}${s
if [ -f "${OLD_ssh_keygen_pub}" ]; then
if [ $TEST -eq 0 ]; then
echo "rename to ${NEW_ssh_keygen_pub}";
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
echo "[?] ${OLD_ssh_keygen_pub} is missing";
write_log "[?] ${OLD_ssh_keygen_pub} is missing" "1";
fi;
# rename entry in user list txt file

View File

@@ -61,31 +61,52 @@ ssh_allow_group="sshallow";
ssh_forward_group="sshforward";
user_group_tpl="gpasswd -d %s %s\ngpasswd -a %s %s\n";
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";
echo "--------------------->"
# $1 ... $n
for username in "$@"; do
# skip if there is an option hidden
# shellcheck disable=SC2154
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[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then
echo "[!] User ${username} is in the ignore user list";
write_log "[ERROR] User ${username} is in the ignore user list" "1";
continue;
fi;
# check that user exists in passwd
if ! id "${username}" &>/dev/null; then
echo "[!] User ${username} does not exists in /etc/passwd file";
write_log "[ERROR] User ${username} does not exists in /etc/passwd file" "1";
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";
write_log "[.] User ${username} already in the ${ssh_allow_group} list" "1";
continue;
fi;
if id -nGz "${username}" | grep -qzxF "${ssh_forward_group}"; then
echo "[.] User ${username} already in the ${ssh_forward_group} list";
write_log "[.] User ${username} already in the ${ssh_forward_group} list" "1";
continue;
fi;
# try to find user in user_list.txt and get the allow/forward flag from there,
@@ -103,7 +124,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}";
write_log "[*] User ${username} will be added to ${ssh_add_group}" "1";
if [ ${TEST} -eq 1 ]; then
# shellcheck disable=SC2059
printf "${user_group_tpl}" "${username}" "${ssh_reject_group}" "${username}" "${ssh_add_group}";
@@ -113,7 +134,7 @@ for username in "$@"; do
fi;
else
# skip not ssh user
echo "[?] User ${username} not in the ssh reject group";
write_log "[?] User ${username} not in the ssh reject group" "1";
fi;
done;