* 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
378 lines
12 KiB
Bash
Executable File
378 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# * input file
|
|
# user_list.txt
|
|
# <ignored id>;<user name>;<group>[,sub group,sub group];<ssh access type>;[override password];[override hostname];[override ssh key type]
|
|
# lines with # are skipped
|
|
# already created users are skipped
|
|
# Mandatory: <ignored id>;<user name>;<group>;<ssh access type>
|
|
# <ssh access type> can be
|
|
# allow (full login access)
|
|
# forward (forward/jump host only)
|
|
# * output file
|
|
# <date>;<target connect host name>;<hostname>;<username>;<password>;<ssh access type>
|
|
# If already existing PEM key is used then <password> is [ALREADY SET]
|
|
#
|
|
# * PEM KEY
|
|
# <hostname>#<group>#<user>#<ssh key type>.pem
|
|
# * PUBLIC KEY
|
|
# <hostname>#<group>#<user>#<ssh key type>.pem.pub
|
|
# stored as zip in
|
|
# zip/
|
|
#
|
|
# If a previously exsting PEM key should be used, put the public pem file
|
|
# into the ssh-keygen/ folder
|
|
# They pem pub key must follow the set rules above
|
|
|
|
# SET TO 1 to TEST [will not create user/group/folder]
|
|
TEST=0; # no creation except ssh keys
|
|
INFO=0; # no creation of anything, just print info strings
|
|
while getopts ":tih:" opt; do
|
|
case "${opt}" in
|
|
t|test)
|
|
TEST=1;
|
|
;;
|
|
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
|
|
host=$(hostname);
|
|
timestamp=$(date +%Y%m%d-%H%M%S)
|
|
# character to set getween info blocks
|
|
separator="#";
|
|
# base folder for all data
|
|
BASE_FOLDER=$(dirname $(readlink -f $0))"/";
|
|
# 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/';
|
|
# 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//');
|
|
fi;
|
|
done;
|
|
|
|
# check if ssh key folder exists
|
|
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}";
|
|
fi;
|
|
# check if password generate software is installed
|
|
# if [ ! command -v pwgen &> /dev/null ]; then
|
|
if [ -z $(command -v pwgen) ]; then
|
|
echo "Missing pwgen application, aborting";
|
|
exit;
|
|
fi;
|
|
# check for zip
|
|
# if [ ! command -v zip &> /dev/null ]; then
|
|
if [ -z $(command -v zip) ]; then
|
|
echo "Missing zip application, aborting";
|
|
exit;
|
|
fi;
|
|
# check if sshallow or sshfoward group exists
|
|
if [ -z $(cat /etc/group | grep "sshallow:") ]; then
|
|
echo "Missing ssh access group: sshallow";
|
|
exit;
|
|
fi;
|
|
# flag if we can set ssh forward
|
|
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}";
|
|
exit;
|
|
fi;
|
|
# make sure my own folder is owned by root and 600 (except for testing)
|
|
if [ $(stat -c %a .) != "600" ]; then
|
|
echo "!!!! RECOMMENDED TO HAVE BASE FOLDER SET TO '600' AND USER 'root' !!!!"
|
|
fi;
|
|
if [ $(whoami) != "root" ]; then
|
|
if [ ${TEST} -eq 0 ] && [ ${INFO} -eq 0 ]; then
|
|
echo "Script must be run as root user";
|
|
exit;
|
|
else
|
|
echo "!!!! Script must be run as root user !!!!";
|
|
fi;
|
|
fi;
|
|
# create users
|
|
cat "${ROOT_FOLDER}${input_file}" |
|
|
while read i; do
|
|
# skip rows start with # (comment)
|
|
if [[ "${i}" =~ ^\# ]]; then
|
|
continue;
|
|
fi;
|
|
# 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
|
|
echo "[!!] Not valid ssh access type ${ssh_access_type}, set to allow";
|
|
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 ${username}";
|
|
break;
|
|
fi;
|
|
ssh_group="ssh${ssh_access_type}";
|
|
# sshallow group is always added
|
|
sub_group_opt=" -G ${ssh_group}";
|
|
# check if "," inside and extract sub groups
|
|
if [ -z "${_group##*,*}" ]; then
|
|
sub_group=$(echo "${_group}" | cut -d "," -f 2-);
|
|
sub_group_opt=" -G ${sub_group}";
|
|
fi;
|
|
# 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;
|
|
# 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 "${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}${username}${separator}${ssh_keytype}.pem";
|
|
# the full file including folder name
|
|
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";
|
|
|
|
if [ ${INFO} -eq 1 ]; then
|
|
# test if pub file exists or not, test if user exists
|
|
echo -n "User: '${username}:${group}(${sub_group});${ssh_group}', SSH: ${ssh_keygen_id}";
|
|
if getent passwd ${username} > /dev/null 2>&1; then
|
|
echo -n ", User exists";
|
|
fi;
|
|
if [ -f "${ssh_keyfile_check_pub}" ]; then
|
|
echo -n ", SSH Pub key OK";
|
|
fi;
|
|
# line break
|
|
echo "";
|
|
continue;
|
|
fi;
|
|
|
|
# add group for each entry in _group
|
|
for create_group in ${_group//,/ }; do
|
|
if [ ${TEST} -eq 0 ]; then
|
|
groupadd -f ${create_group};
|
|
else
|
|
echo "$> groupadd -f ${create_group}";
|
|
fi;
|
|
done;
|
|
# check if user is not already created
|
|
# if getent passwd ${username} > /dev/null 2>&1; then
|
|
if id "${username}" &>/dev/null; then
|
|
echo "-- Skip '${username}:${group}(${sub_group})'";
|
|
else
|
|
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} -d "${HOME_FOLDER}" -m ${username};
|
|
else
|
|
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 14 1));
|
|
else
|
|
echo "! Override password set";
|
|
password=${_password};
|
|
fi;
|
|
# create SSH key
|
|
echo " > Create ssh key-pair '${ssh_keyfile}'";
|
|
if [ ${TEST} -eq 0 ]; then
|
|
ssh-keygen \
|
|
-t ${ssh_keytype} \
|
|
-f "${ssh_keyfile}" \
|
|
-C "${hostname}: ${username}@${group}" \
|
|
-a 100 -N "${password}"
|
|
else
|
|
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})" ${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
|
|
echo " < Use existing public ssh key '${ssh_keygen_id}.pub'";
|
|
# Password already set notification
|
|
fi;
|
|
password="[ALREADY SET]";
|
|
fi;
|
|
if [ ${skip_ssh} -eq 0 ]; then
|
|
# write login info to output file
|
|
if [ ${TEST} -eq 0 ]; then
|
|
create_output_file="${ROOT_FOLDER}${output_file}";
|
|
else
|
|
create_output_file="${ROOT_FOLDER}${output_file}.TEST";
|
|
fi;
|
|
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
|
|
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 file";
|
|
if [ ${TEST} -eq 0 ]; then
|
|
cat "${ssh_keyfile_pub}" > ${SSH_AUTHORIZED_FILE};
|
|
else
|
|
echo "$> cat ${ssh_keyfile_pub} > ${SSH_AUTHORIZED_FILE}";
|
|
fi;
|
|
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 " > Secure central authorized_keys file";
|
|
if [ ${TEST} -eq 0 ]; then
|
|
chown ${username}:${group} ${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}:${group} ${SSH_AUTHORIZED_FILE}";
|
|
echo "$> chmod 400 ${SSH_AUTHORIZED_FILE}";
|
|
echo "$> chattr +i ${SSH_AUTHORIZED_FILE}";
|
|
fi;
|
|
fi;
|
|
fi;
|
|
done;
|
|
|
|
# End before anything because this is just info run
|
|
if [ ${INFO} -eq 1 ]; then
|
|
exit;
|
|
fi;
|
|
# zip everything and remove data in ssh key folder, delete output file with passwords
|
|
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}";
|
|
# delete the rest
|
|
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}*";
|
|
fi;
|
|
|
|
# __END__
|