Compare commits

...

49 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
Clemens Schwaighofer
76f9056069 Fix user create with groups
Move the params into array that we add as dynamic parameters to call
2024-10-11 14:39:56 +09:00
Clemens Schwaighofer
74e7e9823f Bug fix for user create group part 2024-10-11 09:25:41 +09:00
Clemens Schwaighofer
7ce8330aa6 shellcheck fixup 2024-09-27 18:49:36 +09:00
Clemens Schwaighofer
d8f9710593 Merge branch 'development' into shellecheck-cleanup 2024-09-24 11:40:13 +09:00
Clemens Schwaighofer
c37d17fe9f ReadMe file update 2024-09-24 11:38:45 +09:00
Clemens Schwaighofer
307433e0a7 Merge branch 'development' into shellecheck-cleanup 2024-09-20 09:22:20 +09:00
Clemens Schwaighofer
f9cd0806f1 Fix in Readme file for exmaple user_list.txt 2024-09-20 09:22:02 +09:00
Clemens Schwaighofer
d9b3fd97fb Merge branch 'development' into shellecheck-cleanup 2024-09-20 09:20:36 +09:00
Clemens Schwaighofer
21177e1762 Updates for ReadMe file for no login shell settings 2024-09-20 09:20:01 +09:00
Clemens Schwaighofer
3aa6de7e23 check last login shellcheck fixes 2024-09-06 14:44:34 +09:00
Clemens Schwaighofer
3c160a62e7 Merge branch 'development' into shellecheck-cleanup 2024-09-06 14:37:37 +09:00
Clemens Schwaighofer
ca4616c5ee Text fix for error strings in last login check 2024-09-06 14:36:09 +09:00
Clemens Schwaighofer
251b0bf981 SSH login last date check was wrong 2024-09-06 14:34:38 +09:00
Clemens Schwaighofer
6daccfe57c Check last login update with more days info
if WARN then write WARN instead of OK.
Add day numbers if OK

Some minor shellscript updates
2024-09-06 14:25:28 +09:00
Clemens Schwaighofer
91f096ab0c Merge branch 'master' into shellecheck-cleanup 2024-09-06 10:58:13 +09:00
Clemens Schwaighofer
935d6a84c9 Add login shell type select (bash login or no login), fix ssh base groups
no ssh allow/forward/reject base group was set if an optional sub group was set

Add possibility to chose no login when setting the ssh access type to "...|no_login"
2024-09-06 10:44:31 +09:00
Clemens Schwaighofer
ee7cc8555e Merge branch 'development' into shellecheck-cleanup 2024-09-04 14:05:51 +09:00
Clemens Schwaighofer
83f84abd46 Fix skip naming for zip/move creation 2024-09-04 14:04:25 +09:00
Clemens Schwaighofer
090d6f9cec Download zip file message only if there is a file to download 2024-09-04 13:44:47 +09:00
Clemens Schwaighofer
5659cc010f Update zip file/clean up skip with skip information 2024-09-04 13:43:24 +09:00
Clemens Schwaighofer
0bd40cdd73 Create user: skip zip creation run if there are no PEM files
Avoid "file not found" zip file creation and remove if there are no
PEM files created, eg if we have a pre defined pub file
2024-09-04 13:21:36 +09:00
Clemens Schwaighofer
e4ed6fed8d shellcheck based code cleanup 2024-09-04 11:16:05 +09:00
Clemens Schwaighofer
5bf30a8b2f Add shellcheckrc 2024-09-03 12:47:52 +09:00
Clemens Schwaighofer
26c007dba6 Remove error=1 debug set 2024-02-15 18:10:53 +09:00
Clemens Schwaighofer
785e3c116d Fix password set length check 2024-02-15 18:07:53 +09:00
Clemens Schwaighofer
adbfeb0074 Password length set, auto set if not set, and set for pwgen actually 2024-02-15 18:05:03 +09:00
Clemens Schwaighofer
8c7ef32894 Create user script update: allow no password, allow different password length 2024-02-15 18:03:16 +09:00
Clemens Schwaighofer
70ef7a3fc5 Check last login mandatory settings now has combined abort
set an error flag and check all settings before exit program
2024-02-14 14:46:17 +09:00
Clemens Schwaighofer
89252af50b Bug fix for json export with double quotes 2023-12-22 13:39:18 +09:00
Clemens Schwaighofer
8fb833d3c4 Fix the call for getting instance data
Do not use name alias, use the IP address for this
2023-12-22 13:31:33 +09:00
Clemens Schwaighofer
694f04313c Add Account, Region and Instance info for each report
So we can easy match up user reports to other information we collect
2023-12-22 11:54:34 +09:00
Clemens Schwaighofer
50e28c7cfd Check that fallback last access file exists 2023-12-21 16:43:57 +09:00
Clemens Schwaighofer
65b7a6ad43 Fix date check for account created date
Use regex to check instead of empty string.
A comment could be set instead of a date
2023-12-21 16:39:05 +09:00
Clemens Schwaighofer
244461d466 sshforward group typo in lock and unlock users 2023-12-21 16:11:31 +09:00
Clemens Schwaighofer
66213dfd65 Text fixes for check last login 2023-12-21 16:06:53 +09:00
Clemens Schwaighofer
39da44b546 Wrong unlock account var used for unlock users 2023-12-21 16:01:35 +09:00
Clemens Schwaighofer
d4bb06e3e1 Fix lock user flow to only lock if the user is not in the reject group 2023-12-21 15:58:28 +09:00
Clemens Schwaighofer
cc647de495 Readme update 2023-12-21 15:14:57 +09:00
Clemens Schwaighofer
68b450baaf Add warning message for logins 2023-12-21 13:46:58 +09:00
Clemens Schwaighofer
8452a1b8c0 Fix pre check for ssh login checks 2023-12-21 13:35:50 +09:00
Clemens Schwaighofer
3fcb74ac47 Update check last login script with better reporting and csv/json output
Now for each ssh group we report last login/account create stats.
Add the main user group to output
Add unlock user commands for locked users

Add CSV and JSON formatted output
2023-12-21 13:23:35 +09:00
Clemens Schwaighofer
70212da3cb systemd logs end with dot and we split, so we missed user names with . inside 2023-12-20 17:51:35 +09:00
11 changed files with 842 additions and 304 deletions

2
.shellcheckrc Normal file
View File

@@ -0,0 +1,2 @@
shell=bash
external-sources=true

112
Readme.md
View File

