In this project, we want to onboard 20 new Linux users onto a server. Create a shell script that reads a CSV
file of a list of users to be onboarded. Each user requires the following:
Must have a default
/home
directory, ie/home/cdrani/
for usercdrani
Each user must be added to a
developers
groupAn
.ssh
folder with anauthorized_keys
file that includes thersa.pub
key of the current user ($USER)
STEP 1: Setup Private & Public keys for $USER
Generating ssh private (
id_rsa
) and public key (id_rsa.pb
) for $USER. The public key will be copied over to each onboarded user's.ssh/authorized_keys
file. We will make use ofssh-keygen
and just pressEnter/Return
key to accept the default file names and placement. In the end, we should have bothid_rsa
andid_rsa.pub
keys in~/.ssh
folder.sudo ssh-keygen
STEP 2: Onboarding Script
Now for the script itself. It's heavily documented with comments, but some additional criteria I included are to verify that the script is run by a root
user, a .csv
file is passed as an argument and a default password of password
is set for each onboarded user with an expiration date of 7 days.
#!/bin/bash
# Exit if script is not run as root
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root."
exit 1
fi
# Exit if file is not provided
if [ $# -eq 0 ]; then
echo "Please provide the name of the CSV file."
exit 1
fi
# Exit if file provided is not a .csv file
file="$1"
if [ "${file##*.}" != "csv" ]; then
echo "The file must be a CSV file."
exit 1
fi
# Create developers group if it doesn't exist
if ! getent group developers > /dev/null 2>&1; then
groupadd developers
fi
# Read the CSV file
while IFS=',' read -r name
do
username=$name
# Check if user exists
if id "$username" >/dev/null 2>&1; then
echo "User $username already exists."
continue
fi
# Create user
useradd "$username" -g developers -m
echo "$username:default_password" | chpasswd
# Set password expiration to 7 days
# After expiration user needs to set/change password
chage -m 7 "$username"
# Ensure .ssh folder exists for user, otherwise create one
home_dir=$(eval echo "~$username")
ssh_dir="$home_dir/.ssh"
if [ ! -d "$ssh_dir" ]; then
mkdir "$ssh_dir"
chmod 700 "$ssh_dir" $username
fi
# Add public key to users' ~/.ssh/authorized_keys
auth_keys="$ssh_dir/authorized_keys"
touch "$auth_keys"
chmod 600 "$auth_keys" $username
# Need to give ownership to user else cannot login as them!!!
chown $username:developers "$auth_keys"
echo $(cat ~/.ssh/id_rsa.pub) >> "$auth_key"
done < "$file"
To run the script we need a *.csv
file with a list of names:
# names.csv
beth
mark,
lucy,
fred,
liza
Then we need our script to be executable before we run it:
sudo chmod +x onboard_users.sh
sudo ./onboard_users.sh names.csv
Let's test out some of the conditionals we have in place:
We now should have /home/$user
(for ex. /home/beth/
) directories for each user in the names.csv
file:
Finally, we should be able to log in as any of the newly onboarded users, however, our new users don't use the same private key that we set up when launching our ec2 instance - we must use the one we generated above (id_rsa
).
First, we need to ensure our key is not publicly viewable, i.e it is not writable:
sudo chmod -w id_rsa
After the above, we can then copy the private key from our remote server (ec2) to our local environment using scp
:
# scp -i <key> <remote_username>@<Host>:<PathToFile> <LocalFileLocation>
scp -i ~/Desktop/webserver-ec2.pem ubuntu@35.85.56.192:~/.ssh/id_rsa ~/.ssh/aux_id_rsa
With that complete, from our local computer, we can log in as an onboarded user:
ssh -i ~/.ssh/aux_id_rsa fred@38.85.56.192
Only users with the auth key can log in:
Note: One can log in using the *.pem
key for the ec2 instance as well.
Bonus:
Testing the script several times to address issues necessitated removing users as well. This quickly turned into a pain point that required a deboard.sh
script. It has the same checks as the onboard.sh
one which could be refactored out into a separate script that runs before both of them, but it's good enough.
#!/bin/bash
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root."
exit 1
fi
# Check if argument is provided
if [ $# -eq 0 ]; then
echo "Please provide the name of the CSV file."
exit 1
fi
# Check if argument is a .csv file
file="$1"
if [ "${file##*.}" != "csv" ]; then
echo "The file must be a CSV file."
exit 1
fi
# Read the CSV file
while IFS=',' read -r fname lname
do
username=$fname
# Check if user exists
if ! id "$username" >/dev/null 2>&1; then
echo "User $username does not exist."
continue
fi
# Remove user
sudo userdel -r "$username"
done < "$file"