Missing username in create folder path for adding new user check if pub key exists in central location ran even if central file was missing. Fixed check for .ssh or central place to use. File check before trying to remove chattr "i" flag, can't do that if the file does not exists.
399 lines
13 KiB
Bash
Executable File
399 lines
13 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//');
|
|
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}";
|
|
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}${username}" -m ${username};
|
|
else
|
|
echo "$> useradd -c `date +"%F"` -s /bin/bash -g ${group}${sub_group_opt} -d "${HOME_FOLDER}${username}" -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='';
|
|
if [ -f "${SSH_AUTHORIZED_FILE}" ]; then
|
|
found=$(grep "$(cat ${ssh_keyfile_check_pub})" ${SSH_AUTHORIZED_FILE});
|
|
fi;
|
|
if [ ! -z "${found}" ]; then
|
|
skip_ssh=1;
|
|
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;
|
|
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;
|
|
# add
|
|
echo " > Add public into authorized_keys file";
|
|
if [ ${TEST} -eq 0 ]; then
|
|
if
|
|
[ ! -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ] &&
|
|
[ -f "${SSH_AUTHORIZED_FILE}" ];
|
|
then
|
|
chattr -i ${SSH_AUTHORIZED_FILE};
|
|
fi;
|
|
cat "${ssh_keyfile_pub}" > ${SSH_AUTHORIZED_FILE};
|
|
else
|
|
if
|
|
[ ! -z "${SSH_CENTRAL_AUTHORIZED_FILE_FOLDER}" ] &&
|
|
[ -f "${SSH_AUTHORIZED_FILE}" ];
|
|
then
|
|
echo "$> chattr -i ${SSH_AUTHORIZED_FILE}";
|
|
fi;
|
|
echo "$> cat ${ssh_keyfile_pub} > ${SSH_AUTHORIZED_FILE}";
|
|
fi;
|
|
# 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 " > 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;
|
|
|
|
# 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__
|