Florence Okoli
Posted on July 3, 2024
Bash, short for Bourne Again Shell, is a Unix shell and command language that has been a fundamental part of system administration and development for many years. As the default shell on many Unix-like operating systems, including Linux and macOS, Bash is renowned for its powerful capabilities in scripting and automation.
Imagine having to create user accounts, assign them to appropriate groups, set up home directories, and generate secure passwords for each new developer joining your team. Doing this manually can be tedious and error-prone. This is where Bash comes in. You can automate these repetitive tasks with Bash scripting, ensuring consistency and saving valuable time.
In this article, I used a Bash script to automate the onboarding process for new developers. This script reads a text file containing usernames and their respective groups, creates users, assigns them to groups, sets up their home directories, generates random passwords, and logs all actions.
Prerequisites
- A Unix-based system (Linux or macOS)
- Basic knowledge of Unix commands and Bash scripting
Objective
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
My create_users.sh Script
#!/bin/bash
# Log file and password storage
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"
# Ensure the /var/secure directory exists
if [ ! -d "/var/secure" ]; then
mkdir -p /var/secure
chmod 700 /var/secure
fi
# Ensure the log file and password file exist and have correct permissions
touch $LOG_FILE
touch $PASSWORD_FILE
chmod 600 $PASSWORD_FILE
# Function to log messages
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOG_FILE
}
# Check if the file is supplied
if [ $# -ne 1 ]; then
log_message "ERROR: No input file supplied"
echo "Usage: $0 <name-of-text-file>"
exit 1
fi
INPUT_FILE=$1
# Check if input file exists
if [ ! -f $INPUT_FILE ]; then
log_message "ERROR: Input file does not exist"
echo "ERROR: Input file does not exist"
exit 1
fi
# Read the input file line by line
while IFS=';' read -r username groups; do
# Trim whitespace
username=$(echo $username | xargs)
groups=$(echo $groups | xargs)
# Skip empty lines
if [ -z "$username" ]; then
continue
fi
# Create a personal group for the user
if ! getent group $username >/dev/null; then
groupadd $username
log_message "Group $username created."
else
log_message "Group $username already exists."
fi
# Create the user with the personal group
if ! id -u $username >/dev/null 2>&1; then
useradd -m -g $username $username
log_message "User $username created."
else
log_message "User $username already exists."
fi
# Assign the user to additional groups
IFS=',' read -ra ADDR <<< "$groups"
for group in "${ADDR[@]}"; do
group=$(echo $group | xargs)
if [ ! -z "$group" ]; then
if ! getent group $group >/dev/null; then
groupadd $group
log_message "Group $group created."
fi
usermod -aG $group $username
log_message "User $username added to group $group."
fi
done
# Generate a random password
password=$(openssl rand -base64 12)
# Set the user's password
echo "$username:$password" | chpasswd
log_message "Password set for user $username."
# Store the password securely
echo "$username,$password" >> $PASSWORD_FILE
done < "$INPUT_FILE"
# Set the correct permissions on the password file
chmod 600 $PASSWORD_FILE
log_message "User creation process completed."
echo "User creation process completed. Check $LOG_FILE for details."
A detailed breakdown of the Script
Here is what this script does:
Shebang
The#!/bin/bash
known as the shebang indicates that the script should be run on the BASH shell.Path to Log file and Password file
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"
The LOG_FILE
and PASSWORD_FILE
are variables that store the path to the log file and password file respectively.
- Create /var/secure directory and set permission if it doesn't exist
if [ ! -d "/var/secure" ]; then
mkdir -p /var/secure
chmod 700 /var/secure
fi
- Create Log file and Password file if they don't exist and set permission
touch $LOG_FILE
touch $PASSWORD_FILE
chmod 600 $PASSWORD_FILE
touch $LOG_FILE
and touch $PASSWORD_FILE
creates the log and password files if they do not already exist.
chmod 600 $PASSWORD_FILE
sets the permissions for the password file so that only the file owner can read and write to it.
- Log message function
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOG_FILE
}
The log_message
function takes a message as an argument and appends it to the log file with a timestamp.
- Check if input file is provided
if [ $# -ne 1 ]; then
log_message "ERROR: No input file supplied"
echo "Usage: $0 <name-of-text-file>"
exit 1
fi
This checks if [ $# -ne 1 ]; then
checks if exactly one argument (the input file) is supplied to the script.
If not, it logs an error, prints a usage message, and exits the script.
INPUT_FILE=$1
assigns the first argument (input file) to the variable INPUT_FILECheck if the input file exists
if [ ! -f $INPUT_FILE ]; then
log_message "ERROR: Input file does not exist"
echo "ERROR: Input file does not exist"
exit 1
fi
The if [ ! -f $INPUT_FILE ]; then
checks if the input file exists.
If not, it logs an error, prints an error message, and exits the script.Cre
- Read and process the input file
The while IFS=';' read -r username groups; do
starts a loop to read the input file line by line, expecting each line to contain a username and groups separated by a semicolon (;).
- The command below trims whitespace from the username and groups variables if any.
username=$(echo $username | xargs)
groups=$(echo $groups | xargs)
While
if [ -z "$username" ]; then
continue
fi
Skips empty lines (where username is empty).
- Create a group for user
if ! getent group $username >/dev/null; then
groupadd $username
log_message "Group $username created."
else
log_message "Group $username already exists."
fi
This creates a personal group for the user if it doesn't exist and logs the action.
- Creates user for group
if ! id -u $username >/dev/null 2>&1; then
useradd -m -g $username $username
log_message "User $username created."
else
log_message "User $username already exists."
fi
This creates the user with their group if they don't already exist and logs the action.
- Creates additional groups for users.
IFS=',' read -ra ADDR <<< "$groups"
for group in "${ADDR[@]}"; do
group=$(echo $group | xargs)
if [ ! -z "$group" ]; then
if ! getent group $group >/dev/null; then
groupadd $group
log_message "Group $group created."
fi
usermod -aG $group $username
log_message "User $username added to group $group."
fi
done
This command splits the group's string into an array, iterates over it, checks if the group exists (creating it if necessary) and adds the user to the group, logging each action.
Generate a random password
Thepassword=$(openssl rand -base64 12)
generates a random password using the OpenSSLSet the user's password
echo "$username:$password" | chpasswd
log_message "Password set for user $username."
echo "$username,$password" >> $PASSWORD_FILE
done < "$INPUT_FILE"
The code above sets the user's password and then appends the username and password to the PASSWORD_FILE
This
done < "$INPUT_FILE"
code ends the loop that reads from the INPUT FILEThe
chmod 600 $PASSWORD_FILE
code ensures the password file's permissions are secure after all passwords have been added.Log completion of the user creation process
log_message "User creation process completed."
Test the Script
To test this script, let's create a users.txt
file
nano users.txt
In the text file, enter the usernames and groups
wendy; engineering,webteam
florenceokoli; admins, dev_team
chi; support
Execute the Script
`chmod create_users.sh
Run the Script
sudo ./create_users.sh users.txt
Output
Conclusion
Bash is a powerful scripting tool used to automate various tasks on Unix-like operating systems. This script is designed to read a text file containing usernames and their respective groups, create users and their personal groups, assign users to additional groups, set up home directories, generate random passwords, and log all these actions for auditing purposes. Additionally, it stores the generated passwords securely in a dedicated file.
This project is a stage 1 task in the Devops HNG-11 Internship. For more information about the HNG Internship and its various opportunities, visit HNG Internship and HNG Hire.
Posted on July 3, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.