Compare commits

..

16 Commits

Author SHA1 Message Date
Clemens Schwaighofer
fa7e7fbe86 Script to move authorized_keys to central location
If there is a ssh setting that we have a central location for SSH keys
move all users ssh keys there.
Currently skipped are core admin users, they will move later once all
tests are done
2023-05-16 08:58:53 +09:00
Clemens Schwaighofer
fa3c4e0c6e Bug in user create test output
Missing ! for central ssh authorized_file check in pub key update flow
2023-04-05 13:27:05 +09:00
Clemens Schwaighofer
ebf0eaf412 Bug fixes in user create for new ssh key central location
* Bug with existing ssh key but not in ssh authorized_file
The correct public key location was not set for the existing file

* Bug with attr set on authorzied_file update if central location
If a central location the +i attrib must be removed first
It will set always in the folder rights change

* Change the authorized file group to root for central file location
2023-04-05 13:24:15 +09:00
Clemens Schwaighofer
190b12b288 add missing check central ssh auth file folder exists 2023-04-05 11:29:46 +09:00
Clemens Schwaighofer
3a42c521f6 Add central ssh authorized_keys file detect, fixes for home folder create
* new detect for central authorized keys folder
1) must have %u set in the AuthorizedKeysFile list
2) folder must exists (will not be created, if not exists abort)

If above is set, it will create a username file with the ssh key in there
and lock it down as r--/user and +i attrib

else uses old .ssh folder form

* fix for user add with different home base folder
add this as option for the useradd command
2023-04-05 11:24:37 +09:00
Clemens Schwaighofer
61a8bca3d7 Allow /home to have a different base location
If /home is eg located in /storge then we can now set a prefix for this.

Option -h or via config setting in "user_create.cfg" named
HOME_LOCATION="/path"

Note: Path has to be prefix with /. Any sub folders in home will be
ignored and the user is always created in /home/user.name
Group names as sub folders in /home are not supported
2023-03-29 10:57:48 +09:00
Clemens Schwaighofer
a0e7347033 Do not run zip command when test flag is set 2023-03-23 13:52:32 +09:00
Clemens Schwaighofer
c58b0ea7a4 Add wildcard to user list txt file to also ignore TEST created files 2023-02-17 16:57:10 +09:00
Clemens Schwaighofer
fb00036ab9 Abort on invalid option, always set ssh keytype so it doesn't stay on last selected 2023-01-31 13:29:00 +09:00
Clemens Schwaighofer
8808b94413 Add user create flow document 2022-12-02 10:05:40 +09:00
Clemens Schwaighofer
1fbc6c8125 Update password key length to 14 characters 2022-12-02 10:02:40 +09:00
Clemens Schwaighofer
87d53cdb13 Create user bug with positions in list file 2022-12-02 09:59:39 +09:00
Clemens Schwaighofer
716a0c2bfb Fix root/base folder problem 2022-12-02 09:41:25 +09:00
Clemens Schwaighofer
365b52efe5 Bug fix with user_list.txt variable in wrong script. Must be in unlock script not check script 2022-12-02 09:32:27 +09:00
Clemens Schwaighofer
b10cb62612 Fix unlock script with debug comment out code 2022-12-02 09:28:09 +09:00
Clemens Schwaighofer
1f4e295e9f Update lock script, add unlock script, minor updates in other scripts
Make sure that lock script reejcts core users
(root/ec2-user/admin/ubuntu)

Unlock script works reverse with also optional check in user_list.txt
for ssh allow/foward group type

Internal:
rename all $user to $username
2022-12-02 09:26:51 +09:00
9 changed files with 572 additions and 100 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,3 @@
user_list.txt
user_password*.txt
user_password*.txt*
*.zip

View File

@@ -199,6 +199,31 @@ The public key part can be extracted from the SSH PEM key with
*[PEM]* is the placeholder for the filename
## Lock and unlock uses
If a user should be stopped from logging in via ssh the user needs to be removed from the sshallow or sshforward groups. Note that the sshforward group only exists on jump hosts and can normally be ignored.
Default 100% ignored users are 'root', 'ec2-user', 'admin', 'ubuntu'
### Lock users
`bin/lock_users.sh -t <user 1> <user 2> ...`
The `-t` flag is for test run.
If the user is not in the sshallow or sshreject group the change will be skipped.
Locked users will be moved to the sshreject group
### Unlock users
If a user exists in the sshreject group the user can be unlocked
`bin/unlock_uses.sh -t -s <allow|forward> <user 1> <user 2> ...`
Like the lock user script it will only work on users in the sshreject group. But here the target allow / forward group must be selected.
If not set it defaults to allow, if a user_list.txt file with this user exist it will try to extract this data if the `-s` option is not set
## Last login check scripts
There are two scripts that can be user to check if and when the user has logged in the last time.

View File

