Automating the Management of Users and Groups Using a Bash Script in Linux.
Lanky-23
Posted on July 3, 2024
As a SysOps engineer in a company, there is the occasional necessity to manage the creation of users and groups, maximum efficiency can be attained by automating this process. To address this, I have developed a Bash script to create users and groups, set up home directories with appropriate permissions and ownership, generate random passwords, and log all actions.
This article details the functionality and structure of the script, ensuring error handling for scenarios such as existing users, and providing comprehensive documentation and comments within the script.
Script Overview
The creation of Bash script that reads a text file containing users and groups.
Creation of users and groups as specified.
Setting up home directories with appropriate permissions, generating random passwords, and logging all actions to file.
Securely storing generated passwords.
Let's dive into the script
Every Bash script begins with the shebang line.
#!/bin/bash
This indicates that the script should be run using the Bash shell.
Directory and File Setup
mkdir -p /var/log /var/secure
touch /var/log/user_management.log
touch /var/secure/user_passwords.txt
chmod 600 /var/secure/user_passwords.txt
This ensures that the directories /var/log
and /var/secure
exist. The -p
flag allows the command to create parent directories as needed without raising an error if the directory already exists, and creates the log file user_management.log in /var/log
and the password file user_passwords.txt in /var/secure
.
Having created the /var/secure
directory. Using chmod 600
I set the permissions for user_passwords.txt to be readable and writable only by the file's owner.
Action Logging Function
This defines a function log_action
that appends a timestamped log entry to the user_management.log file.
log_action() {
echo "$(date) - $1" >> "/var/log/user_management.log"
}
User Creation Function
- I declared the
create_user()
function, defining three variables: user (username), groups (additional groups), and password (which will be generated).
create_user() {
user, groups, and password
local user="$1"
local groups="$2"
local password
I proceeded to check if the user already exists using the 'id' command. If the user exists, log "$user already exists" and exit the function.
if id "$user" &>/dev/null; then
log_action "User $user already exists."
return
fi
Next, I created a personal group for the user with the same name as the username using groupadd "$user"
.
groupadd "$user"
Group Handling and Creation
The script takes the list of additional groups and splits them into separate items in a group_array
. Logs a message that lists all the groups the user will be added to. The script then goes through each group in the array, removes any extra spaces from the group name, and checks if the group already exists. If the group doesn't exist, it creates the group.
IFS=' ' read -ra group_array <<< "$groups"
# Log the group array
log_action "User $user will be added to groups: ${group_array[*]}"
for group in "${group_array[@]}"; do
group=$(echo "$group" | xargs) # Trim whitespace
if ! getent group "$group" &>/dev/null; then
groupadd "$group"
log_action "Group $group created."
fi
done
I created the user with a home directory (-m)
, a default shell (-s /bin/bash)
, and set the primary group to the personal group (-g "$user")
. Logging the success or failure of the user creation.
useradd -m -s /bin/bash -g "$user" "$user"
if [ $? -eq 0 ]; then
log_action "User $user created with primary group: $user"
else
log_action "Failed to create user $user."
return
fi
Followed by, adding the user to the additional groups using usermod -aG
and logging the action. This splits the additional groups into an array, logs them, trims whitespace, checks if each group exists, and creates any missing groups.
for group in "${group_array[@]}"; do
usermod -aG "$group" "$user"
done
log_action "User $user added to groups: ${group_array[*]}"
Random Password Generation & Granting Home Directory Permissions
I generated a 12-character random password using /dev/urandom
, formatted it, and set it for the user using chpasswd
. Appended the username and password to user_passwords.txt
and stored them in the secure file. Setting the permissions for the user's home directory to be accessible only by the user changing ownership to the user.
password=$(</dev/urandom tr -dc A-Za-z0-9 | head -c 12)
echo "$user:$password" | chpasswd
echo "$user,$password" >> "/var/secure/user_passwords.txt"
chmod 700 "/home/$user"
chown "$user:$user" "/home/$user"
log_action "Password for user $user set and stored securely."
}
Main Script Execution
This begins by checking if exactly one argument <user_list_file>
is provided. If not, it prints usage instructions and exits. Then it checks if the provided 'User list file' exists. If not, it prints an error message and exits. For each line, it reads the username and groups, trims whitespace, replaces commas with spaces, and calls the create_user()
function with the parsed values. Finally, it prints a message indicating that user creation is complete and where to find more information.
if [ $# -ne 1 ]; then
echo "Usage: $0 <user_list_file>"
exit 1
fi
filename="$1"
if [ ! -f "$filename" ]; then
echo "Users list file $filename not found."
exit 1
fi
while IFS=';' read -r user groups; do
user=$(echo "$user" | xargs)
groups=$(echo "$groups" | xargs | tr -d ' ')
groups=$(echo "$groups" | tr ',' ' ')
create_user "$user" "$groups"
done < "$filename"
echo "User created. Type cat /var/log/user_management.log for more information."
This is the combined script.⬇️
#!/bin/bash
# Create directory for user logs and passwords
mkdir -p /var/log /var/secure
# Create logs file and passwords file
touch /var/log/user_management.log
touch /var/secure/user_passwords.txt
# Grant read and write permissions for file owner only
chmod 600 /var/secure/user_passwords.txt
# Action Logging function
log_action() {
echo "$(date) - $1" >> "/var/log/user_management.log"
}
create_user() {
# Define three variables passed to the function: user, groups, and password
local user="$1"
local groups="$2"
local password
# Check if user already exists
if id "$user" &>/dev/null; then
log_action "User $user already exists."
return
fi
# Create personal group for the user
groupadd "$user"
# Create additional groups if they do not exist
IFS=' ' read -ra group_array <<< "$groups"
# Log the group array
log_action "User $user will be added to groups: ${group_array[*]}"
for group in "${group_array[@]}"; do
group=$(echo "$group" | xargs) # Trim whitespace
if ! getent group "$group" &>/dev/null; then
groupadd "$group"
log_action "Group $group created."
fi
done
# Create user with home directory and shell, primary group set to the personal group
useradd -m -s /bin/bash -g "$user" "$user"
if [ $? -eq 0 ]; then
log_action "User $user created with primary group: $user"
else
log_action "Failed to create user $user."
return
fi
# Add the user to additional groups
for group in "${group_array[@]}"; do
usermod -aG "$group" "$user"
done
log_action "User $user added to groups: ${group_array[*]}"
# Generate password and store it securely in a file
password=$(</dev/urandom tr -dc A-Za-z0-9 | head -c 12)
echo "$user:$password" | chpasswd
# Store user and password securely in a file
echo "$user,$password" >> "/var/secure/user_passwords.txt"
# Set permissions and ownership for user home directory
chmod 700 "/home/$user"
chown "$user:$user" "/home/$user"
log_action "Password for user $user set and stored securely."
}
# Check if user list file is provided
if [ $# -ne 1 ]; then
echo "Usage: $0 <user_list_file>"
exit 1
fi
filename="$1"
if [ ! -f "$filename" ]; then
echo "Users list file $filename not found."
exit 1
fi
# Read user list file and create users
while IFS=';' read -r user groups; do
user=$(echo "$user" | xargs)
groups=$(echo "$groups" | xargs | tr -d ' ')
# Replace commas with spaces for usermod group format
groups=$(echo "$groups" | tr ',' ' ')
create_user "$user" "$groups"
done < "$filename"
echo "User created. Type cat /var/log/user_management.log for more information."
Testing The Script
- To use this script, provide a user list file as an argument. Each line in the file should contain a username and a comma-separated list of groups (optional), separated by a semicolon. For example:
light; sudo,dev,www-data
idimma; sudo
mayowa; dev,www-data
- To run the script, use this command.
./script_name.sh user_list_file.txt
. For a non-root user, usesudo ./create_users.sh user_list_file.txt
Conclusion
The Bash script automates user management by creating users, managing groups, generating secure passwords, and logging actions. It ensures the secure handling of passwords and provides detailed logs for auditing purposes. This automation is critical for efficiently onboarding new users and maintaining system security and organization.
To rapidly upskill and advance your tech career, visit https://hng.tech/internship or https://hng.tech/premium for more information.
Posted on July 3, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.