Compare commits

..

13 Commits

Author SHA1 Message Date
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
6 changed files with 256 additions and 62 deletions

2
.gitignore vendored
View File

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

View File

@@ -5,7 +5,6 @@
# base folder
BASE_FOLDER=$(dirname $(readlink -f $0))"/";
input_file='user_list.txt';
# which groups holds the ssh allowed login users (outside of admin users)
ssh_groups=('sshforward' 'sshallow');
ssh_reject_group='sshreject';

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,26 +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))"/";
root_folder="${BASE_FOLDER}";
# 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
@@ -86,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)
@@ -103,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
# 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
@@ -132,19 +185,22 @@ 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 "${username}" ] || [ -z "${_group}" ]; then
@@ -155,11 +211,11 @@ while read i; do
# 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}";
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
@@ -191,18 +247,24 @@ while read i; do
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 ${username};
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 ${username}";
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};
@@ -219,13 +281,13 @@ while read i; do
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/${username}/.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;
@@ -234,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}";"${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/${username}/.ssh/;
else
echo "$> mkdir /home/${username}/.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/${username}/.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/${username}/.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 ${username}:${group} /home/${username}/.ssh/;
chmod 700 /home/${username}/.ssh/;
chmod 600 /home/${username}/.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 ${username}:${group} /home/${username}/.ssh/";
echo "$> chmod 700 /home/${username}/.ssh/";
echo "$> chmod 600 /home/${username}/.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;
@@ -270,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

@@ -42,6 +42,8 @@ if [ ! -z "${SSH_GROUP_ADD}" ] && [ "${SSH_GROUP_ADD}" != "allow" ] && [ "${SSH_
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
@@ -85,8 +87,8 @@ for username in "$@"; do
# else try to set from option
# if not valid use allow
ssh_add_group="${SSH_GROUP_ADD}";
if [ -z "${SSH_GROUP_ADD}" ] && [ -f "${BASE_FOLDER}${input_file}" ]; then
ssh_add_group=$(grep "${username}" "${BASE_FOLDER}${input_file}" | cut -d ";" -f 4 | tr A-Z a-z | tr -d ' ');
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";

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 ""
```