Hey there!
So here is a synopsis of my stage 1 task at the HNG DevOps Internship
Task:
Your company has employed many new developers. As a SysOps engineer, write a bash script called create_users.sh
that reads a text file containing the employee’s usernames and group names, where each line is formatted as user;groups
.
The script should create users and groups as specified, set up home directories with appropriate permissions and ownership, generate random passwords for the users, and log all actions to /var/log/user_management.log
. Additionally, store the generated passwords securely in /var/secure/user_passwords.txt
.
Ensure error handling for scenarios like existing users and provide clear documentation and comments within the script.
Sample Input
light; sudo,dev,www-data
idimma; sudo
mayowa; dev,www-data
Solution
The programme I wrote solves the problem by following these procedures;
- First, we read the
input file
using a function that adds the users to a global variable calledusers
and the groups to another variable calledgroups
. It does this simultaneously allowing the index of each user inusers
to match their corresponding groups ingroups
.
I also ensure the user has entered a valid input file before running this.
Here's the code that does all of this:
declare -a users
declare -a groups
function read_input() {
local file="$1"
while IFS= read -r line; do
user=$(echo "$line" | cut -d';' -f1)
groups_data=$(echo "$line" | cut -d';' -f2 | tr -d '[:space:]')
users+=("$user")
groups+=("$groups_data")
done < "$file"
}
if [[ $# -ne 1 ]]; then
echo "Usage: $0 <input_file>"
exit 1
fi
input_file="$1"
echo "Reading input file: $input_file"
read_input "$input_file"
- Next, I go on to create the required files and their directories if they don't already exist using this code:
log_file="/var/log/user_management.log"
password_file="/var/secure/user_passwords.txt"
if [ ! -f "$log_file" ]; then
mkdir -p /var/log
touch "$log_file"
fi
if [ ! -f "$password_file" ]; then
mkdir -p /var/secure
touch "$password_file"
fi
- Then the main event, at this point I have a list of the users in
users
, a list of their corresponding groups ingroups
and all the files I will need to store valuable information such as logs and the passwords of the users I created.
Now, I use a for
loop to iterate over each user and their corresponding groups with an index.
Remember we created the users
and groups
array simultaneously by looping over each line in the file this means the user at index
in
0users
needs to be added to the groups at index 0
in groups
, so our for
loop will look like this:
for (( i = 0; i < ${#users[@]}; i++ )); do
user="${users[$i]}"
user_groups="${groups[$i]}"
So user
is the user we are working on and user_groups
are the groups we are adding them to.
Next, we check if the user
exists, if they do we just continue with the next iteration; else, we create them with this code:
if id "$user" &>/dev/null; then
echo "User $user already exists, Skipped" | tee -a "$log_file"
else
# Create user
useradd -m -s /bin/bash "$user"
if [[ $? -ne 0 ]]; then
echo "Failed to create user $user" | tee -a "$log_file"
exit 1
fi
echo "User $user created" | tee -a "$log_file"
Then we set a password for them by using openssl to generate 50 random base64 characters then we filter the result to extract the alphabets, numbers and some special characters. We finally slice the first 10 characters and this will serve as the user's password.
We go ahead to store the users password in /var/secure/user_passwords.txt
.
These are done using the code below:
# Set password
password=$(openssl rand -base64 50 | tr -dc 'A-Za-z0-9!?%=' | head -c 10)
echo "$user:$password" | chpasswd
if [[ $? -ne 0 ]]; then
echo "Failed to set password for $user" | tee -a "$log_file"
exit 1
fi
echo "Password for $user set" | tee -a "$log_file"
echo "$user:$password" >> "$password_file"
Finally, we add the user to their groups.
We do this by first of all checking if a personal group was created for the user--most linux distros do this by default on user creation due to security reasons. But if it didn't we create a personal group for the user and add the user to the group.
See code below:
# Create personal group if linux distro didn't create it by default
if grep -q "^$user:" /etc/group; then
echo "Personal group $user already exists" | tee -a "$log_file"
else
echo "Personal group $user does not exist, creating $user" | tee -a "$log_file"
groupadd "$user"
if [[ $? -ne 0 ]]; then
echo "Failed to create personal group $user" | tee -a "$log_file"
exit 1
fi
fi
# Add user to personal group
usermod -aG "$user" "$user"
if [[ $? -ne 0 ]]; then
echo "Failed to add $user to $user group" | tee -a "$log_file"
exit 1
fi
echo "Added $user to $user group" | tee -a "$log_file"
After which we split the previously created variable user_groups
by ,
and iterate through each element creating the group if it doesn't already exist and adding the user to the group. Then we finally close our initial loop
We do this using this code:
# Add user to other groups
for group in $(echo "$user_groups" | tr ',' '\n'); do
if grep -q "^$group:" /etc/group; then
echo "Group $group already exists" | tee -a "$log_file"
else
echo "Group $group does not exist, creating $group" | tee -a "$log_file"
groupadd "$group"
if [[ $? -ne 0 ]]; then
echo "Failed to create group $group" | tee -a "$log_file"
exit 1
fi
fi
usermod -aG "$group" "$user"
if [[ $? -ne 0 ]]; then
echo "Failed to add $user to $group group" | tee -a "$log_file"
exit 1
fi
echo "Added $user to $group group" | tee -a "$log_file"
done
fi
done
And just like that, all the new employees now have user profiles!
You can also reuse this script for new employees. Exciting right?
You will also notice how I appropriately log each event in the log file and gracefully handle failures in each command so even if we run into unexpected problems in our execution we not only end the programme gracefully we also have a log for further investigation.
That's it for now, but be sure to tune in for the Stage 2 task 😉
I am also open to constructive criticism so be sure to leave a comment.
Also, you can learn more about HNG here
Top comments (0)