Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c801ef40b4 | ||
|
|
125cb27de8 | ||
|
|
e45b89c582 | ||
|
|
4a8dab7b01 | ||
|
|
fa47178ed1 | ||
|
|
4629b58a7e | ||
|
|
d8cd628ddd | ||
|
|
76f9056069 | ||
|
|
74e7e9823f | ||
|
|
7ce8330aa6 | ||
|
|
d8f9710593 | ||
|
|
c37d17fe9f | ||
|
|
307433e0a7 | ||
|
|
f9cd0806f1 | ||
|
|
d9b3fd97fb | ||
|
|
21177e1762 | ||
|
|
3aa6de7e23 | ||
|
|
3c160a62e7 | ||
|
|
ca4616c5ee | ||
|
|
251b0bf981 | ||
|
|
6daccfe57c | ||
|
|
91f096ab0c | ||
|
|
935d6a84c9 | ||
|
|
ee7cc8555e | ||
|
|
83f84abd46 | ||
|
|
090d6f9cec | ||
|
|
5659cc010f | ||
|
|
0bd40cdd73 | ||
|
|
e4ed6fed8d | ||
|
|
5bf30a8b2f | ||
|
|
26c007dba6 | ||
|
|
785e3c116d | ||
|
|
adbfeb0074 | ||
|
|
8c7ef32894 | ||
|
|
70ef7a3fc5 | ||
|
|
89252af50b | ||
|
|
8fb833d3c4 | ||
|
|
694f04313c | ||
|
|
50e28c7cfd | ||
|
|
65b7a6ad43 | ||
|
|
244461d466 | ||
|
|
66213dfd65 | ||
|
|
39da44b546 | ||
|
|
d4bb06e3e1 | ||
|
|
cc647de495 | ||
|
|
68b450baaf | ||
|
|
8452a1b8c0 | ||
|
|
3fcb74ac47 |
2
.shellcheckrc
Normal file
2
.shellcheckrc
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
shell=bash
|
||||||
|
external-sources=true
|
||||||
112
Readme.md
112
Readme.md
@@ -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> ...`
|
||||||
|
|||||||
@@ -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] ====>";
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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}";
|
||||||
@@ -72,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
|
||||||
@@ -103,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
|
||||||
@@ -120,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;
|
||||||
@@ -132,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;
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user