@@ -0,0 +1,114 @@
#!/usr/bin/env bash
# check if we need to move the users authorized keys to the central location
TEST=0;
SKIP_USERS=();
while getopts ":tis:" opt; do
case "${opt}" in
t|test)
TEST=1;
;;
s|skip)
SKIP_USERS+=("${OPTARG}");
;;
\?)
echo -e "\n Option does not exist: ${OPTARG}\n";
echo "Use -t for test and -s <user> for users to skip";
exit 1;
;;
esac;
done;
# check if authorized keys is actually enabled
# detect ssh authorized_keys setting
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER='';
SSH_AUTHORIZED_FILE='';
for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do
if [ ! -z $(echo "${cf}" | grep "%u") ]; then
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=$(echo "${cf}" | sed -e 's/%u//');
if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}";
exit;
fi;
fi;
done;
if [ -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo "No central authorized_keys file detected, no change check needed";
exit;
fi;
echo "SSH Authorized Files folder: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}";
PRINTF_INFO="%-8s [%3s]: %-25s: %s\n";
# list of user accounts we will never touch
NO_ACTION=(root admin ec2-user ubuntu);
# loop over passwd file
# if not in no action then check if .ssh/authorized_keys file exists
cat /etc/passwd | cut -d ":" -f 1,6 |
while read user_home; do
username=$(echo "${user_home}" | cut -d ":" -f 1);
# skip admin usernames
if [[ " ${NO_ACTION[*]} " =~ " ${username} " ]]; then
printf "${PRINTF_INFO}" "NO ACT" "!" "${username}" "user in NO ACTION list";
continue;
fi;
if [[ " ${SKIP_USERS[*]} " =~ " ${username} " ]]; then
printf "${PRINTF_INFO}" "SKIP" "*" "${username}" "skip forced via command line";
continue;
fi;
home_folder=$(echo "${user_home}" | cut -d ":" -f 2);
# skip no .ssh/authorized_ekys
if [ ! -f "${home_folder}/.ssh/authorized_keys" ]; then
# but do we have an auth folder, if yes -> exist skip
if [ -f "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}" ]; then
printf "${PRINTF_INFO}" "DONE" "." "${username}" "already moved";
else
printf "${PRINTF_INFO}" "IGNORE" "?" "${username}" "no authorized_keys file";
fi;
continue;
fi;
# check if this user public key(s) exist in AuthorizedKeysFile target
if [ -f "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}" ]; then
ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}");
if [ -z "${ssh_key_diff}" ]; then
printf "${PRINTF_INFO}" "REMOVE" "-" "${username}" ".ssh/authorized_keys";
if [ ${TEST} -eq 0 ]; then
rm "${home_folder}/.ssh/authorized_keys";
else
echo "$> rm \"${home_folder}/.ssh/authorized_keys\"";
fi;
continue;
fi;
# No update, alert
printf "${PRINTF_INFO}" "DIFF" "???" "${username}" "Different authorized keys in home dir, SKIPPED";
continue;
fi;
printf "${PRINTF_INFO}" "MOVE" ">" "${username}" "Move SSH Key to central location";
# move public keys over
if [ ${TEST} -eq 0 ]; then
cat "${home_folder}/.ssh/authorized_keys" > "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}";
# secure new folder: chown/chmod/chattr
chown ${username} "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}";
chmod 400 "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}";
chattr +i "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}";
# confirm
ssh_key_diff=$(diff -u "${home_folder}/.ssh/authorized_keys" "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}");
if [ ! -z "${ssh_key_diff}" ]; then
printf "${PRINTF_INFO}" "ERROR" "!!!" "${username}" "Move problem ${ssh_key_diff}";
break;
fi;
# remove home .ssh/authorized_keys (do not remove folder)
rm "${home_folder}/.ssh/authorized_keys";
else
echo "[START] ====>";
echo "$> cat \"${home_folder}/.ssh/authorized_keys\" > \"${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}\"";
echo "$> chown ${username} \"${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}\"";
echo "$> chmod 400 \"${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}\"";
echo "$> chattr +i \"${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}/${username}\"";
echo "$> rm \"${home_folder}/.ssh/authorized_keys\"";
echo "[END ] ====>";
fi;
done;
# __END__

View File

