Automating User and Group Management on Linux with a Bash Script
Tags: bash, devops
Published: 2024-07-05 07:31:20

## Introduction
Managing users and groups on a Linux system can be daunting, especially when onboarding new employees. As a SysOps engineer, automating these tasks can save time and reduce errors. This article explores a bash script called create_users.sh that automates user creation, password management, and group assignments. This script reads from an input file and logs all actions, ensuring a smooth and auditable process.

## Script Features
Reading Input File: Parses a text file containing usernames and group names.
User Creation: Creates users with personal groups if they don't already exist.
Password Management: Generates and assigns random passwords to users.
Group Assignment: Adds users to specified groups.
Logging: Records all actions to a log file for auditing purposes.

## The Script
Below is the create_users.sh script. Save this script to your server and make it executable.

```
#!/bin/bash

# Function to read and parse the input file
read_input_file() {
  local filename="$1"
  while IFS=';' read -r user groups; do
    users+=("$(echo "$user" | xargs)")
    group_list+=("$(echo "$groups" | tr -d '[:space:]')")
  done < "$filename"
}

# Function to create a user with its group
create_user_with_group() {
  local username="$1"
  if id "$username" &>/dev/null; then
    echo "User $username already exists." | tee -a "$log_file"
  else
    groupadd "$username"
    useradd -m -g "$username" -s /bin/bash "$username"
    echo "Created user $username with personal group $username." | tee -a "$log_file"
  fi
}

# Function to set a password for the user
set_user_password() {
  local username="$1"
  local password=$(openssl rand -base64 12)
  echo "$username:$password" | chpasswd
  echo "$username,$password" >> "$password_file"
  echo "Password for $username set and stored." | tee -a "$log_file"
}

# Function to add users to additional groups
add_user_to_groups() {
  local username="$1"
  IFS=',' read -r -a groups <<< "$2"
  for group in "${groups[@]}"; do
    if ! getent group "$group" &>/dev/null; then
      groupadd "$group"
      echo "Group $group created." | tee -a "$log_file"
    fi
    usermod -aG "$group" "$username"
    echo "Added $username to group $group." | tee -a "$log_file"
  done
}

# Check for an input file argument
if [[ $# -ne 1 ]]; then
  echo "Usage: $0 <input_file>"
  exit 1
fi

# Initialize variables
input_file="$1"
log_file="/var/log/user_management.log"
password_file="/var/secure/user_passwords.txt"
declare -a users
declare -a group_list

# Create log and password files if they do not exist
mkdir -p /var/log /var/secure
touch "$log_file"
touch "$password_file"
chmod 600 "$password_file"

# Read input file
read_input_file "$input_file"

# Process each user
for ((i = 0; i < ${#users[@]}; i++)); do
  username="${users[i]}"
  user_groups="${group_list[i]}"

  if [[ "$username" == "" ]]; then
    continue  # Skip empty usernames
  fi

  create_user_with_group "$username"
  set_user_password "$username"
  add_user_to_groups "$username" "$user_groups"
done

echo "User creation and group assignment completed." | tee -a "$log_file"

```

## How to Use the Script

- Prepare the Input File: Create a file named users.txt with the following format:

```
light;sudo,dev,www-data
idimma;sudo
mayowa;dev,www-data

```
- Reading the Input File

The script begins by defining a function to read and parse the input file. Each line in the file contains a username and a list of groups separated by a semicolon (;).

```
# Function to read and parse the input file
read_input_file() {
  local filename="$1"
  while IFS=';' read -r user groups; do
    users+=("$(echo "$user" | xargs)")
    group_list+=("$(echo "$groups" | tr -d '[:space:]')")
  done < "$filename"
}

```
- Creating a User with a Personal Group

Next, we define a function to create a user and their group. If the user already exists, the script logs a message and skips the creation.

```
# Function to create a user with its group
create_user_with_group() {
  local username="$1"
  if id "$username" &>/dev/null; then
    echo "User $username already exists." | tee -a "$log_file"
  else
    groupadd "$username"
    useradd -m -g "$username" -s /bin/bash "$username"
    echo "Created user $username with personal group $username." | tee -a "$log_file"
  fi
}

```
- Setting a Password for the User

This function generates a random password for the user, sets it, and stores the password in a secure file.

```
# Function to set a password for the user
set_user_password() {
  local username="$1"
  local password=$(openssl rand -base64 12)
  echo "$username:$password" | chpasswd
  echo "$username,$password" >> "$password_file"
  echo "Password for $username set and stored." | tee -a "$log_file"
}

```
- Adding the User to Additional Groups

The following function adds the user to the specified groups. If a group does not exist, it is created.

```
# Function to add users to additional groups
add_user_to_groups() {
  local username="$1"
  IFS=',' read -r -a groups <<< "$2"
  for group in "${groups[@]}"; do
    if ! getent group "$group" &>/dev/null; then
      groupadd "$group"
      echo "Group $group created." | tee -a "$log_file"
    fi
    usermod -aG "$group" "$username"
    echo "Added $username to group $group." | tee -a "$log_file"
  done
}

```
- Main Script Execution

The main part of the script checks for the input file argument initializes variables, creates log and password files if they don't exist, and processes each user in the input file.

```
# Check for an input file argument
if [[ $# -ne 1 ]]; then
  echo "Usage: $0 <input_file>"
  exit 1
fi

# Initialize variables
input_file="$1"
log_file="/var/log/user_management.log"
password_file="/var/secure/user_passwords.txt"
declare -a users
declare -a group_list

# Create log and password files if they do not exist
mkdir -p /var/log /var/secure
touch "$log_file"
touch "$password_file"
chmod 600 "$password_file"

# Read input file
read_input_file "$input_file"

# Process each user
for ((i = 0; i < ${#users[@]}; i++)); do
  username="${users[i]}"
  user_groups="${group_list[i]}"

  if [[ "$username" == "" ]]; then
    continue  # Skip empty usernames
  fi

  create_user_with_group "$username"
  set_user_password "$username"
  add_user_to_groups "$username" "$user_groups"
done

echo "User creation and group assignment completed." | tee -a "$log_file"

```

Run the Script: Execute the script with the input file as an argument:

```
./create_users.sh users.txt

```
Check Logs and Passwords: Review the log file at /var/log/user_management.log for actions taken and find user passwords in /var/secure/user_passwords.txt.

## Benefits of Automation

- Efficiency: Automates repetitive tasks, freeing time for more critical activities.

- Consistency: Ensures that user and group configurations are applied uniformly.

- Security: Randomly generated passwords enhance security, and storing them securely minimizes risks.

- Auditing: Detailed logging helps in tracking changes and troubleshooting.

## Learn More
If you're interested in advancing your career in tech, consider joining the HNG Internship program by visiting [HNG Internship](https://hng.tech/internship) or [HNG Premium](https://hng.tech/premium). It's an excellent opportunity to gain hands-on experience and learn from industry professionals.

For those looking to hire top tech talent, [HNG Hire](https://hng.tech/hire)  connects you with skilled developers who have undergone rigorous training.

## Conclusion
Automating user and group management tasks with a bash script can significantly improve efficiency and security in a Linux environment. By following the steps outlined in this article, you can streamline your onboarding process and ensure proper user management.