Automated User Management Script for Linux Systems
damilola lawal
Posted on July 3, 2024
Nowadays managing user accounts properly is extremely important for SysOps professionals working in dynamic IT setups.
The pro of user provisioning is that it saves time, ensures consistency , security across systems and improve efficiency since much of the process can be automated.
In this article, we will discuss about bash script and how to create a bash script that can be used for creating and managing accounts of users on Linux servers.
In this article we will be writing a script which that reads a text file containing the employee’s usernames and group names, where each line is formatted as "user;groups".
This script will 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, it will store the generated passwords securely in /var/secure/user_passwords.txt.
we will ensure error handling for scenarios like existing users by the script.
Each User will have a personal group with the same group name as the username, this group name will not be written in the text file
A user can have multiple groups, each group delimited by comma ","
Usernames and user groups are separated by semicolon ";"
For example;
- light; sudo,dev,www-data
- idimma; sudo
- mayowa; dev,www-data
Where light is username and groups are sudo, dev, www-data
Firstly,
#!/bin/bash
# Check if script is run as root
if [ "$EUID" -ne 0 ]; then
echo "Please run as root"
exit 1
fi
The #!/bin/bash line at the beginning of a script is known as the shebang. This shebang line tells the operating system which interpreter to use to execute the script. In this case, it specifies the Bash shell as the interpreter.
The line if [ "$EUID" -ne 0 ]; checks if the script is being run as root. The EUID (Effective User ID) is used to determine the privileges of the executing process. The -ne operator means "not equal." Since the root user has an ID of 0, this condition checks if the current user is not root. If true, it prompts to run the script as root and exits.
Next;
# Check if the input file is provided
if [ -z "$1" ]; then
echo "Usage: bash create_users.sh <name-of-text-file>"
exit 1
fi
The script checks if a positional argument is provided. If not, it exits with a status of 1 and displays the message: "Usage: bash create_user.sh ," prompting the user to provide the correct argument.
The -z is a string value which means value has a length of zero and "$1" indicate the first parameter after the script name($0) which is assigned a variable name INPUT_FILE. So it checks if the first positional parameter is empty.
Next;
INPUT_FILE="$1"
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"
# Ensure log and password files exist and have the correct permissions
touch $LOG_FILE
chmod 644 $LOG_FILE
mkdir -p /var/secure
touch $PASSWORD_FILE
chmod 600 $PASSWORD_FILE
We will create the directory /var/secure and the file user_password.txt in it to securely store user passwords with permissions set to "600" (read and write only for the owner). Additionally, we will create the file management.log in the /var/log directory to log all events.
The first positional parameter($1) is assigned INPUT_FILE as variable
Next;
# Function to generate random password
generate_password() {
openssl rand -base64 12
}
The OpenSSL rand command will be used to generate a cryptographic password that is base64 encoded (strong and resistant as it contains letters, numbers, and characters). This function will generate the password, which will be called in the script.
Next;
# Process the input file
while IFS=';' read -r username groups; do
# Create personal group for the user
if ! getent group "$username" &>/dev/null; then
groupadd "$username"
echo "Created group $username" | tee -a $LOG_FILE
fi
Let's process the input file;
IFS means Internal Field Separator; this is an environment variable which define a list of characters the Bash shell uses as field separators. These include space, tab, newline.
Use the while condition to read the username and group taking note of the separators by the IFS.
We will create a personal group for the user but before then we will check the system group database (/etc/group) using the getent command to ensure the group is not present.
The negate operator (!) is used to reverse the outcome of an expression. In this case, if the $group does not exist, the expression with ! will evaluate to true. This condition triggers the groupadd command to create the group if it doesn't already exist.
# Check if user already exists
if id "$username" &>/dev/null; then
echo "User $username already exists. Skipping..." | tee -a $LOG_FILE
continue
fi
If user already exist then our shell script will throw an error message indicating that user exist but we want to redirect such output( standard error or output) to the /dev/null and the tee reads the output and save it silently in the $LOG_FILE.
We then use the continue to create user if user does not exist.
# Create user and personal group
useradd -m -s /bin/bash -g "$username" "$username"
if [ $? -eq 0 ]; then
echo "Created user $username with a personal group $username" | tee -a $LOG_FILE
else
echo "Failed to create user $username" | tee -a $LOG_FILE
continue
fi
Let's add create user and add to the personal group using the popular command useradd and use the -m(to add a home directory for the user, -s (to set the shell to /bin/bash).
If the user is created and added to the personal group successfully this make the exit status ($?) equal zero (0) and it print the success message "Created user $username with a personal group $username" to the $LOG_FILE and if not it execute the else statement.
Next;
# Generate password and set it for the user
password=$(generate_password)
echo "$username:$password" | chpasswd
if [ $? -eq 0 ]; then
echo "$username,$password" >> $PASSWORD_FILE
echo "Set password for $username" | tee -a $LOG_FILE
else
echo "Failed to set password for $username" | tee -a $LOG_FILE
fi
Let's call the function to generate the password and set password for the user using chpasswd (change password) , write the username,password into the $PASSWORD_FILE and log it.
chpasswd is designed to process multiple username and password pairs from standard input (usually via a pipe | or a redirection <)
.
Next,
# Create additional groups if specified
if [ -n "$groups" ]; then
IFS=',' read -ra group_array <<< "$groups"
for group in "${group_array[@]}"; do
# Create group if it doesn't exist
if ! getent group "$group" &>/dev/null; then
groupadd "$group"
echo "Created group $group" | tee -a $LOG_FILE
fi
fi
we will be creating other group which user will be by passing the $groups as an array and iterate over it by "${group_array[@]}" where "@" insinuate every character.
The character -n is also similar to the -z only that it describe value which length is greater than zero
We will check the system group database (/etc/group) using the getent command but will add a negate operator (!) which will negate the expression and makes it True, if the $group does not exist thereby causing it to create the group if it doesn't exist using the groupadd command as previously discussed.
Next;
usermod -aG "$group" "$username"
if [ $? -eq 0 ]; then
echo "Added $username to group $group" | tee -a $LOG_FILE
else
echo "Failed to add $username to group $group" | tee -a $LOG_FILE
fi
done
fi
we then add the user to group using the usermod -aG command
Finally,
done < "$INPUT_FILE"
echo "User creation process completed." | tee -a $LOG_FILE
we will close our while loop condition and pass the $INPUT_FILE to read lines from it.
Create a directory, touch a file named create.sh (shell script) in the directory and make the file executable;
sudo mkdir -p ~/bash-script
sudo chmod +x ~/bash-script/create_users.sh
open the create and paste this script;
#!/bin/bash
#check if script is run as root
if [ "$EUID" -ne 0 ]; then
echo "Please run as root"
exit 1
fi
# Check if the input file is provided
if [ -z "$1" ]; then
echo "Usage: bash create_users.sh <name-of-text-file>"
exit 1
fi
INPUT_FILE="$1"
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"
# Ensure log and password files exist and have the correct permissions
touch $LOG_FILE
chmod 644 $LOG_FILE
mkdir -p /var/secure
touch $PASSWORD_FILE
chmod 600 $PASSWORD_FILE
# Function to generate random password
generate_password() {
openssl rand -base64 12
}
# Process the input file
while IFS=';' read -r username groups; do
# Create personal group for the user
if ! getent group "$username" &>/dev/null; then
groupadd "$username"
echo "Created group $username" | tee -a $LOG_FILE
fi
# Check if user already exists
if id "$username" &>/dev/null; then
echo "User $username already exists. Skipping..." | tee -a $LOG_FILE
continue
fi
# Create user and personal group
useradd -m -s /bin/bash -g "$username" "$username"
if [ $? -eq 0 ]; then
echo "Created user $username with a personal group $username" | tee -a $LOG_FILE
else
echo "Failed to create user $username" | tee -a $LOG_FILE
continue
fi
# Generate password and set it for the user
password=$(generate_password)
echo "$username:$password" | chpasswd
if [ $? -eq 0 ]; then
echo "$username,$password" >> $PASSWORD_FILE
echo "Set password for $username" | tee -a $LOG_FILE
else
echo "Failed to set password for $username" | tee -a $LOG_FILE
fi
# Create additional groups if specified
if [ -n "$groups" ]; then
IFS=',' read -ra group_array <<< "$groups"
for group in "${group_array[@]}"; do
# Create group if it doesn't exist
if ! getent group "$group" &>/dev/null; then
groupadd "$group"
echo "Created group $group" | tee -a $LOG_FILE
fi
usermod -aG "$group" "$username"
if [ $? -eq 0 ]; then
echo "Added $username to group $group" | tee -a $LOG_FILE
else
echo "Failed to add $username to group $group" | tee -a $LOG_FILE
fi
done
fi
done < "$INPUT_FILE"
echo "User creation process completed." | tee -a $LOG_FILE
Create a file (input_file.txt) containing username;groups
light; sudo,dev,www-data
idimma; sudo
mayowa; dev,www-data
Run the script and pass the input_file.txt as argument.
Thank you for reading, to learn more kindly join the HNG internship programme to get your tech skill upgraded and land you dream job.
Follow this link
https://hng.tech/internship,
https://hng.tech/hire
hsh
Posted on July 3, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.