@@ -41,21 +41,26 @@ echo "Max age no login : ${max_age_create} days";
for ssh_group in ${ssh_groups[@]}; do
echo "--------------------->"
echo "Checking Group : ${ssh_group}";
for user in $(cat /etc/group|grep "${ssh_group}:" | cut -d ":" -f 4 | sed -e 's/,/ /g'); do
for username in $(cat /etc/group|grep "${ssh_group}:" | cut -d ":" -f 4 | sed -e 's/,/ /g'); do
# check that user exists in passwd
if ! id "${username}" &>/dev/null; then
echo "[!] User $username does not exists in /etc/passwd file";
continue;
fi;
account_age=0;
delete_user=0;
out_string="";
#echo "* Checking user ${user}";
#echo "* Checking user ${username}";
# check user create time, if we have set it in comment
user_create_date=$(cat /etc/passwd | grep "${user}:" | cut -d ":" -f 5);
user_create_date=$(cat /etc/passwd | grep "${username}:" | cut -d ":" -f 5);
# if empty try last password set time
if [ -z "${user_create_date}" ]; then
# user L 11/09/2020 0 99999 7 -1
user_create_date=$(passwd -S ${user} | cut -d " " -f 3);
user_create_date=$(passwd -S ${username} | cut -d " " -f 3);
fi;
# last try is user home .bash_logout
if [ -z "${user_create_date}" ]; then
home_dir=$(cat /etc/passwd | grep "${user}:" | cut -d ":" -f 6)"/.bash_logout";
home_dir=$(cat /etc/passwd | grep "${username}:" | cut -d ":" -f 6)"/.bash_logout";
user_create_date=$(stat -c %Z "${home_dir}");
fi;
@@ -63,15 +68,15 @@ echo "Checking Group : ${ssh_group}";
# users. Use the collect script from systemd-logind or /var/log/secure
# Username Port From Latest
# user pts/35 10.110.160.230 Wed Nov 2 09:40:35 +0900 2022
last_login_string=$(lastlog -u ${user} | sed 1d);
last_login_string=$(lastlog -u ${username} | sed 1d);
search="Never logged in";
found="";
# problem with running rep check in if
if [ -f "${AUTH_LOG}" ]; then
found=$(grep "${user};" "${AUTH_LOG}");
found=$(grep "${username};" "${AUTH_LOG}");
fi;
if [ ! -z "${found}" ]; then
last_login_date=$(grep "${user};" "${AUTH_LOG}" | cut -d ";" -f 2 | date +"%s" -f -);
last_login_date=$(grep "${username};" "${AUTH_LOG}" | cut -d ";" -f 2 | 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";
@@ -109,15 +114,15 @@ echo "Checking Group : ${ssh_group}";
fi;
# build delete output
if [ ${delete_user} = 1 ]; then
delete_accounts="${delete_accounts}"$(printf "${user_group_tpl}" "${user}" "${ssh_group}" "${user}" "${ssh_reject_group}")$'\n';
delete_accounts="${delete_accounts}"$(printf "${user_group_tpl}" "${username}" "${ssh_group}" "${username}" "${ssh_reject_group}")$'\n';
fi;
printf "* Checking user %-20s: %s\n" "${user}" "${out_string}";
printf "* Checking user %-20s: %s\n" "${username}" "${out_string}";
done;
done;
echo "--------------------->"
echo "Showing current SSH Reject users:"
for user in $(cat /etc/group|grep "${ssh_reject_group}:" | cut -d ":" -f 4 | sed -e 's/,/ /g'); do
echo "${user}";
echo "${username}";
done;
if [ ! -z "${delete_accounts}" ]; then
echo "--------------------->"

View File

@@ -27,7 +27,7 @@
# SET TO 1 to TEST [will not create user/group/folder]
TEST=0; # no creation except ssh keys
INFO=0; # no creation of anything, just print info strings
while getopts ":ti" opt; do
while getopts ":tih:" opt; do
case "${opt}" in
t|test)
TEST=1;
@@ -35,6 +35,15 @@ while getopts ":ti" opt; do
i|info)
INFO=1;
;;
h|home)
HOME_LOCATION="${OPTARG}";
;;
\?)
echo -e "\n Option does not exist: ${OPTARG}\n";
echo "Use -t for test and -i for info";
echo "Override default /home/ folder location with -h <base>";
exit 1;
;;
esac;
done;
# hostname for output file only
@@ -43,24 +52,68 @@ timestamp=$(date +%Y%m%d-%H%M%S)
# character to set getween info blocks
separator="#";
# base folder for all data
root_folder=$(pwd)'/';
BASE_FOLDER=$(dirname $(readlink -f $0))"/";
# home folder is always thome
HOME_BASE="/home/";
# config location
CONFIG_BASE="${BASE_FOLDER}../config/";
# check config folder for .env file with HOME_LOCATION
# only use if HOME_LOCATION not yet set
if [ -z "${HOME_LOCATION}" ] && [ -f "${CONFIG_BASE}create_user.cfg" ]; then
source <(grep = ${CONFIG_BASE}create_user.cfg | sed 's/ *= */=/g')
fi;
if [ ! -z "${HOME_LOCATION}" ]; then
# must start with / as it has to be from root
if [ "${HOME_LOCATION##/*}" ]; then
echo "Home location folder must start with a slash (/): ${HOME_LOCATION}";
exit;
fi;
# must be valid folder
if [ ! -d "${HOME_LOCATION}" ]; then
echo "Folder for home location does not exists: ${HOME_LOCATION}";
exit;
fi;
fi;
# the new location for home, if override is set will be created in this folder
HOME_FOLDER="${HOME_LOCATION}${HOME_BASE}"
if [ ! -d "${HOME_FOLDER}" ]; then
echo "Home folder location not found: ${HOME_FOLDER}";
exit;
fi;
ROOT_FOLDER="${BASE_FOLDER}../";
input_file='user_list.txt';
output_file="user_password.${timestamp}.txt";
output_zip_folder='zip/';
output_zip="users.${timestamp}.zip"
ssh_keygen_folder='ssh-keygen/';
ssh_keygen_folder_created_pub='ssh-keygen-created-pub/';
ssh_keytype='ed25519';
SSH_KEYGEN_FOLDER='ssh-keygen/';
SSH_KEYGEN_FOLDER_CREATED_PUB='ssh-keygen-created-pub/';
# set default key tpye
default_ssh_keytype='ed25519';
ssh_keytype='';
# sshallow or sshforward
ssh_group='';
ssh_forward_ok=0;
# detect ssh authorized_keys setting
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER='';
SSH_AUTHORIZED_FILE='';
for cf in $(grep "^AuthorizedKeysFile" /etc/ssh/sshd_config | grep "%u"); do
if [ ! -z $(echo "${cf}" | grep "%u") ]; then
SSH_CENTRAL_AUTHORIZED_FILE_FOLDER=$(echo "${cf}" | sed -e 's/%u//');
if [ ! -d "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo "ssh central authorized_file folder could not be found: ${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}";
exit;
fi;
fi;
done;
# check if ssh key folder exists
if [ ! -d "${root_folder}${ssh_keygen_folder}" ]; then
mkdir "${root_folder}${ssh_keygen_folder}";
if [ ! -d "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}" ]; then
mkdir "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}";
fi;
# check if zip folder is missing
if [ ! -d "${root_folder}${output_zip_folder}" ]; then
mkdir "${root_folder}${output_zip_folder}";
if [ ! -d "${ROOT_FOLDER}${output_zip_folder}" ]; then
mkdir "${ROOT_FOLDER}${output_zip_folder}";
fi;
# check if password generate software is installed
# if [ ! command -v pwgen &> /dev/null ]; then
@@ -84,8 +137,8 @@ if [ ! -z $(cat /etc/group | grep "sshforward:") ]; then
ssh_forward_ok=1;
fi;
# check if user list file exists
if [ ! -f "${root_folder}${input_file}" ]; then
echo "Missing ${root_folder}${input_file}";
if [ ! -f "${ROOT_FOLDER}${input_file}" ]; then
echo "Missing ${ROOT_FOLDER}${input_file}";
exit;
fi;
# make sure my own folder is owned by root and 600 (except for testing)
@@ -101,17 +154,19 @@ if [ $(whoami) != "root" ]; then
fi;
fi;
# create users
cat "${root_folder}${input_file}" |
cat "${ROOT_FOLDER}${input_file}" |
while read i; do
# skip rows start with # (comment)
if [[ "${i}" =~ ^\# ]]; then
continue;
fi;
# make lower case, remove spaces
user=$(echo "${i}" | cut -d ";" -f 2 | tr A-Z a-z | tr -d ' ');
# POS 2: make lower case, remove spaces
username=$(echo "${i}" | cut -d ";" -f 2 | tr A-Z a-z | tr -d ' ');
# POS 3: groups
_group=$(echo "${i}" | cut -d ";" -f 3 | tr A-Z a-z | tr -d ' ');
group=$(echo "${_group}" | cut -d "," -f 1);
sub_group="";
# POS 4: ssh access type
ssh_access_type=$(echo "${i}" | cut -d ";" -f 4 | tr A-Z a-z | tr -d ' ');
# if not allow or forward, set to access
if [ "${ssh_access_type}" != "allow" ] && [ "${ssh_access_type}" != "forward" ]; then
@@ -119,7 +174,7 @@ while read i; do
ssh_access_type="allow";
fi;
if [ $ssh_forward_ok -eq 0 ] && [ "${ssh_access_type}" = "forward" ]; then
echo "[!!!] sshforward group does not exsts, cannot set user ${user}";
echo "[!!!] sshforward group does not exsts, cannot set user ${username}";
break;
fi;
ssh_group="ssh${ssh_access_type}";
@@ -130,39 +185,42 @@ while read i; do
sub_group=$(echo "${_group}" | cut -d "," -f 2-);
sub_group_opt=" -G ${sub_group}";
fi;
# override host name, lowercase and spaces removed
_hostname=$(echo "${i}" | cut -d ";" -f 5 | tr A-Z a-z | tr -d ' ');
# POS 5: do we have a password preset
_password=$(echo "${i}" | cut -d ";" -f 5);
# POS 6: override host name, lowercase and spaces removed
_hostname=$(echo "${i}" | cut -d ";" -f 6 | tr A-Z a-z | tr -d ' ');
if [ -z "${_hostname}" ]; then
hostname=${host};
else
hostname=${_hostname};
fi;
# do we have a password preset
_password=$(echo "${i}" | cut -d ";" -f 4);
_ssh_keytype=$(echo "${i}" | cut -d ";" -f 6 | tr A-Z a-z | tr -d ' ');
# POS 7: ssh keytype override
_ssh_keytype=$(echo "${i}" | cut -d ";" -f 7 | tr A-Z a-z | tr -d ' ');
if [ "${_ssh_keytype}" = "rsa" ]; then
ssh_keytype="${_ssh_keytype}";
#echo "[!!] BACKWARDS COMPATIBLE RSA TYPE SELECTION [!!]";
else
ssh_keytype=${default_ssh_keytype};
fi;
# user & group not set
if [ -z "${user}" ] || [ -z "${_group}" ]; then
echo "[!!!!!] Missing user or group entry for ${user}/${_group}";
if [ -z "${username}" ] || [ -z "${_group}" ]; then
echo "[!!!!!] Missing user or group entry for ${username}/${_group}";
echo "[*** ABORT RUN ***]"
break;
fi;
# SSH file name part without folder
ssh_keygen_id="${hostname}${separator}${group}${separator}${user}${separator}${ssh_keytype}.pem";
ssh_keygen_id="${hostname}${separator}${group}${separator}${username}${separator}${ssh_keytype}.pem";
# the full file including folder name
ssh_keyfile="${root_folder}${ssh_keygen_folder}${ssh_keygen_id}";
ssh_keyfile="${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}${ssh_keygen_id}";
# publ file if new
ssh_keyfile_pub="${ssh_keyfile}.pub";
# 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";
if [ ${INFO} -eq 1 ]; then
# test if pub file exists or not, test if user exists
echo -n "User: '${user}:${group}(${sub_group});${ssh_group}', SSH: ${ssh_keygen_id}";
if getent passwd ${user} > /dev/null 2>&1; then
echo -n "User: '${username}:${group}(${sub_group});${ssh_group}', SSH: ${ssh_keygen_id}";
if getent passwd ${username} > /dev/null 2>&1; then
echo -n ", User exists";
fi;
if [ -f "${ssh_keyfile_check_pub}" ]; then
@@ -182,24 +240,31 @@ while read i; do
fi;
done;
# check if user is not already created
if getent passwd ${user} > /dev/null 2>&1; then
echo "-- Skip '${user}:${group}(${sub_group})'";
# if getent passwd ${username} > /dev/null 2>&1; then
if id "${username}" &>/dev/null; then
echo "-- Skip '${username}:${group}(${sub_group})'";
else
echo "++ Create '${user}:${group}(${sub_group})'";
echo "++ Create '${username}:${group}(${sub_group})'";
if [ ${TEST} -eq 0 ]; then
# comment is user create time
useradd -c `date +"%F"` -s /bin/bash -g ${group}${sub_group_opt} -m ${user};
useradd -c `date +"%F"` -s /bin/bash -g ${group}${sub_group_opt} -d "${HOME_FOLDER}" -m ${username};
else
echo "$> useradd -s /bin/bash -g ${group}${sub_group_opt} -m ${user}";
echo "$> useradd -c `date +"%F"` -s /bin/bash -g ${group}${sub_group_opt} -d "${HOME_FOLDER}" -m ${username}";
fi;
fi;
# set the auth file
if [ -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
SSH_AUTHORIZED_FILE="${HOME_FOLDER}${username}/.ssh/authorized_keys";
else
SSH_AUTHORIZED_FILE="${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}${username}";
fi;
skip_ssh=0;
# if public pem already exists skip creation
if [ ! -f "${ssh_keyfile_check_pub}" ]; then
# Note we only create a password if we need it
# password + store pwgen 10 1 -1
if [ -z "${_password}" ]; then
password=$(printf "%s" $(pwgen 10 1));
password=$(printf "%s" $(pwgen 14 1));
else
echo "! Override password set";
password=${_password};
@@ -210,19 +275,19 @@ while read i; do
ssh-keygen \
-t ${ssh_keytype} \
-f "${ssh_keyfile}" \
-C "${hostname}: ${user}@${group}" \
-C "${hostname}: ${username}@${group}" \
-a 100 -N "${password}"
else
echo "$> ssh-keygen -t ${ssh_keytype} -f ${ssh_keyfile} -C ${hostname}: ${user}@${group} -a 100 -N ${password}";
echo "$> ssh-keygen -t ${ssh_keytype} -f ${ssh_keyfile} -C ${hostname}: ${username}@${group} -a 100 -N ${password}";
fi;
else
found=$(grep "$(cat ${ssh_keyfile_check_pub})" /home/${user}/.ssh/authorized_keys);
found=$(grep "$(cat ${ssh_keyfile_check_pub})" ${SSH_AUTHORIZED_FILE});
if [ ! -z "${found}" ]; then
skip_ssh=1;
# override previously set with stored one
ssh_keyfile_pub=${ssh_keyfile_check_pub};
echo "-- Skip SSH Key creation: ${ssh_keygen_id}.pub";
else
# override previously set with stored one
ssh_keyfile_pub=${ssh_keyfile_check_pub};
echo " < Use existing public ssh key '${ssh_keygen_id}.pub'";
# Password already set notification
fi;
@@ -231,33 +296,58 @@ while read i; do
if [ ${skip_ssh} -eq 0 ]; then
# write login info to output file
if [ ${TEST} -eq 0 ]; then
create_output_file="${root_folder}${output_file}";
create_output_file="${ROOT_FOLDER}${output_file}";
else
create_output_file="${root_folder}${output_file}.TEST";
create_output_file="${ROOT_FOLDER}${output_file}.TEST";
fi;
echo $(date +"%F %T")";"${host}";"${_hostname}";"${user}";"${password}";"${ssh_allow_type} >> ${create_output_file};
echo $(date +"%F %T")";"${host}";"${_hostname}";"${username}";"${password}";"${ssh_allow_type} >> ${create_output_file};
# create folder only if we do not have central
# create the SSH foler and authorized access file with correct permissions
echo " > Create .ssh folder";
if [ ${TEST} -eq 0 ]; then
mkdir /home/${user}/.ssh/;
else
echo "$> mkdir /home/${user}/.ssh/";
if [ ! -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo " > Create .ssh folder";
if [ ${TEST} -eq 0 ]; then
mkdir ${HOME_FOLDER}${username}/.ssh/;
else
echo "$> mkdir ${HOME_FOLDER}${username}/.ssh/";
fi;
fi;
echo " > Add public into authorized_keys";
# add
echo " > Add public into authorized_keys file";
if [ ${TEST} -eq 0 ]; then
cat "${ssh_keyfile_pub}" > /home/${user}/.ssh/authorized_keys;
if [ ! -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
chattr -i ${SSH_AUTHORIZED_FILE};
fi;
cat "${ssh_keyfile_pub}" > ${SSH_AUTHORIZED_FILE};
else
echo "$> cat ${ssh_keyfile_pub} > /home/${user}/.ssh/authorized_keys";
if [ ! -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo "$> chattr -i ${SSH_AUTHORIZED_FILE}";
fi;
echo "$> cat ${ssh_keyfile_pub} > ${SSH_AUTHORIZED_FILE}";
fi;
echo " > Secure folder .ssh and authorized_keys file";
if [ ${TEST} -eq 0 ]; then
chown -R ${user}:${group} /home/${user}/.ssh/;
chmod 700 /home/${user}/.ssh/;
chmod 600 /home/${user}/.ssh/authorized_keys;
# secure
if [ -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ]; then
echo " > Secure home directory folder .ssh and authorized_keys file";
if [ ${TEST} -eq 0 ]; then
chown -R ${username}:${group} ${HOME_FOLDER}${username}/.ssh/;
chmod 700 ${HOME_FOLDER}${username}/.ssh/;
chmod 600 ${SSH_AUTHORIZED_FILE};
else
echo "$> chown -R ${username}:${group} ${HOME_FOLDER}${username}/.ssh/";
echo "$> chmod 700 ${HOME_FOLDER}${username}/.ssh/";
echo "$> chmod 600 ${SSH_AUTHORIZED_FILE}";
fi;
else
echo "$> chown -R ${user}:${group} /home/${user}/.ssh/";
echo "$> chmod 700 /home/${user}/.ssh/";
echo "$> chmod 600 /home/${user}/.ssh/authorized_keys";
echo " > Secure central authorized_keys file";
if [ ${TEST} -eq 0 ]; then
chown ${username}:root ${SSH_AUTHORIZED_FILE};
chmod 400 ${SSH_AUTHORIZED_FILE};
# set +i so user can't change file
chattr +i ${SSH_AUTHORIZED_FILE};
else
echo "$> chown ${username}:root ${SSH_AUTHORIZED_FILE}";
echo "$> chmod 400 ${SSH_AUTHORIZED_FILE}";
echo "$> chattr +i ${SSH_AUTHORIZED_FILE}";
fi;
fi;
fi;
done;
@@ -267,24 +357,33 @@ if [ ${INFO} -eq 1 ]; then
exit;
fi;
# zip everything and remove data in ssh key folder, delete output file with passwords
zip -r \
"${root_folder}${output_zip_folder}${output_zip}" \
"${input_file}" \
"${output_file}" \
"${ssh_keygen_folder}" \
-x\*.gitignore;
echo "Download: ${root_folder}${output_zip_folder}${output_zip}";
if [ ${TEST} -eq 0 ]; then
zip -r \
"${ROOT_FOLDER}${output_zip_folder}${output_zip}" \
"${input_file}" \
"${output_file}" \
"${SSH_KEYGEN_FOLDER}" \
-x\*.gitignore;
else
echo "zip -r \\"
echo "${ROOT_FOLDER}${output_zip_folder}${output_zip} \\"
echo "${input_file} \\"
echo "${output_file} \\"
echo "${SSH_KEYGEN_FOLDER} \\"
echo "-x\*.gitignore;"
fi;
echo "Download: ${ROOT_FOLDER}${output_zip_folder}${output_zip}";
# cleam up user log file and ssh keys
if [ ${TEST} -eq 0 ]; then
# move pub to created folders
mv "${root_folder}${ssh_keygen_folder}"*.pub "${root_folder}${ssh_keygen_folder_created_pub}";
mv "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}"*.pub "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER_CREATED_PUB}";
# delete the rest
rm "${root_folder}${output_file}";
rm "${root_folder}${ssh_keygen_folder}"*;
rm "${ROOT_FOLDER}${output_file}";
rm "${ROOT_FOLDER}${SSH_KEYGEN_FOLDER}"*;
else
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}${ssh_keygen_folder}*";
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}${SSH_KEYGEN_FOLDER}*";
fi;
# __END__

View File

@@ -2,26 +2,36 @@
# disable a user by removing them from the sshallow/sshforward group
# and move them to the sshreject group
# Note that call is ./lock_user.sh -t <user 1> <user 2> ...
# if the -t is not in the first position it will be ignored
# SET TO 1 to TEST [will not move user in groups]
TEST=0; # no creation except ssh keys
INFO=0; # no creation of anything, just print info strings
while getopts ":ti" opt; do
TEST=0; # no delete, just print
while getopts ":t" opt; do
case "${opt}" in
t|test)
TEST=1;
;;
i|info)
INFO=1;
;;
esac;
done;
shift "$((OPTIND-1))"
if [ $(whoami) != "root" ]; then
if [ ${TEST} -eq 0 ]; then
echo "Script must be run as root user";
exit;
else
echo "!!!! Script must be run as root user !!!!";
fi;
fi;
if [ $# -eq 0 ]; then
echo "Must give at least one user name";
exit;
fi;
# ignore users (root and admin users)
ignore_users=('root' 'ec2-user' 'ubuntu' 'admin');
# ssh reject group
ssh_reject_group="sshreject";
if [ -z $(cat /etc/group | grep "${ssh_reject_group}:") ]; then
@@ -30,20 +40,29 @@ if [ -z $(cat /etc/group | grep "${ssh_reject_group}:") ]; then
fi;
ssh_allow_group="sshallow";
ssh_forward_group="sshfoward";
delete_accounts="";
user_group_tpl="gpasswd -d %s %s;gpasswd -a %s %s;";
user_group_tpl="gpasswd -d %s %s\ngpasswd -a %s %s\n";
echo "--------------------->"
# $1 ... $n
for username in "$@"; do
# skip if there is an option hidden
if [[ ${_arg:0:1} = "-" ]]; then
continue;
fi;
# skip ignore users, note that if a user is not in the sshallow list anyway
# we skip them too, this is just in case check
if [[ " ${ignore_users[*]} " =~ " ${username} " ]]; then
echo "[!] User $username is in the ignore user list";
continue;
fi;
# check that user exists in passwd
if [ -z $(cat /etc/passwd | grep "${username}:") ]; then
if ! id "${username}" &>/dev/null; then
echo "[!] User $username does not exists in /etc/passwd file";
continue;
fi;
# if not check if in reject list
if id -nGz "${username}" | grep -qzxF "${ssh_reject}"; then
echo "[.] User $username already in the ${ssh_reject} list";
if id -nGz "${username}" | grep -qzxF "${ssh_reject_group}"; then
echo "[.] User $username already in the ${ssh_reject_group} list";
continue;
fi;
# check if user is in sshallow/forward list
@@ -62,17 +81,16 @@ for username in "$@"; do
if [ ! -z "${ssh_remove_group}" ]; then
# remove user from ssh group and add to reject groups
echo "[*] User $username will be removed from ${ssh_remove_group}";
delete_accounts="${delete_accounts}"$(printf "${user_group_tpl}" "${username}" "${ssh_remove_group}" "${username}" "${ssh_reject_group}")$'\n';
if [ ${TEST} -eq 1 ]; then
printf "${user_group_tpl}" "${username}" "${ssh_remove_group}" "${username}" "${ssh_reject_group}";
else
gpasswd -d "${username}" "${ssh_remove_group}";
gpasswd -a "${username}" "${ssh_reject_group}";
fi;
else
# skip not ssh user
echo "[?] User $username not in any ssh allow/foward groups";
fi;
done;
if [ ! -z "${delete_accounts}" ]; then
echo "--------------------->"
echo "% Run list below to move users to reject ssh group";
echo "";
echo "${delete_accounts}";
fi;
# __END__

114
bin/unlock_user.sh Executable file
View File

@@ -0,0 +1,114 @@
#!/usr/bin/env bash
# disable a user by removing them from the sshallow/sshforward group
# and move them to the sshreject group
# Note that call is ./lock_user.sh -t <user 1> <user 2> ...
# if the -t is not in the first position it will be ignored
# SET TO 1 to TEST [will not move user in groups]
TEST=0; # no delete, just print
SSH_GROUP_ADD='';
while getopts ":ts:" opt; do
case "${opt}" in
t|test)
TEST=1;
;;
s|sshgroup)
if [ -z "${SSH_GROUP_ADD}" ]; then
SSH_GROUP_ADD=${OPTARG};
fi;
;;
esac;
done;
shift "$((OPTIND-1))"
if [ $(whoami) != "root" ]; then
if [ ${TEST} -eq 0 ]; then
echo "Script must be run as root user";
exit;
else
echo "!!!! Script must be run as root user !!!!";
fi;
fi;
if [ $# -eq 0 ]; then
echo "Must give at least one user name";
exit;
fi;
if [ ! -z "${SSH_GROUP_ADD}" ] && [ "${SSH_GROUP_ADD}" != "allow" ] && [ "${SSH_GROUP_ADD}" != "forward" ]; then
echo "sshgroup option can only be 'allow' or 'forward'";
exit;
fi;
BASE_FOLDER=$(dirname $(readlink -f $0))"/";
root_folder="${BASE_FOLDER}../";
input_file='user_list.txt';
# ignore users (root and admin users)
ignore_users=('root' 'ec2-user' 'ubuntu' 'admin');
# ssh reject group
ssh_reject_group="sshreject";
if [ -z $(cat /etc/group | grep "${ssh_reject_group}:") ]; then
echo "Missing ssh reject group: ${ssh_reject_group}";
exit;
fi;
ssh_allow_group="sshallow";
ssh_forward_group="sshfoward";
user_group_tpl="gpasswd -d %s %s\ngpasswd -a %s %s\n";
echo "--------------------->"
# $1 ... $n
for username in "$@"; do
# skip if there is an option hidden
if [[ ${_arg:0:1} = "-" ]]; then
continue;
fi;
# skip ignore users, note that if a user is not in the sshallow list anyway
# we skip them too, this is just in case check
if [[ " ${ignore_users[*]} " =~ " ${username} " ]]; then
echo "[!] User $username is in the ignore user list";
continue;
fi;
# check that user exists in passwd
if ! id "${username}" &>/dev/null; then
echo "[!] User $username does not exists in /etc/passwd file";
continue;
fi;
# check if already in OK groups
if id -nGz "${username}" | grep -qzxF "${ssh_allow_group}"; then
echo "[.] User $username already in the ${ssh_allow_group} list";
continue;
fi;
if id -nGz "${username}" | grep -qzxF "${ssh_forward_group}"; then
echo "[.] User $username already in the ${ssh_forward_group} list";
continue;
fi;
# try to find user in user_list.txt and get the allow/forward flag from there,
# else try to set from option
# if not valid use allow
ssh_add_group="${SSH_GROUP_ADD}";
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 ' ');
fi;
if [ "${ssh_access_type}" != "allow" ] && [ "${ssh_access_type}" != "forward" ]; then
ssh_add_group="allow";
fi;
ssh_add_group="ssh${ssh_add_group}";
# check if user is in reject group remove
if id -nGz "${username}" | grep -qzxF "${ssh_reject_group}"; then
# remove user from ssh group and add to reject groups
echo "[*] User $username will be added to ${ssh_add_group}";
if [ ${TEST} -eq 1 ]; then
printf "${user_group_tpl}" "${username}" "${ssh_reject_group}" "${username}" "${ssh_add_group}";
else
gpasswd -d "${username}" "${ssh_reject_group}";
gpasswd -a "${username}" "${ssh_add_group}";
fi;
else
# skip not ssh user
echo "[?] User $username not in the ssh reject group";
fi;
done;
# __END__

2
config/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

95
user_create_flow.md Normal file
View File

@@ -0,0 +1,95 @@
# AWS user create flow
* Step 1: check if main group exists
* Step 2: Add user to user_list.txt
Example:
```txt
# 2022-12-12
1;test.foo;group-a;allow
```
* Step 3: run create script in root/users `bin/create_user.sh`
Not, if unsure use `-t` for testing or `-i` for info only.
Example output for `-i`:
```sh
$> bin/create_user.sh -i
User: 'test.foo:group-a();sshallow', SSH: hostname.com#grou-a#test.foo#ed25519.pem
```
Run output (example):
```sh
++ Create 'test.foo:group-a()'
! Override password set
> Create ssh key-pair '/root/users/bin/../ssh-keygen/hostname.com#group-a#test.foo#ed25519.pem'
Generating public/private ed25519 key pair.
Your identification has been saved in /root/users/bin/../ssh-keygen/hostname.com#group-a#test.foo#ed25519.pem
Your public key has been saved in /root/users/bin/../ssh-keygen/hostname.com#group-a#test.foo#ed25519.pem.pub
The key fingerprint is:
SHA256:IXiHXZrBGuMIHgU34L4DgAwLeFeX37AhQD69TOF1XZI hostname.com: test.foo@group-a
The key's randomart image is:
+--[ED25519 256]--+
|+ o++o+o+.o ...o.|
|*o+..+o*+Bo. E. |
|++.+.o*+Xo = |
|... ..o* oo . |
|. . S |
| . . |
| o |
| . |
| |
+----[SHA256]-----+
> Create .ssh folder
> Add public into authorized_keys
> Secure folder .ssh and authorized_keys file
adding: user_list.txt (stored 0%)
adding: user_password.20221202-094351.txt (stored 0%)
adding: ssh-keygen/ (stored 0%)
adding: ssh-keygen/hostname.com#group-a#test.foo#ed25519.pem (deflated 24%)
adding: ssh-keygen/hostname.com#group-a#test.foo#ed25519.pem.pub (deflated 2%)
Download: /root/users/bin/../zip/users.20221202-094351.zip
```
* Step 4: Move the zip file to a folder where you can download it
```sh
$> mv /root/users/bin/../zip/users.20221202-094351.zip /home/<admin user>/
```
* Step 5: Download ZIP file to local computer and extract
Overwrite user_list.txt file if it exists
In the zup file there are the following files:
* user_password.YYYYMMDD-HHmmss.txt (creation timestamp)
* ssh-keygen/hostname#group#user#keytype.pem
* ssh-keygen/hostname#group#user#keytype.pem.pub
The .pem key has to be given to the user, the pub key is for reference only
* Step 6: test login
In the folder where the data was extracted
```sh
ssh -i ssh-keygen/hostname#group#user#keytype.pem user@hostname
```
Hand over to the user:
* username
* hostname
* PEM key file
* PEM key password
If the password needs to be removed:
```sh
ssh-keygen -p -f ssh-keygen/hostname#group#user#keytype.pem -P <old password> -N ""
```