@@ -1,4 +1,4 @@
# AWS User Creation # User creation on AWS Servers
Two files to create new user entries with an SSH key and zip all the data for download Two files to create new user entries with an SSH key and zip all the data for download
@@ -11,20 +11,50 @@ The folder holding the script must be owned by *root* and have *600* permissions
```sh ```sh
cd /root/ cd /root/
git clone http://gitlab-ap.factory.tools/scripts-collections/aws-user-create.git users git clone <UrlToGitRepository> users
chown root. users chown root. users
chgrp 600 users chgrp 600 users
``` ```
Alternate download:
`git clone https://git.tequila.jp/ScriptsCollections/AwsUserCreate.git users`
## Folders ## Folders
Inside the base folder there are Inside the base folder there are
- ssh-keygen for temporary holding the PEM/PUB files - auth-log/: access logs from users for the last login check
- zip file which holds the created user list, password and PEM/PUB files - bin/: scripts folder
- backup/: for removed users home directories
- config/: config settings (eg alternative home base folder
- log/: user creation and other action logs
- ssh-keygen/: PEM keys are stored here during creation and then zip-ed into the zip folder
- ssh-keygen-created-pub/: Public keys are stored here and stay here (used for checking)
- user_list.txt: users that should exist on this server with various settings
- [user_password.YYYYMMDD-HHmmss.txt] temporary file with username and password, zip-ed into the zip folder
- zip/: after user creation the password and PEM files are stored in here
## Config
### create_user.sh: create_user.cfg
A `create_user.cfg` can be created to set a differen HOME_LOCATION and PASSWORD_LENGTH values
eg:
```ini
HOME_LOCATION="/storage"
PASSWORD_LENGTH=14
```
### authorized_key_location_change.sh: authorized_key_location_change.ignore
For this script a `authorized_key_location_change.ignore` with a list of user names to ignore for the
move
eg:
```ini
foo_user
bar_user
```
## Options ## Options
@@ -47,12 +77,12 @@ In the `/root/users/` folder there needs to be a file called '*user_list.txt*'
This is a CSV type file with the following layout This is a CSV type file with the following layout
ID | Username | Group and Sub Group | SSH Access Type | Optional Password | Override host name | Override ssh key type ID | Username | Group and Sub Group | SSH Access Type and No Login flag | Optional Password | Override host name | Override ssh key type
-|-|-|-|-|-|- -|-|-|-|-|-|-
1: The ID, Username and Group column must be filled. 1: The ID, Username and Group column must be filled.
2: For sub groups add them with a *,* The first group is the master group 2: For sub groups add them with a MASTER_GROUP,SUB_GROUP_A,SUB_GROUP_B,... The first group is the master group
3: SSH Access type as: allow/forward. allow is default 3: SSH Access type as: allow/forward. allow is default, additional separated by | can be a "no_login" to set a no login shell, else bash shell will be set
4: If the password column is filled, the string from here will be used as the PEM Key password. 4: If the password column is filled, the string from here will be used as the PEM Key password.
5: If a override hostname is set it will be used instead of `hostname` 5: If a override hostname is set it will be used instead of `hostname`
6: If the ssh key type is set, it will override the default *ed25519* type. Only *rsa* is allowed. This is for setting up backwards compatible lists. Change is not recommended 6: If the ssh key type is set, it will override the default *ed25519* type. Only *rsa* is allowed. This is for setting up backwards compatible lists. Change is not recommended
@@ -65,11 +95,12 @@ The file can hold comments. The first character in the line must be a *#*
Example file Example file
```csv ```csv
#user_id;user_name;group,subgroup;ssh access type;override password;override hostname;override ssh type #user_id;user_name;group,subgroup;ssh access type|no login flag;override password;override hostname;override ssh type
user1;some.name;group-a;allow;;hostname; user1;some.name;group-a;allow;;hostname;
user2;othername;group-a;allow;;; user2;othername;group-a;allow;;;
# I am a comment # I am a comment
;username;groupC;allow;setpassword;; ;username;groupC;allow;setpassword;;
;username_c;groupC;allow|no_login;;;
... ...
``` ```
@@ -235,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. 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` Data is stored in `auth-log/user_auth.log` folder as `user;last login date`
@@ -247,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. 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. Currently only information is printed out and no action is done itself.
@@ -257,6 +288,61 @@ The script can be put into the crontab and run once a month, it prints to STDOUT
0 2 1 * * root /root/users/bin/check_last_login.sh | mail -s "User Account check: $(hostname)" 0 2 1 * * root /root/users/bin/check_last_login.sh | mail -s "User Account check: $(hostname)"
``` ```
For processable output there is a "csv" and "json" option to output the data in CSV or JSON format
Example csv
```csv
Hostname,Username,Main Group,SSH Group,Account Created Date,Account Age,Last Login Date,Last Login Age,Login Source,Never Logged In,Status
some.host,name_a,staff,sshallow,2021-11-18,764,,,,true,[!] Never logged in: account created 764 days ago
some.host,name_b,staff,sshallow,2021-11-15,767,2023-12-20 22:18:36,1,ssh,false,OK [ssh]
...
```
```json
{
"Info": {
"Hostname": "host.name",
"Date": "2023-12-21 13:11:45",
"MaxAgeLogin": 90,
"MaxAgeCreate": 30
},
"Users": [
{
"Username": "name_a",
"SshGroup": "sshallow",
"MainGroup": "staff",
"SubGroups": [],
"AccountCreatedDate": "2021-11-18",
"AccountAge": "764",
"LastLoginDate": "",
"LastLoginAge": "",
"LoginSource": "",
"NeverLoggedIn": true,
"Status": "[!] Never logged in: account created 764 days ago"
},
{
"Username": "name_b",
"SshGroup": "sshallow",
"MainGroup": "staff",
"SubGroups": [
"sudo",
"users",
"group_a",
"group_b",
],
"AccountCreatedDate": "2021-11-15",
"AccountAge": "767",
"LastLoginDate": "2023-12-20 22:18:36",
"LastLoginAge": "1",
"LoginSource": "ssh",
"NeverLoggedIn": false,
"Status": "OK [ssh]"
},
]
}
```
## Delete users ## Delete users
`bin/delete_user.sh -t -b <user 1> <user 2> ...` `bin/delete_user.sh -t -b <user 1> <user 2> ...`

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2059
# check if we need to move the users authorized keys to the central location # check if we need to move the users authorized keys to the central location
TEST=1; TEST=1;
@@ -7,14 +9,14 @@ LIST=0;
SKIP_USERS=(); SKIP_USERS=();
while getopts ":gls:" opt; do while getopts ":gls:" opt; do
case "${opt}" in case "${opt}" in
g|go) g) # go
# default we test # default we test
TEST=0; TEST=0;
;; ;;
s|skip) s) # skip
SKIP_USERS+=("${OPTARG}"); SKIP_USERS+=("${OPTARG}");
;; ;;
l|list) l) # list
LIST=1; LIST=1;
;; ;;
\?) \?)
@@ -29,10 +31,11 @@ done;
# detect ssh authorized_keys setting # detect ssh authorized_keys setting
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=''; SSH_CENTRAL_AUTHORIZED_FILE_FOLDER='';
SSH_MASTER_AUTHORIZED_FILE=''; SSH_MASTER_AUTHORIZED_FILE='';
SSH_AUTHORIZED_FILE=''; # SSH_AUTHORIZED_FILE='';
# shellcheck disable=SC2013
for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do
if [ ! -z $(echo "${cf}" | grep "%u") ]; then if echo "$cf" | grep -q "%u"; then
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=$(echo "${cf}" | sed -e 's/%u//'); SSH_CENTRAL_AUTHORIZED_FILE_FOLDER="${cf/%%u//}";
if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}"; echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}";
exit; exit;
@@ -43,8 +46,9 @@ if [ -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo "No central authorized_keys file detected, no change check needed"; echo "No central authorized_keys file detected, no change check needed";
exit; exit;
fi; fi;
# shellcheck disable=SC2013
for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep -- "--master"); do for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep -- "--master"); do
if [ ! -z $(echo "${cf}" | grep -- "--master") ]; then if ! echo "${cf}" | grep -q -- "--master"; then
SSH_MASTER_AUTHORIZED_FILE="${cf}"; SSH_MASTER_AUTHORIZED_FILE="${cf}";
if [ ! -f "${SSH_MASTER_AUTHORIZED_FILE}" ]; then if [ ! -f "${SSH_MASTER_AUTHORIZED_FILE}" ]; then
echo "ssh master authorized_file could not be found: ${SSH_MASTER_AUTHORIZED_FILE}"l echo "ssh master authorized_file could not be found: ${SSH_MASTER_AUTHORIZED_FILE}"l
@@ -66,7 +70,7 @@ if [ ${LIST} -eq 1 ]; then
fi; fi;
# base folder # base folder
BASE_FOLDER=$(dirname $(readlink -f $0))"/"; BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
# output printf # output printf
PRINTF_INFO="%-8s [%3s]: %-25s: %s\n"; PRINTF_INFO="%-8s [%3s]: %-25s: %s\n";
# list of user accounts we will never touch # list of user accounts we will never touch
@@ -84,23 +88,44 @@ if [ -f "${BASE_FOLDER}${IGNORE_USER_FILE}" ]; then
echo "Reading ${IGNORE_USER_FILE}"; echo "Reading ${IGNORE_USER_FILE}";
fi; 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 # loop over passwd file
# if not in no action then check if .ssh/authorized_keys file exists # if not in no action then check if .ssh/authorized_keys file exists
cat /etc/passwd | cut -d ":" -f 1,6 | cut -d ":" -f 1,6 /etc/passwd |
while read user_home; do while read -r user_home; do
username=$(echo "${user_home}" | cut -d ":" -f 1); username=$(echo "${user_home}" | cut -d ":" -f 1);
master_user=0; master_user=0;
# skip admin usernames # skip admin usernames
if [[ " ${NO_ACTION[*]} " =~ " ${username} " ]]; then if [[ " ${NO_ACTION[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then
printf "${PRINTF_INFO}" "NO ACT" "!" "${username}" "user in NO ACTION list"; printf "${PRINTF_INFO}" "NO ACT" "!" "${username}" "user in NO ACTION list";
write_log "[NO ACT] ${username} in NO ACTION list";
continue; continue;
fi; fi;
if [[ " ${SKIP_USERS[*]} " =~ " ${username} " ]]; then if [[ " ${SKIP_USERS[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then
printf "${PRINTF_INFO}" "SKIP" "*" "${username}" "skip forced via command line"; printf "${PRINTF_INFO}" "SKIP" "*" "${username}" "skip forced via command line";
write_log "[SKIP] ${username} skip forced via command line";
continue; continue;
fi; fi;
if [[ " ${IGNORE_USER[*]} " =~ " ${username} " ]]; then if [[ " ${IGNORE_USER[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then
printf "${PRINTF_INFO}" "SKIP" "**" "${username}" "skip from ignore config file"; printf "${PRINTF_INFO}" "SKIP" "**" "${username}" "skip from ignore config file";
write_log "[SKIP] ${username} skip from ignore config file";
continue; continue;
fi; fi;
home_folder=$(echo "${user_home}" | cut -d ":" -f 2); home_folder=$(echo "${user_home}" | cut -d ":" -f 2);
@@ -109,17 +134,20 @@ while read user_home; do
# but do we have an auth folder, if yes -> exist skip # but do we have an auth folder, if yes -> exist skip
if [ -f "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}" ]; then if [ -f "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}" ]; then
printf "${PRINTF_INFO}" "DONE" "." "${username}" "already moved"; printf "${PRINTF_INFO}" "DONE" "." "${username}" "already moved";
write_log "[DONE] ${username} already moved";
else else
printf "${PRINTF_INFO}" "IGNORE" "?" "${username}" "no authorized_keys file"; printf "${PRINTF_INFO}" "IGNORE" "?" "${username}" "no authorized_keys file";
write_log "[IGNORE] ${username} no authorized_keys file";
fi; fi;
continue; continue;
fi; fi;
# check those keys are in the master key list # check those keys are in the master key list
if [[ " ${MASTER_KEY[*]} " =~ " ${username} " ]]; then if [[ " ${MASTER_KEY[*]} " =~ [[:space:]]${username}[[:space:]] ]]; then
master_user=1; master_user=1;
ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_MASTER_AUTHORIZED_FILE}"); ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_MASTER_AUTHORIZED_FILE}");
if [ ! -z "${ssh_key_diff}" ]; then if [ -n "${ssh_key_diff}" ]; then
printf "${PRINTF_INFO}" "ABORT" "!!!" "${username}" "authorized key is not matching the master key file"; 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; exit;
fi; fi;
fi; fi;
@@ -128,6 +156,7 @@ while read user_home; do
ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"); ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}");
if [ -z "${ssh_key_diff}" ]; then if [ -z "${ssh_key_diff}" ]; then
printf "${PRINTF_INFO}" "REMOVE" "-" "${username}" ".ssh/authorized_keys"; printf "${PRINTF_INFO}" "REMOVE" "-" "${username}" ".ssh/authorized_keys";
write_log "[REMOVE] ${username} .ssh/authorized_keys";
if [ ${master_user} -eq 0 ]; then if [ ${master_user} -eq 0 ]; then
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
rm "${home_folder}/.ssh/authorized_keys"; rm "${home_folder}/.ssh/authorized_keys";
@@ -135,33 +164,36 @@ while read user_home; do
echo "$> rm \"${home_folder}/.ssh/authorized_keys\""; echo "$> rm \"${home_folder}/.ssh/authorized_keys\"";
fi; fi;
else else
echo "[!] No delete for master user, must be done manually"; write_log "[!] No delete for master user, must be done manually" "1";
fi; fi;
continue; continue;
fi; fi;
# No update, alert # No update, alert
printf "${PRINTF_INFO}" "DIFF" "???" "${username}" "Different authorized keys in home dir, SKIPPED"; printf "${PRINTF_INFO}" "DIFF" "???" "${username}" "Different authorized keys in home dir, SKIPPED";
write_log "[DIFF] ${username} Different authorized keys in home dir, SKIPPED";
continue; continue;
fi; fi;
printf "${PRINTF_INFO}" "MOVE" ">" "${username}" "Move SSH Key to central location"; 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 # move public keys over
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
cat "${home_folder}/.ssh/authorized_keys" > "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"; cat "${home_folder}/.ssh/authorized_keys" > "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}";
# secure new folder: chown/chmod/chattr # secure new folder: chown/chmod/chattr
chown ${username} "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"; chown "${username}" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}";
chmod 400 "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"; chmod 400 "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}";
chattr +i "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"; chattr +i "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}";
# confirm # confirm
ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}"); ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}");
if [ ! -z "${ssh_key_diff}" ]; then if [ -n "${ssh_key_diff}" ]; then
printf "${PRINTF_INFO}" "ERROR" "!!!" "${username}" "Move problem ${ssh_key_diff}"; printf "${PRINTF_INFO}" "ERROR" "!!!" "${username}" "Move problem ${ssh_key_diff}";
write_log "[ERROR] ${username} Move problem ${ssh_key_diff}";
break; break;
fi; fi;
# remove home .ssh/authorized_keys (do not remove folder) # remove home .ssh/authorized_keys (do not remove folder)
if [ ${master_user} -eq 0 ]; then if [ ${master_user} -eq 0 ]; then
rm "${home_folder}/.ssh/authorized_keys"; rm "${home_folder}/.ssh/authorized_keys";
else else
echo "=> No delete for master user, must be done manually"; write_log "=> No delete for master user, must be done manually" "1";
fi; fi;
else else
echo "[START] ====>"; echo "[START] ====>";

View File

@@ -4,131 +4,336 @@
# if user login >30days, remoe user from sshallow group and write log # if user login >30days, remoe user from sshallow group and write log
# base folder # base folder
BASE_FOLDER=$(dirname $(readlink -f $0))"/"; BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
# which groups holds the ssh allowed login users (outside of admin users) # which groups holds the ssh allowed login users (outside of admin users)
ssh_groups=('sshforward' 'sshallow'); ssh_groups=('sshforward' 'sshallow' 'sshreject');
ssh_reject_group='sshreject'; ssh_reject_group='sshreject';
# date now for compare # date now for compare
now=$(date +"%s"); now=$(date +"%s");
# max age for last login or account create without login # max age for last login or account create without login
max_age_login=60; max_age_login=90;
warn_age_login=80;
max_age_create=30; max_age_create=30;
# one day in seconds # one day in seconds
day=86400; day=86400;
# delete account strings # delete account strings
lock_accounts=""; lock_accounts="";
unlock_flag=0;
unlock_accounts="";
# only needed for json output
first_run=1;
# log base folder # log base folder
LOG="${BASE_FOLDER}/../log"; LOG="${BASE_FOLDER}/../log";
# auth log file user;date from collect_login_data script # auth log file user;date from collect_login_data script
AUTH_LOG="${BASE_FOLDER}/../auth-log/user_auth.log"; AUTH_LOG="${BASE_FOLDER}/../auth-log/user_auth.log";
if [ $(whoami) != "root" ]; then error=0;
if [ "$(whoami)" != "root" ]; then
echo "Script must be run as root user"; echo "Script must be run as root user";
exit; error=1;
fi; fi;
if [ ! -d "${LOG}" ]; then if [ ! -d "${LOG}" ]; then
echo "log folder ${LOG} not found"; echo "log folder ${LOG} not found";
error=1;
fi;
if [ -z "$(command -v curl)" ]; then
echo "Missing curl application, aborting";
error=1;
fi;
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; exit;
fi; fi;
LOG="${LOG}/check_ssh_user."$(date +"%F_%H%m%S")".log"; # option 1 in list
exec &> >(tee -a "${LOG}"); case "${1,,}" in
echo "[START] =============>"; text)
echo "Hostname : "$(hostname); OUTPUT_TARGET="text";
echo "Run date : "$(date +"%F %T"); ;;
echo "Max age last login: ${max_age_login} days"; json)
echo "Max age no login : ${max_age_create} days"; OUTPUT_TARGET="json";
for ssh_group in ${ssh_groups[@]}; do echo "{";
echo "--------------------->" ;;
echo "Checking Group : ${ssh_group}"; csv)
for username in $(cat /etc/group|grep "${ssh_group}:" | cut -d ":" -f 4 | sed -e 's/,/ /g'); do CSV_LINE="%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n";
OUTPUT_TARGET="csv";
echo "Account ID,Region,Instance ID,Hostname,Username,Main Group,SSH Group,Account Created Date,Account Age,Last Login Date,Last Login Age,Never Logged In,Login Source,Status";
;;
*)
OUTPUT_TARGET="text";
;;
esac;
# collect info via: curl http://169.254.169.254/latest/meta-data/
instance_data=$(
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") &&
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/dynamic/instance-identity/document
)
instance_id=$(echo "${instance_data}" | jq .instanceId)
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";
exec &> >(tee -a "${LOG}");
echo "[START] =============>";
echo "AWS ID : ${account_id}";
echo "Region : ${region}";
echo "Instance ID : ${instance_id}";
echo "Hostname : $(hostname)";
echo "Run date : $(date +"%F %T")";
echo "Max age last login : ${max_age_login} days";
echo "Warn age last login: ${warn_age_login} days";
echo "Max age no login : ${max_age_create} days";
elif [ "${OUTPUT_TARGET}" = "json" ]; then
echo '"Info": {'
echo '"AccountId": '"${account_id}"',';
echo '"Region": '"${region}"',';
echo '"InstanceId": '"${instance_id}"',';
echo '"Hostname": "'"$(hostname)"'",';
echo '"Date": "'"$(date +"%F %T")"'",';
echo '"MaxAgeLogin": '${max_age_login}',';
echo '"WarnAgeLogin": '${warn_age_login}',';
echo '"MaxAgeCreate": '${max_age_create}'';
echo '},'
echo '"Users": ['
fi;
for ssh_group in "${ssh_groups[@]}"; do
if [ "${OUTPUT_TARGET}" = "text" ]; then
echo "--------------------->"
if [ "${ssh_group}" = "${ssh_reject_group}" ]; then
echo "Showing current SSH Reject users:";
unlock_flag=1
else
echo "Checking Group : ${ssh_group}";
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 # check that user exists in passwd
if ! id "${username}" &>/dev/null; then if ! id "${username}" &>/dev/null; then
echo "[!] User $username does not exists in /etc/passwd file"; out_string="[!] User $username does not exists in /etc/passwd file";
case "${OUTPUT_TARGET}" in
text)
echo "${out_string}";
;;
json)
echo "{";
echo '"Username": "'"${username}"'",';
echo '"SshGroup": "'"${ssh_group}"'",';
echo '"MainGroup": "",';
echo '"SubGroups": [],';
echo '"AccountCreatedDate": "",';
echo '"AccountAge": "",';
echo '"LastLoginDate": "",';
echo '"LastLoginAge": "",';
echo '"LoginSource": "",';
echo '"NeverLoggedIn": true,';
echo '"Status": "'"${out_string}"'"';
echo "}";
;;
csv)
# shellcheck disable=SC2059
printf "${CSV_LINE}" "${account_id}" "${region}" "${instance_id}" "$(hostname)" "${username}" "" "${ssh_group}" "" "" "" "" "true" "${out_string}"
;;
esac;
continue; continue;
fi; fi;
# for json output, we need , between outputs
if [ "${OUTPUT_TARGET}" = "json" ] && [ $first_run -eq 0 ]; then
echo ",";
fi;
first_run=0;
# unlock lis of users
if [ $unlock_flag -eq 1 ]; then
unlock_accounts="${unlock_accounts} ${username}"
fi;
account_age=0; account_age=0;
lock_user=0; lock_user=0;
out_string=""; out_string="";
# get the main group for this user
main_group=$(id -gn "${username}")
# get all the sub groups for this user, and remove the main groups
sub_groups=$(id -Gn "${username}" | sed -e "s/${main_group}//" | sed -e "s/${ssh_group}//")
#echo "* Checking user ${username}"; #echo "* Checking user ${username}";
# check user create time, if we have set it in comment # check user create time, if we have set it in comment
user_create_date=$(cat /etc/passwd | grep "${username}:" | cut -d ":" -f 5); user_create_date_string=$(grep "${username}:" /etc/passwd | cut -d ":" -f 5);
# if empty try last password set time # if empty try last password set time
if [ -z "${user_create_date}" ]; then if ! [[ "${user_create_date_string}" =~ ^\d{4}-\d{2}-\{2} ]]; then
# user L 11/09/2020 0 99999 7 -1 # user L 11/09/2020 0 99999 7 -1
user_create_date=$(passwd -S ${username} | cut -d " " -f 3); user_create_date_string=$(passwd -S "${username}" | cut -d " " -f 3);
fi; fi;
# last try is user home .bash_logout # last try is user home .bash_logout
if [ -z "${user_create_date}" ]; then if ! [[ "${user_create_date_string}" =~ ^\d{4}-\d{2}-\{2} ]]; then
home_dir=$(cat /etc/passwd | grep "${username}:" | cut -d ":" -f 6)"/.bash_logout"; # try logout or bash history
user_create_date=$(stat -c %Z "${home_dir}"); home_dir_bl=$(grep "${username}:" /etc/passwd | cut -d ":" -f 6)"/.bash_logout";
home_dir_bh=$(grep "${username}:" /etc/passwd | cut -d ":" -f 6)"/.bash_history";
# check that this file exists
if [ -f "${home_dir_bl}" ]; then
user_create_date_string=$(stat -c %Z "${home_dir_bl}");
elif [ -f "${home_dir_bh}" ]; then
user_create_date_string=$(stat -c %Z "${home_dir_bh}");
fi;
fi;
# still no date -> set empty
if ! [[ "${user_create_date_string}" =~ ^\d{4}-\d{2}-\{2} ]]; then
user_create_date_string="";
fi; fi;
# below only works if the user logged in, a lot of them are just file upload # 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 # users. Use the collect script from systemd-logind or /var/log/secure
# Username Port From Latest # for the rest use lslogin, returns ":" separted list, not set is never logged in
# user pts/35 10.110.160.230 Wed Nov 2 09:40:35 +0900 2022 # LAST LOGIN :FAILED LOGIN
last_login_string=$(lastlog -u ${username} | sed 1d); # 2025-09-12T09:56:22+09:00:
search="Never logged in"; 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=""; found="";
login_source="";
last_login_date="";
account_age="";
last_login="";
# problem with running rep check in if # problem with running rep check in if
if [ -f "${AUTH_LOG}" ]; then if [ -f "${AUTH_LOG}" ]; then
found=$(grep "${username};" "${AUTH_LOG}"); found=$(grep "${username};" "${AUTH_LOG}");
fi; fi;
if [ ! -z "${found}" ]; then # always pre work account dates if they exist, but output only if text
last_login_date=$(grep "${username};" "${AUTH_LOG}" | cut -d ";" -f 2 | date +"%s" -f -); if [ -n "${user_create_date_string}" ]; then
last_login=$(awk '{printf("%.0f\n",($1-$2)/$3)}' <<<"${now} ${last_login_date} ${day}"); user_create_date=$(echo "${user_create_date_string}" | date +"%s" -f -);
if [ ${last_login} -gt ${max_age_login} ]; then
out_string="[!] last ssh log in ${last_login} days ago";
lock_user=1;
else
out_string="OK [ssh]";
fi;
elif [ ! -z "${last_login_string##*$search*}" ]; 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
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";
lock_user=1;
else
out_string="OK [lastlog]";
fi;
elif [ ! -z "${user_create_date}" ]; then
user_create_date=$(echo "${user_create_date}" | date +"%s" -f -);
# if all empty, we continue with only check if user has last login date # if all empty, we continue with only check if user has last login date
# else get days since creation # else get days since creation
#account_age=$[ ($(date +"%s")-$(date -d "${user_create_date}" +"%s"))/24 ]; #account_age=$[ ($(date +"%s")-$(date -d "${user_create_date}" +"%s"))/24 ];
account_age=$(awk '{printf("%.0f\n",($1-$2)/$3)}' <<<"${now} ${user_create_date} ${day}"); account_age=$(awk '{printf("%.0f\n",($1-$2)/$3)}' <<<"${now} ${user_create_date} ${day}");
if [ ${account_age} -gt ${max_age_create} ]; then user_create_date_out=$(echo "${user_create_date_string}" | date +"%F" -f -);
out_string="[!] Never logged in, account created ${account_age} days ago"; fi;
lock_user=1; if [ -n "${found}" ]; then
last_login_date_string=$(grep "${username};" "${AUTH_LOG}" | cut -d ";" -f 2);
last_login_date=$(echo "${last_login_date_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 ssh log in ${last_login} days ago";
if [ "${ssh_group}" != "${ssh_reject_group}" ]; then
lock_user=1;
fi;
elif [ "${last_login}" -gt ${warn_age_login} ]; then
out_string="WARN [last ssh login ${last_login} days ago]";
else else
out_string="OK [first login]"; out_string="OK [ssh, ${last_login} days ago]";
fi; fi;
login_source="ssh";
# rewrite to Y-M-D, aka
last_login_date="${last_login_date_string}"
elif [ -n "${last_login_date}" ]; then
# if we have "** Never logged in**" the user never logged in
# 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";
if [ "${ssh_group}" != "${ssh_reject_group}" ]; then
lock_user=1;
fi;
elif [ "${last_login}" -gt ${warn_age_login} ]; then
out_string="WARN [last terminal login ${last_login} days ago]";
else
out_string="OK [lastlog, ${last_login} days ago]";
fi;
login_source="lastlog";
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";
if [ "${ssh_group}" != "${ssh_reject_group}" ]; then
lock_user=1;
fi;
else
out_string="OK [Never logged in, created ${account_age} days ago]";
fi;
never_logged_in="true";
else else
out_string="[!!!] Never logged in and we have no create date"; out_string="[!!!] Never logged in and we have no create date";
never_logged_in="true";
fi; fi;
# build delete output # build delete output
if [ ${lock_user} = 1 ]; then if [ ${lock_user} -eq 1 ]; then
lock_accounts="${lock_accounts} ${username}" lock_accounts="${lock_accounts} ${username}"
fi; fi;
printf "* Checking user %-20s: %s\n" "${username}" "${out_string}"; case "${OUTPUT_TARGET}" in
done; text)
printf "* Checking user %-20s (%-20s): %s\n" "${username}" "${main_group}" "${out_string}";
;;
json)
sub_groups_string="["
sub_group_first=1
for s_group in $sub_groups; do
if [ "${sub_group_first}" = 0 ]; then
sub_groups_string="${sub_groups_string},";
fi;
sub_groups_string="${sub_groups_string}\"${s_group}\"";
sub_group_first=0;
done;
sub_groups_string="${sub_groups_string}]";
echo "{";
echo '"Username": "'"${username}"'",';
echo '"SshGroup": "'"${ssh_group}"'",';
echo '"MainGroup": "'"${main_group}"'",';
echo '"SubGroups": '"${sub_groups_string}"',';
echo '"AccountCreatedDate": "'"${user_create_date_out}"'",';
echo '"AccountAge": "'"${account_age}"'",';
echo '"LastLoginDate": "'"${last_login_date}"'",';
echo '"LastLoginAge": "'"${last_login}"'",';
echo '"LoginSource": "'"${login_source}"'",';
echo '"NeverLoggedIn": '"${never_logged_in}"',';
echo '"Status": "'"${out_string}"'"';
echo "}";
;;
csv)
# shellcheck disable=SC2059
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/,/\n/g')";
done; done;
echo "--------------------->" if [ "${OUTPUT_TARGET}" = "text" ]; then
echo "Showing current SSH Reject users:" if [ -n "${lock_accounts}" ]; then
for user in $(cat /etc/group|grep "${ssh_reject_group}:" | cut -d ":" -f 4 | sed -e 's/,/ /g'); do echo "--------------------->"
echo "${user}"; echo "% Run script below to move users to reject ssh group";
done; echo "";
if [ ! -z "${lock_accounts}" ]; then echo "bin/lock_user.sh ${lock_accounts}";
echo "--------------------->" fi;
echo "% Run script below to move users to reject ssh group"; if [ -n "${unlock_accounts}" ]; then
echo ""; echo "--------------------->"
echo "bin/lock_user.sh ${lock_accounts}"; echo "% Run script below to move users to allow or forward ssh group";
echo "";
echo "For ALLOW:"
echo "bin/unlock_user.sh -s allow ${unlock_accounts}";
echo "";
echo "For FORWARDONLY:"
echo "bin/unlock_user.sh -s forward ${unlock_accounts}";
fi;
echo "[END] ===============>"
elif [ "${OUTPUT_TARGET}" = "json" ]; then
# users
echo "]";
# overall
echo "}";
fi; fi;
echo "[END] ===============>"
# __END__ # __END__

View File

@@ -9,7 +9,7 @@ if [[ "$EUID" -ne "0" ]]; then
fi; fi;
# base folder # base folder
BASE_FOLDER=$(dirname $(readlink -f $0))"/"; BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
# auth log file # auth log file
AUTH_LOG="${BASE_FOLDER}/../auth-log/user_auth.log"; AUTH_LOG="${BASE_FOLDER}/../auth-log/user_auth.log";
if [ ! -f "${AUTH_LOG}" ]; then if [ ! -f "${AUTH_LOG}" ]; then
@@ -22,13 +22,19 @@ RUN_FULL_LOG=0;
# option parsing # option parsing
while getopts ":fd" opt; do while getopts ":fd" opt; do
case "${opt}" in case "${opt}" in
f|full) f) # full
echo "[!!!] Run through all log files to collect data"; echo "[!!!] Run through all log files to collect data";
RUN_FULL_LOG=1; RUN_FULL_LOG=1;
;; ;;
d|deubg) d) # deubg
DEBUG=1; DEBUG=1;
;; ;;
\?)
echo "";
echo "-f Collect all log data again";
echo "-d Debug output";
exit 1;
;;
esac; esac;
done; done;
@@ -37,8 +43,8 @@ function prD()
message="${1}"; message="${1}";
debug=${2:-0}; debug=${2:-0};
lb_off=${3:-0}; lb_off=${3:-0};
if [ ${debug} -eq 1 ]; then if [ "${debug}" -eq 1 ]; then
if [ ${lb_off} -eq 1 ]; then if [ "${lb_off}" -eq 1 ]; then
echo -n "${message}"; echo -n "${message}";
else else
echo "${message}"; echo "${message}";
@@ -61,7 +67,8 @@ function parseLog()
if [ "${logger}" = "systemd" ]; then if [ "${logger}" = "systemd" ]; then
# 2022-11-18T20:04:08+0900 # 2022-11-18T20:04:08+0900
auth_date=$(echo "${line}" | cut -d " " -f 1); auth_date=$(echo "${line}" | cut -d " " -f 1);
auth_user=$(echo "${line}" | cut -d "]" -f 2 | cut -d " " -f 7 | cut -d "." -f 1); # Note, instead of cut with dot, remove last dot in line
auth_user=$(echo "${line}" | cut -d "]" -f 2 | cut -d " " -f 7 | sed -e "s/\.$//");
else else
auth_date=$(echo "${line}" | cut -c 1-6)" ${start_year} "$(echo "${line}" | cut -c 8-15); auth_date=$(echo "${line}" | cut -c 1-6)" ${start_year} "$(echo "${line}" | cut -c 8-15);
auth_user=$(echo "${line}" | cut -d ")" -f 2 | cut -d " " -f 6 | cut -d "(" -f 1); auth_user=$(echo "${line}" | cut -d ")" -f 2 | cut -d " " -f 6 | cut -d "(" -f 1);
@@ -71,25 +78,26 @@ function parseLog()
# $(printf "USER: %-20s: %19s" "${auth_user}" "${auth_date}") # $(printf "USER: %-20s: %19s" "${auth_user}" "${auth_date}")
# prD "USER: $auth_user | DATE: $auth_date" ${debug} 1; # prD "USER: $auth_user | DATE: $auth_date" ${debug} 1;
printf -v msg "Source: %-10s | Year: %4s | Last auth user: %-20s: %19s" "${logger}" "${start_year}" "${auth_user}" "${auth_date}" printf -v msg "Source: %-10s | Year: %4s | Last auth user: %-20s: %19s" "${logger}" "${start_year}" "${auth_user}" "${auth_date}"
prD "${msg}" ${debug} 1; prD "${msg}" "${debug}" 1;
# find auth user in current auth file # find auth user in current auth file
# if not there attach, else replace date only # if not there attach, else replace date only
found=$(grep "${auth_user};" "${auth_log}"); found=$(grep "${auth_user};" "${auth_log}");
if [ -z "${found}" ]; then if [ -z "${found}" ]; then
prD " | Write new" ${debug}; prD " | Write new" "${debug}";
echo "${auth_user};${auth_date}" >> "${auth_log}"; echo "${auth_user};${auth_date}" >> "${auth_log}";
else else
prD " | Replace old" ${debug}; prD " | Replace old" "${debug}";
sed -i "s/${auth_user};.*$/${auth_user};${auth_date}/" "${auth_log}"; sed -i "s/${auth_user};.*$/${auth_user};${auth_date}/" "${auth_log}";
fi; fi;
} }
printf -v msg "Run date: %s %s" $(date +"%F %T") printf -v msg "Run date: %s" "$(date +"%F %T")"
prD "${msg}" ${DEBUG}; prD "${msg}" ${DEBUG};
# Collector script for login information via journalctl # Collector script for login information via journalctl
# if no systemd installed, try to get info from /var/log/secure or /var/log/auth.log # if no systemd installed, try to get info from /var/log/secure or /var/log/auth.log
readonly init_version=$(/proc/1/exe --version | head -n 1); init_version=$(/proc/1/exe --version | head -n 1);
readonly init_version;
if [ -z "${init_version##*systemd*}" ]; then if [ -z "${init_version##*systemd*}" ]; then
LOG_TARGET="systemd"; LOG_TARGET="systemd";
# for journalctl # for journalctl
@@ -102,8 +110,8 @@ if [ -z "${init_version##*systemd*}" ]; then
fi; fi;
# READ as other format so we get the YEAR -o short-iso # READ as other format so we get the YEAR -o short-iso
START_YEAR=$(date +%Y -d "1 day ago"); START_YEAR=$(date +%Y -d "1 day ago");
journalctl -u systemd-logind --no-pager -o short-iso ${OPT_START_DATE} ${OPT_END_DATE} | grep ": New session" | journalctl -u systemd-logind --no-pager -o short-iso "${OPT_START_DATE}" "${OPT_END_DATE}" | grep ": New session" |
while read line; do while read -r line; do
# # Nov 21 14:15:46 we.are.hostname.com systemd-logind[1865]: New session 12345 of user some^user. # # Nov 21 14:15:46 we.are.hostname.com systemd-logind[1865]: New session 12345 of user some^user.
# date: 5 chars # date: 5 chars
# time: 8 chars # time: 8 chars
@@ -119,11 +127,11 @@ else
# for secure/auth log # for secure/auth log
if [ $RUN_FULL_LOG -eq 1 ]; then if [ $RUN_FULL_LOG -eq 1 ]; then
# we loop over EACH file and get the DATE so we can have the correct YEAR # we loop over EACH file and get the DATE so we can have the correct YEAR
for sfile in $(ls -1 /var/log/secure*bz2); do for sfile in /var/log/secure*bz2; do
tz=$(stat -c %Z "${sfile}"); tz=$(stat -c %Z "${sfile}");
START_YEAR=$(date +%Y -d @${tz}); START_YEAR=$(date +%Y -d @"${tz}");
bunzip2 -ck "${sfile}" | grep ": session opened for user" | grep " by (uid=0)" | bunzip2 -ck "${sfile}" | grep ": session opened for user" | grep " by (uid=0)" |
while read line; do while read -r line; do
parseLog "${line}" "${AUTH_LOG}" "${START_YEAR}" "${LOG_TARGET}" ${DEBUG}; parseLog "${line}" "${AUTH_LOG}" "${START_YEAR}" "${LOG_TARGET}" ${DEBUG};
done; done;
done; done;
@@ -131,8 +139,8 @@ else
START_DATE="sshd" START_DATE="sshd"
fi; fi;
START_YEAR=$(date +%Y -d "1 day ago"); START_YEAR=$(date +%Y -d "1 day ago");
cat /var/log/secure | grep "${START_DATE}" | grep ": session opened for user" | grep " by (uid=0)" | grep "${START_DATE}" "/var/log/secure" | grep ": session opened for user" | grep " by (uid=0)" |
while read line; do while read -r line; do
parseLog "${line}" "${AUTH_LOG}" "${START_YEAR}" "${LOG_TARGET}" ${DEBUG}; parseLog "${line}" "${AUTH_LOG}" "${START_YEAR}" "${LOG_TARGET}" ${DEBUG};
done; done;
fi; fi;

View File

@@ -2,13 +2,14 @@
# * input file # * input file
# user_list.txt # user_list.txt
# <ignored id>;<user name>;<group>[,sub group,sub group];<ssh access type>;[override password];[override hostname];[override ssh key type] # <ignored id>;<user name>;<group>[,sub group,sub group];<ssh access type>|<no login flag>;[override password];[override hostname];[override ssh key type]
# lines with # are skipped # lines with # are skipped
# already created users are skipped # already created users are skipped
# Mandatory: <ignored id>;<user name>;<group>;<ssh access type> # Mandatory: <ignored id>;<user name>;<group>;<ssh access type>
# <ssh access type> can be # <ssh access type> can be
# allow (full login access) # allow (full login access)
# forward (forward/jump host only) # forward (forward/jump host only)
# if in this column with pipe (|) the flag "no_login" is set then the default shell will change to "/sbin/nologin"
# * output file # * output file
# <date>;<target connect host name>;<hostname>;<username>;<password>;<ssh access type> # <date>;<target connect host name>;<hostname>;<username>;<password>;<ssh access type>
# If already existing PEM key is used then <password> is [ALREADY SET] # If already existing PEM key is used then <password> is [ALREADY SET]
@@ -30,16 +31,16 @@ INFO=0; # no creation of anything, just print info strings
GO=0; # without this flag the script will exit with an info box GO=0; # without this flag the script will exit with an info box
while getopts ":gtih:" opt; do while getopts ":gtih:" opt; do
case "${opt}" in case "${opt}" in
g|go) g) # go
GO=1; GO=1;
;; ;;
t|test) t) # test
TEST=1; TEST=1;
;; ;;
i|info) i) # info
INFO=1; INFO=1;
;; ;;
h|home) h) # home
HOME_LOCATION="${OPTARG}"; HOME_LOCATION="${OPTARG}";
;; ;;
\?) \?)
@@ -58,7 +59,7 @@ timestamp=$(date +%Y%m%d-%H%M%S)
# character to set getween info blocks # character to set getween info blocks
separator="#"; separator="#";
# base folder for all data # base folder for all data
BASE_FOLDER=$(dirname $(readlink -f $0))"/"; BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
# home folder is always thome # home folder is always thome
HOME_BASE="/home/"; HOME_BASE="/home/";
# config location # config location
@@ -66,10 +67,12 @@ CONFIG_BASE="${BASE_FOLDER}../config/";
# check config folder for .env file with HOME_LOCATION # check config folder for .env file with HOME_LOCATION
# only use if HOME_LOCATION not yet set # only use if HOME_LOCATION not yet set
if [ -z "${HOME_LOCATION}" ] && [ -f "${CONFIG_BASE}create_user.cfg" ]; then if [ -z "${HOME_LOCATION}" ] && [ -f "${CONFIG_BASE}create_user.cfg" ]; then
source <(grep = ${CONFIG_BASE}create_user.cfg | sed 's/ *= */=/g') # shellcheck source=../config/create_user.cfg"
# shellcheck disable=SC1091
source <(grep "=" "${CONFIG_BASE}create_user.cfg" | sed 's/ *= */=/g')
fi; fi;
if [ ! -z "${HOME_LOCATION}" ]; then if [ -n "${HOME_LOCATION}" ]; then
# must start with / as it has to be from root # must start with / as it has to be from root
if [ "${HOME_LOCATION##/*}" ]; then if [ "${HOME_LOCATION##/*}" ]; then
echo "Home location folder must start with a slash (/): ${HOME_LOCATION}"; echo "Home location folder must start with a slash (/): ${HOME_LOCATION}";
@@ -87,6 +90,13 @@ if [ ! -d "${HOME_FOLDER}" ]; then
echo "Home folder location not found: ${HOME_FOLDER}"; echo "Home folder location not found: ${HOME_FOLDER}";
error=1; error=1;
fi; fi;
# allow 10 to 39 length for password
if [ -n "${PASSWORD_LENGTH}" ] && ! [[ "${PASSWORD_LENGTH}" =~ ^[13][0-9]$ ]]; then
echo "Password length set error, can only be a value between 10 and 39";
error=1;
elif [ -z "${PASSWORD_LENGTH}" ]; then
PASSWORD_LENGTH=14;
fi;
# home dir error abort # home dir error abort
if [ $error -eq 1 ]; then if [ $error -eq 1 ]; then
exit; exit;
@@ -104,12 +114,17 @@ ssh_keytype='';
# sshallow or sshforward # sshallow or sshforward
ssh_group=''; ssh_group='';
ssh_forward_ok=0; ssh_forward_ok=0;
# login shells
login_shell="/bin/bash";
no_login_shell="/sbin/nologin";
user_login_shell="";
# detect ssh authorized_keys setting # detect ssh authorized_keys setting
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=''; SSH_CENTRAL_AUTHORIZED_FILE_FOLDER='';
SSH_AUTHORIZED_FILE=''; SSH_AUTHORIZED_FILE='';
# shellcheck disable=SC2013
for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do
if [ ! -z $(echo "${cf}" | grep "%u") ]; then if echo "$cf" | grep -q "%u"; then
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=$(echo "${cf}" | sed -e 's/%u//'); SSH_CENTRAL_AUTHORIZED_FILE_FOLDER="${cf/%%u//}";
if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}"; echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}";
exit; exit;
@@ -126,24 +141,21 @@ if [ ! -d "${ROOT_FOLDER}${output_zip_folder}" ]; then
mkdir "${ROOT_FOLDER}${output_zip_folder}"; mkdir "${ROOT_FOLDER}${output_zip_folder}";
fi; fi;
# check if password generate software is installed # check if password generate software is installed
# if [ ! command -v pwgen &> /dev/null ]; then if [ -z "$(command -v pwgen)" ]; then
if [ -z $(command -v pwgen) ]; then
echo "Missing pwgen application, aborting"; echo "Missing pwgen application, aborting";
error=1; error=1;
fi; fi;
# check for zip # check for zip
# if [ ! command -v zip &> /dev/null ]; then if [ -z "$(command -v zip)" ]; then
if [ -z $(command -v zip) ]; then
echo "Missing zip application, aborting"; echo "Missing zip application, aborting";
error=1; error=1;
fi; fi;
# check if sshallow or sshfoward group exists if ! grep -q "sshallow:" "/etc/group"; then
if [ -z $(cat /etc/group | grep "sshallow:") ]; then
echo "Missing ssh access group: sshallow"; echo "Missing ssh access group: sshallow";
error=1; error=1;
fi; fi;
# flag if we can set ssh forward # flag if we can set ssh forward
if [ ! -z $(cat /etc/group | grep "sshforward:") ]; then if ! grep -q "sshforward:" "/etc/group"; then
ssh_forward_ok=1; ssh_forward_ok=1;
fi; fi;
# check if user list file exists # check if user list file exists
@@ -152,10 +164,10 @@ if [ ! -f "${ROOT_FOLDER}${input_file}" ]; then
error=1; error=1;
fi; fi;
# make sure my own folder is owned by root and 600 (except for testing) # make sure my own folder is owned by root and 600 (except for testing)
if [ $(stat -c %a .) != "600" ]; then if [ "$(stat -c %a .)" != "600" ]; then
echo "!!!! RECOMMENDED TO HAVE BASE FOLDER SET TO '600' AND USER 'root' !!!!" echo "!!!! RECOMMENDED TO HAVE BASE FOLDER SET TO '600' AND USER 'root' !!!!"
fi; fi;
if [ $(whoami) != "root" ]; then if [ "$(whoami)" != "root" ]; then
if [ ${TEST} -eq 0 ] && [ ${INFO} -eq 0 ]; then if [ ${TEST} -eq 0 ] && [ ${INFO} -eq 0 ]; then
echo "Script must be run as root user"; echo "Script must be run as root user";
error=1; error=1;
@@ -164,6 +176,12 @@ if [ $(whoami) != "root" ]; then
fi; fi;
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 # exit if not -g parameter set
if [ $GO -eq 0 ]; then if [ $GO -eq 0 ]; then
echo "Script has to be run with -g option for actual user creation."; echo "Script has to be run with -g option for actual user creation.";
@@ -175,58 +193,99 @@ if [ $error -eq 1 ]; then
exit; exit;
fi; 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 # create users
cat "${ROOT_FOLDER}${input_file}" | while read -r i; do
while read i; do # run error for one row
run_error=0;
# skip rows start with # (comment) # skip rows start with # (comment)
if [[ "${i}" =~ ^\# ]]; then if [[ "${i}" =~ ^\# ]]; then
continue; continue;
fi; 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 # POS 2: make lower case, remove spaces
username=$(echo "${i}" | cut -d ";" -f 2 | tr A-Z a-z | tr -d ' '); username=$(echo "${i}" | cut -d ";" -f 2 | tr "[:upper:]" "[:lower:]" | tr -d ' ');
# check username is alphanumeric with . # check username is alphanumeric with .
if ! [[ "${username}" =~ ^[a-z0-9]+([.a-z0-9_-]+[a-z0-9])?$ ]]; then 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}"; run_error=1;
if [ ${TEST} -eq 0 ]; then write_log "[ERROR] User name can only be a-z 0-9 - _ . and cannot start or end with - . or _: ${username}" "1";
break;
fi;
fi; fi;
# POS 3: groups # POS 3: groups
_group=$(echo "${i}" | cut -d ";" -f 3 | tr A-Z a-z | tr -d ' '); _group=$(echo "${i}" | cut -d ";" -f 3 | tr "[:upper:]" "[:lower:]" | tr -d ' ');
group=$(echo "${_group}" | cut -d "," -f 1); group=$(echo "${_group}" | cut -d "," -f 1);
sub_group=""; sub_group="";
# POS 4: ssh access type # POS 4: ssh access type and no login flag
ssh_access_type=$(echo "${i}" | cut -d ";" -f 4 | tr A-Z a-z | tr -d ' '); # no login flag
no_login_flag="";
# if there is a pipe, check, else ignore
if echo "${i}" | cut -d ";" -f 4 | grep -q "|"; then
no_login_flag=$(echo "${i}" | cut -d ";" -f 4 | cut -d "|" -f 2);
fi;
# anything set in no login shell flag, we set no login shell
if [ -n "${no_login_flag}" ]; then
user_login_shell="${no_login_shell}";
else
user_login_shell="${login_shell}";
fi;
# ssh access type
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 not allow or forward, set to access
if [ "${ssh_access_type}" != "allow" ] && [ "${ssh_access_type}" != "forward" ]; then if [ "${ssh_access_type}" != "allow" ] && [ "${ssh_access_type}" != "forward" ]; then
echo "[!!] Not valid ssh access type ${ssh_access_type}, set to allow"; run_error=1;
ssh_access_type="allow"; write_log "[ERROR] Not valid ssh access type ${ssh_access_type}" "1";
fi; fi;
if [ $ssh_forward_ok -eq 0 ] && [ "${ssh_access_type}" = "forward" ]; then if [ $ssh_forward_ok -eq 0 ] && [ "${ssh_access_type}" = "forward" ]; then
echo "[!!!] sshforward group does not exsts, cannot set user ${username}"; write_log "[ERROR] sshforward group does not exsts, cannot set user ${username}" "1";
if [ ${TEST} -eq 0 ]; then run_error=1;
break;
fi;
fi; fi;
ssh_group="ssh${ssh_access_type}"; ssh_group="ssh${ssh_access_type}";
# sshallow group is always added # sshallow group is always added
sub_group_opt=" -G ${ssh_group}"; sub_group_opt=("${ssh_group}");
# check if "," inside and extract sub groups # check if "," inside and extract sub groups
if [ -z "${_group##*,*}" ]; then if [ -z "${_group##*,*}" ]; then
sub_group=$(echo "${_group}" | cut -d "," -f 2-); sub_group=$(echo "${_group}" | cut -d "," -f 2-);
sub_group_opt=" -G ${sub_group}"; sub_group_opt+=("${sub_group}");
fi; fi;
# POS 5: do we have a password preset # POS 5: do we have a password preset
_password=$(echo "${i}" | cut -d ";" -f 5); _password=$(echo "${i}" | cut -d ";" -f 5);
# POS 6: override host name, lowercase and spaces removed # POS 6: override host name, lowercase and spaces removed
_hostname=$(echo "${i}" | cut -d ";" -f 6 | tr A-Z a-z | tr -d ' '); _hostname=$(echo "${i}" | cut -d ";" -f 6 | tr "[:upper:]" "[:lower:]" | tr -d ' ');
if [ -z "${_hostname}" ]; then if [ -z "${_hostname}" ]; then
hostname=${host}; hostname=${host};
else else
hostname=${_hostname}; hostname=${_hostname};
fi; fi;
# POS 7: ssh keytype override # POS 7: ssh keytype override
_ssh_keytype=$(echo "${i}" | cut -d ";" -f 7 | tr A-Z a-z | tr -d ' '); _ssh_keytype=$(echo "${i}" | cut -d ";" -f 7 | tr "[:upper:]" "[:lower:]" | tr -d ' ');
if [ "${_ssh_keytype}" = "rsa" ]; then if [ "${_ssh_keytype}" = "rsa" ]; then
ssh_keytype="${_ssh_keytype}"; ssh_keytype="${_ssh_keytype}";
#echo "[!!] BACKWARDS COMPATIBLE RSA TYPE SELECTION [!!]"; #echo "[!!] BACKWARDS COMPATIBLE RSA TYPE SELECTION [!!]";
@@ -235,24 +294,35 @@ while read i; do
fi; fi;
# user & group not set # user & group not set
if [ -z "${username}" ] || [ -z "${_group}" ]; then if [ -z "${username}" ] || [ -z "${_group}" ]; then
echo "[!!!!!] Missing user or group entry for ${username}/${_group}"; run_error=1;
echo "[*** ABORT RUN ***]" write_log "[ERROR] Missing user or group entry for ${username}/${_group}" "1";
if [ ${TEST} -eq 0 ]; then
break;
fi;
else else
group_error=0; group_error=0;
# check group names valid # check group names valid
for create_group in ${_group//,/ }; do for create_group in ${_group//,/ }; do
if ! [[ "${create_group}" =~ ^[a-z0-9]+([a-z0-9_-]+[a-z0-9])?$ ]]; then 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; group_error=1;
fi; fi;
done; done;
if [ $group_error -eq 1 ] && [ ${TEST} -eq 0 ]; then if [ $group_error -eq 1 ]; then
break; run_error=1;
fi; fi;
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 file name part without folder
ssh_keygen_id="${hostname}${separator}${group}${separator}${username}${separator}${ssh_keytype}.pem"; ssh_keygen_id="${hostname}${separator}${group}${separator}${username}${separator}${ssh_keytype}.pem";
# the full file including folder name # the full file including folder name
@@ -262,24 +332,25 @@ while read i; do
# check existing pub file # check existing pub file
ssh_keyfile_check_pub="${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}${ssh_keygen_id}.pub"; ssh_keyfile_check_pub="${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}${ssh_keygen_id}.pub";
# MARK: INFO
if [ ${INFO} -eq 1 ]; then 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 # 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
if getent passwd ${username} > /dev/null 2>&1; then info_string="${info_string}, User exists";
echo -n ", User exists";
fi; fi;
if [ -f "${ssh_keyfile_check_pub}" ]; then if [ -f "${ssh_keyfile_check_pub}" ]; then
echo -n ", SSH Pub key OK"; info_string="${info_string}, SSH Pub key OK";
fi; fi;
# line break echo "${info_string}";
echo "";
continue; continue;
fi; fi;
# MARK: CREATE
# add group for each entry in _group # add group for each entry in _group
for create_group in ${_group//,/ }; do for create_group in ${_group//,/ }; do
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
groupadd -f ${create_group}; groupadd -f "${create_group}";
else else
echo "$> groupadd -f ${create_group}"; echo "$> groupadd -f ${create_group}";
fi; fi;
@@ -287,14 +358,20 @@ while read i; do
# check if user is not already created # check if user is not already created
# if getent passwd ${username} > /dev/null 2>&1; then # if getent passwd ${username} > /dev/null 2>&1; then
if id "${username}" &>/dev/null; then if id "${username}" &>/dev/null; then
echo "-- Skip '${username}:${group}(${sub_group})'"; write_log "-- Skip '${username}:${group}(${sub_group})'" "1";
else 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[*]}")"
"-d" "${HOME_FOLDER}${username}" "-m"
"${username}"
);
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
# comment is user create time # comment is user create time
useradd -c `date +"%F"` -s /bin/bash -g ${group}${sub_group_opt} -d "${HOME_FOLDER}${username}" -m ${username}; useradd "${params[@]}";
else else
echo "$> useradd -c `date +"%F"` -s /bin/bash -g ${group}${sub_group_opt} -d "${HOME_FOLDER}${username}" -m ${username}"; echo "$> useradd ${params[*]}";
fi; fi;
fi; fi;
# set the auth file # set the auth file
@@ -309,16 +386,20 @@ while read i; do
# Note we only create a password if we need it # Note we only create a password if we need it
# password + store pwgen 10 1 -1 # password + store pwgen 10 1 -1
if [ -z "${_password}" ]; then if [ -z "${_password}" ]; then
password=$(printf "%s" $(pwgen 14 1)); password=$(printf "%s" "$(pwgen "${PASSWORD_LENGTH}" 1)");
elif [ "${_password}" = "SET_NO_PASSWORD" ]; then
# set empty
echo "* No password set";
password="";
else else
echo "! Override password set"; echo "! Override password set";
password=${_password}; password=${_password};
fi; fi;
# create SSH key # create SSH key
echo " > Create ssh key-pair '${ssh_keyfile}'"; write_log " > Create ssh key-pair: ${ssh_keyfile}" "1";
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
ssh-keygen \ ssh-keygen \
-t ${ssh_keytype} \ -t "${ssh_keytype}" \
-f "${ssh_keyfile}" \ -f "${ssh_keyfile}" \
-C "${hostname}: ${username}@${group}" \ -C "${hostname}: ${username}@${group}" \
-a 100 -N "${password}" -a 100 -N "${password}"
@@ -328,50 +409,51 @@ while read i; do
else else
found=''; found='';
if [ -f "${SSH_AUTHORIZED_FILE}" ]; then if [ -f "${SSH_AUTHORIZED_FILE}" ]; then
found=$(grep "$(cat ${ssh_keyfile_check_pub})" ${SSH_AUTHORIZED_FILE}); found=$(grep "$(cat "${ssh_keyfile_check_pub}")" "${SSH_AUTHORIZED_FILE}");
fi; fi;
if [ ! -z "${found}" ]; then if [ -n "${found}" ]; then
skip_ssh=1; skip_ssh=1;
echo "-- Skip SSH Key creation: ${ssh_keygen_id}.pub"; write_log "-- Skip SSH Key creation: ${ssh_keygen_id}.pub" "1";
else else
# override previously set with stored one # override previously set with stored one
ssh_keyfile_pub=${ssh_keyfile_check_pub}; 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 # Password already set notification
fi; fi;
password="[ALREADY SET]"; password="[ALREADY SET]";
fi; fi;
if [ ${skip_ssh} -eq 0 ]; then if [ ${skip_ssh} -eq 0 ]; then
# MARK: SSH CREATE
# write login info to output file # write login info to output file
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
create_output_file="${ROOT_FOLDER}${output_file}"; create_output_file="${ROOT_FOLDER}${output_file}";
else else
create_output_file="${ROOT_FOLDER}${output_file}.TEST"; create_output_file="${ROOT_FOLDER}${output_file}.TEST";
fi; fi;
echo $(date +"%F %T")";"${host}";"${_hostname}";"${username}";"${password}";"${ssh_access_type} >> ${create_output_file}; echo "$(date +"%F %T");${host};${_hostname};${username};${password};${ssh_access_type}" >> "${create_output_file}";
# create folder only if we do not have central # create folder only if we do not have central
# create the SSH foler and authorized access file with correct permissions # create the SSH foler and authorized access file with correct permissions
if [ -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then if [ -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo " > Create .ssh folder"; echo " > Create .ssh folder";
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
mkdir ${HOME_FOLDER}${username}/.ssh/; mkdir "${HOME_FOLDER}${username}/.ssh/";
else else
echo "$> mkdir ${HOME_FOLDER}${username}/.ssh/"; echo "$> mkdir \"${HOME_FOLDER}${username}/.ssh/\"";
fi; fi;
fi; fi;
# add # add
echo " > Add public into authorized_keys file"; echo " > Add public into authorized_keys file";
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
if if
[ ! -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ] && [ -n "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ] &&
[ -f "${SSH_AUTHORIZED_FILE}" ]; [ -f "${SSH_AUTHORIZED_FILE}" ];
then then
chattr -i ${SSH_AUTHORIZED_FILE}; chattr -i "${SSH_AUTHORIZED_FILE}";
fi; fi;
cat "${ssh_keyfile_pub}" > ${SSH_AUTHORIZED_FILE}; cat "${ssh_keyfile_pub}" > "${SSH_AUTHORIZED_FILE}";
else else
if if
[ ! -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ] && [ -n "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ] &&
[ -f "${SSH_AUTHORIZED_FILE}" ]; [ -f "${SSH_AUTHORIZED_FILE}" ];
then then
echo "$> chattr -i ${SSH_AUTHORIZED_FILE}"; echo "$> chattr -i ${SSH_AUTHORIZED_FILE}";
@@ -382,42 +464,54 @@ while read i; do
if [ -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then if [ -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo " > Secure home directory folder .ssh and authorized_keys file"; echo " > Secure home directory folder .ssh and authorized_keys file";
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
chown -R ${username}:${group} ${HOME_FOLDER}${username}/.ssh/; chown -R "${username}":"${group}" "${HOME_FOLDER}${username}/.ssh/";
chmod 700 ${HOME_FOLDER}${username}/.ssh/; chmod 700 "${HOME_FOLDER}${username}/.ssh/";
chmod 600 ${SSH_AUTHORIZED_FILE}; chmod 600 "${SSH_AUTHORIZED_FILE}";
else else
echo "$> chown -R ${username}:${group} ${HOME_FOLDER}${username}/.ssh/"; echo "$> chown -R \"${username}\":\"${group}\" \"${HOME_FOLDER}${username}/.ssh/\"";
echo "$> chmod 700 ${HOME_FOLDER}${username}/.ssh/"; echo "$> chmod 700 \"${HOME_FOLDER}${username}/.ssh/\"";
echo "$> chmod 600 ${SSH_AUTHORIZED_FILE}"; echo "$> chmod 600 \"${SSH_AUTHORIZED_FILE}\"";
fi; fi;
else else
echo " > Secure central authorized_keys file"; echo " > Secure central authorized_keys file";
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
chown ${username}:root ${SSH_AUTHORIZED_FILE}; chown "${username}":root "${SSH_AUTHORIZED_FILE}";
chmod 400 ${SSH_AUTHORIZED_FILE}; chmod 400 "${SSH_AUTHORIZED_FILE}";
# set +i so user can't change file # set +i so user can't change file
chattr +i ${SSH_AUTHORIZED_FILE}; chattr +i "${SSH_AUTHORIZED_FILE}";
else else
echo "$> chown ${username}:root ${SSH_AUTHORIZED_FILE}"; echo "$> chown \"${username}\":root \"${SSH_AUTHORIZED_FILE}\"";
echo "$> chmod 400 ${SSH_AUTHORIZED_FILE}"; echo "$> chmod 400 \"${SSH_AUTHORIZED_FILE}\"";
echo "$> chattr +i ${SSH_AUTHORIZED_FILE}"; echo "$> chattr +i \"${SSH_AUTHORIZED_FILE}\"";
fi; fi;
fi; fi;
fi; fi;
done; done <<< "$(cat "${ROOT_FOLDER}${input_file}")";
# End before anything because this is just info run # End before anything because this is just info run
if [ ${INFO} -eq 1 ]; then if [ ${INFO} -eq 1 ]; then
exit; exit;
fi; 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
has_pem_files=1;
fi;
# zip everything and remove data in ssh key folder, delete output file with passwords # zip everything and remove data in ssh key folder, delete output file with passwords
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
zip -r \ if [ "${has_pem_files}" -eq 1 ]; then
"${ROOT_FOLDER}${output_zip_folder}${output_zip}" \ zip -r \
"${input_file}" \ "${ROOT_FOLDER}${output_zip_folder}${output_zip}" \
"${output_file}" \ "${input_file}" \
"${SSH_KEYGEN_FOLDER}" \ "${output_file}" \
-x\*.gitignore; "${SSH_KEYGEN_FOLDER}" \
-x\*.gitignore;
echo "Download: ${ROOT_FOLDER}${output_zip_folder}${output_zip}";
else
echo "Skip ZIP file creation, no pem files";
fi;
else else
echo "zip -r \\" echo "zip -r \\"
echo "${ROOT_FOLDER}${output_zip_folder}${output_zip} \\" echo "${ROOT_FOLDER}${output_zip_folder}${output_zip} \\"
@@ -425,19 +519,28 @@ else
echo "${output_file} \\" echo "${output_file} \\"
echo "${SSH_KEYGEN_FOLDER} \\" echo "${SSH_KEYGEN_FOLDER} \\"
echo "-x\*.gitignore;" echo "-x\*.gitignore;"
echo "Download: ${ROOT_FOLDER}${output_zip_folder}${output_zip}";
fi; fi;
echo "Download: ${ROOT_FOLDER}${output_zip_folder}${output_zip}";
# cleam up user log file and ssh keys # cleam up user log file and ssh keys
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
# move pub to created folders if [ "${has_pem_files}" -eq 1 ]; then
mv "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}"*.pub "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}"; # move pub to created folders
# delete the rest mv "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}"*.pub "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}";
rm "${ROOT_FOLDER}${output_file}"; # delete the rest
rm "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}"*; rm "${ROOT_FOLDER}${output_file}";
rm "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}"*;
else
echo "Skip pub file move and cleanup, no pem files";
fi;
else else
echo "$> mv ${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}*.pub ${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB};"; echo "$> mv ${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}*.pub ${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB};";
echo "$> rm ${ROOT_FOLDER}${output_file}"; echo "$> rm ${ROOT_FOLDER}${output_file}";
echo "$> rm ${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}*"; echo "$> rm ${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}*";
fi; 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__ # __END__

View File

@@ -15,10 +15,10 @@ TEST=0; # do not run any actions
BACKUP=1; BACKUP=1;
while getopts ":tb" opt; do while getopts ":tb" opt; do
case "${opt}" in case "${opt}" in
t|test) t) # var/log/secure*bz2
TEST=1; TEST=1;
;; ;;
b|nobackup) b) # nobackup
BACKUP=0; BACKUP=0;
;; ;;
\?) \?)
@@ -32,7 +32,7 @@ while getopts ":tb" opt; do
done; done;
shift "$((OPTIND-1))" shift "$((OPTIND-1))"
if [ $(whoami) != "root" ]; then if [ "$(whoami)" != "root" ]; then
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
echo "Script must be run as root user"; echo "Script must be run as root user";
exit; exit;
@@ -53,27 +53,23 @@ timestamp=$(date +%Y%m%d-%H%M%S);
# character to set getween info blocks # character to set getween info blocks
separator="#"; separator="#";
# base folder for all data # base folder for all data
BASE_FOLDER=$(dirname $(readlink -f $0))"/"; BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
root_folder="${BASE_FOLDER}../"; root_folder="${BASE_FOLDER}../";
backup_folder="${BASE_FOLDER}../backup/"; backup_folder="${BASE_FOLDER}../backup/";
SSH_KEYGEN_FOLDER_CREATED_PUB='ssh-keygen-created-pub/'; # SSH_KEYGEN_FOLDER_CREATED_PUB='ssh-keygen-created-pub/';
input_file='user_list.txt'; input_file='user_list.txt';
user_list_file="${root_folder}${input_file}"; user_list_file="${root_folder}${input_file}";
# log file # log file
LOG="${BASE_FOLDER}/../log/delete_user."$(date +"%F_%H%m%S"); HISTORY="${BASE_FOLDER}/../log/delete_user.log";
if [ ${TEST} -eq 0 ]; then
LOG="${LOG}.log";
else
LOG="${LOG}.test.log";
fi;
# ignore users (root and admin users) # ignore users (root and admin users)
ignore_users=('root' 'ec2-user' 'ubuntu' 'admin'); ignore_users=('root' 'ec2-user' 'ubuntu' 'admin');
# detect ssh authorized_keys setting # detect ssh authorized_keys setting
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=''; SSH_CENTRAL_AUTHORIZED_FILE_FOLDER='';
SSH_AUTHORIZED_FILE=''; SSH_AUTHORIZED_FILE='';
for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do # shellcheck disable=SC2013
if [ ! -z $(echo "${cf}" | grep "%u") ]; then for cf in $(grep "^AuthorizedKeysFile" "/etc/ssh/sshd_config" | grep "%u"); do
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=$(echo "${cf}" | sed -e 's/%u//'); if echo "$cf" | grep -q "%u"; then
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER="${cf/%%u//}";
if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}"; echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}";
exit; exit;
@@ -86,17 +82,39 @@ if [ ! -f "${user_list_file}" ]; then
exit; exit;
fi; 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 # $1 ... $n
for username in "$@"; do for username in "$@"; do
error=0; error=0;
# skip if there is an option hidden # skip if there is an option hidden
# shellcheck disable=SC2154
if [[ ${_arg:0:1} = "-" ]]; then if [[ ${_arg:0:1} = "-" ]]; then
continue; continue;
fi; fi;
# skip ignore users, note that if a user is not in the sshallow list anyway # 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 # we skip them too, this is just in case check
if [[ " ${ignore_users[*]} " =~ " ${username} " ]]; then 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; continue;
fi; fi;
@@ -104,31 +122,33 @@ for username in "$@"; do
# if missing in or another do not continue # if missing in or another do not continue
if ! id "${username}" &>/dev/null; then if ! id "${username}" &>/dev/null; then
# not in passwd # 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; error=1;
fi; fi;
user_list_entry=$(grep "${username}" "${user_list_file}"); user_list_entry=$(grep "${username}" "${user_list_file}");
if [ -z "${user_list_entry}" ]; then 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; error=1;
elif [[ "${user_list_entry}" =~ ^#DELETED ]]; then 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; error=1;
fi; fi;
if [ $error -eq 1 ]; then if [ $error -eq 1 ]; then
overall_run_error=1;
write_log "[*** ABORT RUN ***]" "1";
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
break; break;
fi; fi;
fi; fi;
echo "=> Delete: ${username}"; write_log "=> Delete: ${username}" "1";
# ssh authorized file # ssh authorized file
SSH_AUTHORIZED_FILE="${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}${username}"; SSH_AUTHORIZED_FILE="${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}${username}";
# make backup from /home # make backup from /home
if [ ${BACKUP} -eq 1 ]; then 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"; backup_file="${backup_folder}${host}${separator}${username}.${timestamp}.tar.bz2";
files_list="${home_folder}"; files_list="${home_folder}";
if [ -f "${SSH_AUTHORIZED_FILE}" ]; then if [ -f "${SSH_AUTHORIZED_FILE}" ]; then
@@ -136,7 +156,7 @@ for username in "$@"; do
fi; fi;
echo "[0] Backup ${files_list} to ${backup_file}"; echo "[0] Backup ${files_list} to ${backup_file}";
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
tar cfjp "${backup_file}" ${file_list}; tar cfjp "${backup_file}" "${files_list}";
else else
echo "$> tar cfjp \"${backup_file}\" ${files_list};"; echo "$> tar cfjp \"${backup_file}\" ${files_list};";
fi; fi;
@@ -144,9 +164,13 @@ for username in "$@"; do
echo "[1] Remove user + home dir"; echo "[1] Remove user + home dir";
if [ ${TEST} -eq 0 ]; then 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 else
echo "$> userdel -r ${username}"; echo "$> usermod -G \"\" \"${username}\"";
echo "$> userdel -r \"${username}\"";
fi; fi;
# remove ssh files in pub # remove ssh files in pub
@@ -162,7 +186,7 @@ for username in "$@"; do
fi; fi;
else else
# Not critical error # Not critical error
echo "[?] Cannot find ${SSH_AUTHORIZED_FILE}"; write_log "[?] Cannot find ${SSH_AUTHORIZED_FILE}" "1";
fi; fi;
# Update user_list.txt file and add # for the line # Update user_list.txt file and add # for the line
@@ -172,11 +196,17 @@ for username in "$@"; do
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
sed -i -e "s/^\([A-Za-z0-9]\{1,\};${username};\)/#DELETED-${delete_date}:\1/" "${user_list_file}"; sed -i -e "s/^\([A-Za-z0-9]\{1,\};${username};\)/#DELETED-${delete_date}:\1/" "${user_list_file}";
else else
# shellcheck disable=SC2028
echo "$> sed -i -e \"s/^\([A-Za-z0-9]\{1,\};${username};\)/#DELETED-${delete_date}:\1/\" \"${user_list_file}\";"; echo "$> sed -i -e \"s/^\([A-Za-z0-9]\{1,\};${username};\)/#DELETED-${delete_date}:\1/\" \"${user_list_file}\";";
fi; fi;
echo $(date +"%F %T")";${host};${username}" >> "${LOG}"; echo "$(date +"%F %T");${host};${username};${TEST}" >> "${HISTORY}";
done; 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__ # __END__

View File

@@ -9,14 +9,18 @@
TEST=0; # no delete, just print TEST=0; # no delete, just print
while getopts ":t" opt; do while getopts ":t" opt; do
case "${opt}" in case "${opt}" in
t|test) t) # test
TEST=1; TEST=1;
;; ;;
\?)
echo "";
echo "-t test run, do not lock users";
;;
esac; esac;
done; done;
shift "$((OPTIND-1))" shift "$((OPTIND-1))"
if [ $(whoami) != "root" ]; then if [ "$(whoami)" != "root" ]; then
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
echo "Script must be run as root user"; echo "Script must be run as root user";
exit; exit;
@@ -34,35 +38,58 @@ fi;
ignore_users=('root' 'ec2-user' 'ubuntu' 'admin'); ignore_users=('root' 'ec2-user' 'ubuntu' 'admin');
# ssh reject group # ssh reject group
ssh_reject_group="sshreject"; ssh_reject_group="sshreject";
if [ -z $(cat /etc/group | grep "${ssh_reject_group}:") ]; then if ! grep -q "${ssh_reject_group}:" /etc/group; then
echo "Missing ssh reject group: ${ssh_reject_group}"; echo "Missing ssh reject group: ${ssh_reject_group}";
exit; exit;
fi; fi;
ssh_allow_group="sshallow"; ssh_allow_group="sshallow";
ssh_forward_group="sshfoward"; ssh_forward_group="sshforward";
user_group_tpl="gpasswd -d %s %s\ngpasswd -a %s %s\n"; 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 "--------------------->" echo "--------------------->"
# $1 ... $n # $1 ... $n
for username in "$@"; do for username in "$@"; do
# skip if there is an option hidden # skip if there is an option hidden
# shellcheck disable=SC2154
if [[ ${_arg:0:1} = "-" ]]; then if [[ ${_arg:0:1} = "-" ]]; then
continue; continue;
fi; fi;
# skip ignore users, note that if a user is not in the sshallow list anyway # 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 # we skip them too, this is just in case check
if [[ " ${ignore_users[*]} " =~ " ${username} " ]]; then 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; continue;
fi; fi;
# check that user exists in passwd # check that user exists in passwd
if ! id "${username}" &>/dev/null; then 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; continue;
fi; fi;
# if not check if in reject list # if not check if in reject list
if id -nGz "${username}" | grep -qzxF "${ssh_reject_group}"; then 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; continue;
fi; fi;
# check if user is in sshallow/forward list # check if user is in sshallow/forward list
@@ -72,16 +99,17 @@ for username in "$@"; do
fi; fi;
# if user is in ssh allow group and ALSO in ssh forward group -> bad # 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 id -nGz "${username}" | grep -qzxF "${ssh_forward_group}"; then
if [ ! -z "${ssh_remove_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; break;
fi; fi;
ssh_remove_group="${ssh_forward_group}"; ssh_remove_group="${ssh_forward_group}";
fi; fi;
if [ ! -z "${ssh_remove_group}" ]; then if [ -n "${ssh_remove_group}" ]; then
# remove user from ssh group and add to reject groups # 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 if [ ${TEST} -eq 1 ]; then
# shellcheck disable=SC2059
printf "${user_group_tpl}" "${username}" "${ssh_remove_group}" "${username}" "${ssh_reject_group}"; printf "${user_group_tpl}" "${username}" "${ssh_remove_group}" "${username}" "${ssh_reject_group}";
else else
gpasswd -d "${username}" "${ssh_remove_group}"; gpasswd -d "${username}" "${ssh_remove_group}";
@@ -89,7 +117,7 @@ for username in "$@"; do
fi; fi;
else else
# skip not ssh user # 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; fi;
done; done;

View File

@@ -12,15 +12,15 @@ OLD_USERNAME="";
NEW_USERNAME=""; NEW_USERNAME="";
while getopts ":to:n:" opt; do while getopts ":to:n:" opt; do
case "${opt}" in case "${opt}" in
t|test) t) # test
TEST=1; TEST=1;
;; ;;
o|old-user) o) # old-user
if [ -z "${OLD_USERNAME}" ]; then if [ -z "${OLD_USERNAME}" ]; then
OLD_USERNAME="${OPTARG}"; OLD_USERNAME="${OPTARG}";
fi; fi;
;; ;;
n|new-user) n) # new-user
if [ -z "${NEW_USERNAME}" ]; then if [ -z "${NEW_USERNAME}" ]; then
NEW_USERNAME="${OPTARG}"; NEW_USERNAME="${OPTARG}";
fi; fi;
@@ -36,7 +36,7 @@ while getopts ":to:n:" opt; do
done; done;
shift "$((OPTIND-1))" shift "$((OPTIND-1))"
if [ $(whoami) != "root" ]; then if [ "$(whoami)" != "root" ]; then
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
echo "Script must be run as root user"; echo "Script must be run as root user";
exit; exit;
@@ -47,35 +47,29 @@ fi;
error=0; error=0;
host=$(hostname); host=$(hostname);
timestamp=$(date +%Y%m%d-%H%M%S); # timestamp=$(date +%Y%m%d-%H%M%S);
# character to set getween info blocks # character to set getween info blocks
separator="#"; separator="#";
# base folder for all data # base folder for all data
BASE_FOLDER=$(dirname $(readlink -f $0))"/"; BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
root_folder="${BASE_FOLDER}../"; ROOT_FOLDER="${BASE_FOLDER}../";
SSH_KEYGEN_FOLDER_CREATED_PUB='ssh-keygen-created-pub/'; SSH_KEYGEN_FOLDER_CREATED_PUB='ssh-keygen-created-pub/';
input_file='user_list.txt'; input_file='user_list.txt';
user_list_file="${root_folder}${input_file}"; user_list_file="${ROOT_FOLDER}${input_file}";
default_ssh_keytype='ed25519'; default_ssh_keytype='ed25519';
ssh_keytype=''; 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 and admin users)
ignore_users=('root' 'ec2-user' 'ubuntu' 'admin'); ignore_users=('root' 'ec2-user' 'ubuntu' 'admin');
# detect ssh authorized_keys setting # detect ssh authorized_keys setting
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=''; SSH_CENTRAL_AUTHORIZED_FILE_FOLDER='';
SSH_AUTHORIZED_FILE=''; # SSH_AUTHORIZED_FILE='';
# shellcheck disable=SC2013
for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do
if [ ! -z $(echo "${cf}" | grep "%u") ]; then if echo "$cf" | grep -q "%u"; then
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=$(echo "${cf}" | sed -e 's/%u//'); SSH_CENTRAL_AUTHORIZED_FILE_FOLDER="${cf/%%u//}";
if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}"; echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}";
error=1; exit;
fi; fi;
fi; fi;
done; done;
@@ -101,11 +95,11 @@ fi;
# skip ignore users, note that if a user is not in the sshallow list anyway # 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 # we skip them too, this is just in case check
if [[ " ${ignore_users[*]} " =~ " ${OLD_USERNAME} " ]]; then if [[ " ${ignore_users[*]} " =~ [[:space:]]${OLD_USERNAME}[[:space:]] ]]; then
echo "[!] User ${OLD_USERNAME} is in the ignore user list"; echo "[!] User ${OLD_USERNAME} is in the ignore user list";
error=1; error=1;
fi; fi;
if [[ " ${ignore_users[*]} " =~ " ${NEW_USERNAME} " ]]; then if [[ " ${ignore_users[*]} " =~ [[:space:]]${NEW_USERNAME}[[:space:]] ]]; then
echo "[!] User ${NEW_USERNAME} is in the ignore user list"; echo "[!] User ${NEW_USERNAME} is in the ignore user list";
error=1; error=1;
fi; fi;
@@ -128,12 +122,12 @@ if [ -f "${user_list_file}" ]; then
error=1; error=1;
fi; fi;
# if the old user exists but as DELETED -> no go # if the old user exists but as DELETED -> no go
if [ ! -z $(echo "${user_list_entry}" | grep "#DELETED-") ]; then if ! echo "${user_list_entry}" | grep -q "#DELETED-"; then
echo "[!!!] User ${OLD_USERNAME} has been flagged as deleted"; echo "[!!!] User ${OLD_USERNAME} has been flagged as deleted";
error=1; error=1;
fi; fi;
# if new user name already exists in user list file for whatever reason # if new user name already exists in user list file for whatever reason
if [ $(grep "${NEW_USERNAME}" "${user_list_file}") ]; then if grep -q "${NEW_USERNAME}" "${user_list_file}"; then
echo "[!!!] User ${NEW_USERNAME} exists in user_list.txt file"; echo "[!!!] User ${NEW_USERNAME} exists in user_list.txt file";
error=1; error=1;
fi; fi;
@@ -143,34 +137,55 @@ if [ $error -eq 1 ]; then
exit; exit;
fi; 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 # parse user list entry for group/hostname/ssh type key to build ssh key list
# POS 3: groups # POS 3: groups
_group=$(echo "${user_list_entry}" | cut -d ";" -f 3 | tr A-Z a-z | tr -d ' '); _group=$(echo "${user_list_entry}" | cut -d ";" -f 3 | tr '[:upper:]' '[:lower:]' | tr -d ' ');
group=$(echo "${_group}" | cut -d "," -f 1); group=$(echo "${_group}" | cut -d "," -f 1);
# POS 6: override host name, lowercase and spaces removed # POS 6: override host name, lowercase and spaces removed
_hostname=$(echo "${user_list_entry}" | cut -d ";" -f 6 | tr A-Z a-z | tr -d ' '); _hostname=$(echo "${user_list_entry}" | cut -d ";" -f 6 | tr '[:upper:]' '[:lower:]' | tr -d ' ');
if [ -z "${_hostname}" ]; then if [ -z "${_hostname}" ]; then
hostname=${host}; hostname=${host};
else else
hostname=${_hostname}; hostname=${_hostname};
fi; fi;
# POS 7: ssh keytype override # POS 7: ssh keytype override
_ssh_keytype=$(echo "${user_list_entry}" | cut -d ";" -f 7 | tr A-Z a-z | tr -d ' '); _ssh_keytype=$(echo "${user_list_entry}" | cut -d ";" -f 7 | tr '[:upper:]' '[:lower:]' | tr -d ' ');
if [ "${_ssh_keytype}" = "rsa" ]; then if [ "${_ssh_keytype}" = "rsa" ]; then
ssh_keytype="${_ssh_keytype}"; ssh_keytype="${_ssh_keytype}";
else else
ssh_keytype=${default_ssh_keytype}; ssh_keytype=${default_ssh_keytype};
fi; 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); old_home_dir=$(getent passwd "${OLD_USERNAME}" | cut -d: -f6);
new_home_dir=$(echo "${old_home_dir}" | sed -e "s/\/${OLD_USERNAME}$/\/${NEW_USERNAME}/"); new_home_dir=$(echo "${old_home_dir}" | sed -e "s/\/${OLD_USERNAME}$/\/${NEW_USERNAME}/");
# rename user # rename user
if [ $TEST -eq 0 ]; then if [ $TEST -eq 0 ]; then
echo "usermod with ${new_home_dir}"; echo "usermod with ${new_home_dir}";
usermod -l ${NEW_USERNAME} -m -d "${new_home_dir}" ${OLD_USERNAME}; usermod -l "${NEW_USERNAME}" -m -d "${new_home_dir}" "${OLD_USERNAME}";
else else
echo "$> usermod -l ${NEW_USERNAME} -m -d \"${new_home_dir}\" ${OLD_USERNAME};"; echo "$> usermod -l ${NEW_USERNAME} -m -d \"${new_home_dir}\" ${OLD_USERNAME};";
fi fi
@@ -201,7 +216,7 @@ NEW_SSH_AUTHORIZED_FILE="${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}${NEW_USERNAME}";
if [ -f "${OLD_SSH_AUTHORIZED_FILE}" ]; then if [ -f "${OLD_SSH_AUTHORIZED_FILE}" ]; then
if [ $TEST -eq 0 ]; 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}"; chattr -i "${OLD_SSH_AUTHORIZED_FILE}";
mv "${OLD_SSH_AUTHORIZED_FILE}" "${NEW_SSH_AUTHORIZED_FILE}"; mv "${OLD_SSH_AUTHORIZED_FILE}" "${NEW_SSH_AUTHORIZED_FILE}";
chattr +i "${NEW_SSH_AUTHORIZED_FILE}"; chattr +i "${NEW_SSH_AUTHORIZED_FILE}";
@@ -211,7 +226,7 @@ if [ -f "${OLD_SSH_AUTHORIZED_FILE}" ]; then
echo "$> chattr +i \"${NEW_SSH_AUTHORIZED_FILE}\";"; echo "$> chattr +i \"${NEW_SSH_AUTHORIZED_FILE}\";";
fi; fi;
else else
echo "[?] ${OLD_SSH_AUTHORIZED_FILE} is missing"; write_log "[?] ${OLD_SSH_AUTHORIZED_FILE} is missing" "1";
fi; fi;
# rename keygen public file # rename keygen public file
@@ -220,13 +235,13 @@ NEW_ssh_keygen_pub="${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}${hostname}${s
if [ -f "${OLD_ssh_keygen_pub}" ]; then if [ -f "${OLD_ssh_keygen_pub}" ]; then
if [ $TEST -eq 0 ]; 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}"; mv "${OLD_ssh_keygen_pub}" "${NEW_ssh_keygen_pub}";
else else
echo "$> mv \"${OLD_ssh_keygen_pub}\" \"${NEW_ssh_keygen_pub}\";"; echo "$> mv \"${OLD_ssh_keygen_pub}\" \"${NEW_ssh_keygen_pub}\";";
fi; fi;
else else
echo "[?] ${OLD_ssh_keygen_pub} is missing"; write_log "[?] ${OLD_ssh_keygen_pub} is missing" "1";
fi; fi;
# rename entry in user list txt file # rename entry in user list txt file
@@ -234,6 +249,8 @@ if [ $TEST -eq 0 ]; then
echo "update ${user_list_file}"; echo "update ${user_list_file}";
sed -i -e "s/^\([A-Za-z0-9]\{1,\}\);${OLD_USERNAME};/\1;${NEW_USERNAME};/" "${user_list_file}"; sed -i -e "s/^\([A-Za-z0-9]\{1,\}\);${OLD_USERNAME};/\1;${NEW_USERNAME};/" "${user_list_file}";
else 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}\";"; echo "$> sed -i -e \"s/^\([A-Za-z0-9]\{1,\}\);${OLD_USERNAME};/\1;${NEW_USERNAME};/\" \"${user_list_file}\";";
fi; fi;

View File

@@ -10,19 +10,24 @@ TEST=0; # no delete, just print
SSH_GROUP_ADD=''; SSH_GROUP_ADD='';
while getopts ":ts:" opt; do while getopts ":ts:" opt; do
case "${opt}" in case "${opt}" in
t|test) t) # test
TEST=1; TEST=1;
;; ;;
s|sshgroup) s) # sshgroup
if [ -z "${SSH_GROUP_ADD}" ]; then if [ -z "${SSH_GROUP_ADD}" ]; then
SSH_GROUP_ADD=${OPTARG}; SSH_GROUP_ADD=${OPTARG};
fi; fi;
;; ;;
\?)
echo "";
echo "-t Test only, do not change user lock status";
echo "-s <group> Override ssh group from user_list.txt for this user";
;;
esac; esac;
done; done;
shift "$((OPTIND-1))" shift "$((OPTIND-1))"
if [ $(whoami) != "root" ]; then if [ "$(whoami)" != "root" ]; then
if [ ${TEST} -eq 0 ]; then if [ ${TEST} -eq 0 ]; then
echo "Script must be run as root user"; echo "Script must be run as root user";
exit; exit;
@@ -36,51 +41,72 @@ if [ $# -eq 0 ]; then
exit; exit;
fi; fi;
if [ ! -z "${SSH_GROUP_ADD}" ] && [ "${SSH_GROUP_ADD}" != "allow" ] && [ "${SSH_GROUP_ADD}" != "forward" ]; then if [ -n "${SSH_GROUP_ADD}" ] && [ "${SSH_GROUP_ADD}" != "allow" ] && [ "${SSH_GROUP_ADD}" != "forward" ]; then
echo "sshgroup option can only be 'allow' or 'forward'"; echo "sshgroup option can only be 'allow' or 'forward'";
exit; exit;
fi; fi;
BASE_FOLDER=$(dirname $(readlink -f $0))"/"; BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
root_folder="${BASE_FOLDER}../"; root_folder="${BASE_FOLDER}../";
input_file='user_list.txt'; input_file='user_list.txt';
# ignore users (root and admin users) # ignore users (root and admin users)
ignore_users=('root' 'ec2-user' 'ubuntu' 'admin'); ignore_users=('root' 'ec2-user' 'ubuntu' 'admin');
# ssh reject group # ssh reject group
ssh_reject_group="sshreject"; ssh_reject_group="sshreject";
if [ -z $(cat /etc/group | grep "${ssh_reject_group}:") ]; then if ! grep -q "${ssh_reject_group}:" /etc/group; then
echo "Missing ssh reject group: ${ssh_reject_group}"; echo "Missing ssh reject group: ${ssh_reject_group}";
exit; exit;
fi; fi;
ssh_allow_group="sshallow"; ssh_allow_group="sshallow";
ssh_forward_group="sshfoward"; ssh_forward_group="sshforward";
user_group_tpl="gpasswd -d %s %s\ngpasswd -a %s %s\n"; 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 "--------------------->" echo "--------------------->"
# $1 ... $n # $1 ... $n
for username in "$@"; do for username in "$@"; do
# skip if there is an option hidden # skip if there is an option hidden
# shellcheck disable=SC2154
if [[ ${_arg:0:1} = "-" ]]; then if [[ ${_arg:0:1} = "-" ]]; then
continue; continue;
fi; fi;
# skip ignore users, note that if a user is not in the sshallow list anyway # 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 # we skip them too, this is just in case check
if [[ " ${ignore_users[*]} " =~ " ${username} " ]]; then 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; continue;
fi; fi;
# check that user exists in passwd # check that user exists in passwd
if ! id "${username}" &>/dev/null; then 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; continue;
fi; fi;
# check if already in OK groups # check if already in OK groups
if id -nGz "${username}" | grep -qzxF "${ssh_allow_group}"; then 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; continue;
fi; fi;
if id -nGz "${username}" | grep -qzxF "${ssh_forward_group}"; then 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; continue;
fi; fi;
# try to find user in user_list.txt and get the allow/forward flag from there, # try to find user in user_list.txt and get the allow/forward flag from there,
@@ -88,9 +114,9 @@ for username in "$@"; do
# if not valid use allow # if not valid use allow
ssh_add_group="${SSH_GROUP_ADD}"; ssh_add_group="${SSH_GROUP_ADD}";
if [ -z "${SSH_GROUP_ADD}" ] && [ -f "${root_folder}${input_file}" ]; then if [ -z "${SSH_GROUP_ADD}" ] && [ -f "${root_folder}${input_file}" ]; then
ssh_add_group=$(grep "${username}" "${root_folder}${input_file}" | cut -d ";" -f 4 | tr A-Z a-z | tr -d ' '); ssh_add_group=$(grep "${username}" "${root_folder}${input_file}" | cut -d ";" -f 4 | tr '[:upper]' '[:lower:]' | tr -d ' ');
fi; fi;
if [ "${ssh_access_type}" != "allow" ] && [ "${ssh_access_type}" != "forward" ]; then if [ "${ssh_add_group}" != "allow" ] && [ "${ssh_add_group}" != "forward" ]; then
ssh_add_group="allow"; ssh_add_group="allow";
fi; fi;
ssh_add_group="ssh${ssh_add_group}"; ssh_add_group="ssh${ssh_add_group}";
@@ -98,8 +124,9 @@ for username in "$@"; do
# check if user is in reject group remove # check if user is in reject group remove
if id -nGz "${username}" | grep -qzxF "${ssh_reject_group}"; then if id -nGz "${username}" | grep -qzxF "${ssh_reject_group}"; then
# remove user from ssh group and add to reject groups # 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 if [ ${TEST} -eq 1 ]; then
# shellcheck disable=SC2059
printf "${user_group_tpl}" "${username}" "${ssh_reject_group}" "${username}" "${ssh_add_group}"; printf "${user_group_tpl}" "${username}" "${ssh_reject_group}" "${username}" "${ssh_add_group}";
else else
gpasswd -d "${username}" "${ssh_reject_group}"; gpasswd -d "${username}" "${ssh_reject_group}";
@@ -107,7 +134,7 @@ for username in "$@"; do
fi; fi;
else else
# skip not ssh user # 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; fi;
done; done;

View File

@@ -1 +1 @@
#user_id;user_name;group,subgroup;ssh access type;override password;override hostname;override ssh type #user_id;user_name;group,subgroup;ssh access type|no login flag;override password;override hostname;override ssh type