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

## Introduction
Managing users and groups on a Linux system can be a daunting task, especially when onboarding new employees. As a SysOps engineer, automating these tasks can save time and reduce errors. In this article, we'll explore 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, broken down into detailed code blocks for better understanding.

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"
}

```

- Purpose: This function reads the input file line by line.

- Parsing: Each line is split into user and groups using the semicolon (;) as a delimiter.

- Trim Whitespace: The xargs command removes any leading or trailing whitespace from user, and tr -d '[:space:]' removes all spaces from groups.

- Storing Data: Usernames are stored in the users array and group lists in the group_list array.

Creating a User with a Personal Group
Next, we define a function to create a user and their personal group. If the user already exists, the script logs a message and skips the creation.

```
# Function to create a user with its personal 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
}

```

- Check Existence: The id command checks if the user already exists. If they do, a message is logged.

- Create Group: If the user does not exist, the script creates a new group with the same name as the username using groupadd.

- Create User: The useradd command creates a new user with:
      -m: Creates a home directory for the user.
      -g "$username": Assigns the user to their personal group.
      -s /bin/bash: Sets the default shell to /bin/bash.

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"
}

```

- Generate Password: The openssl rand -base64 12 command generates a random 12-character password.

- Set Password: The chpasswd command sets the user's password.

- Store Password: The username and password are appended to the password file for future reference.

- Logging: A message is logged indicating that the password was set and stored.

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 user 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
}

```

- Split Groups: The IFS=',' setting and read -r -a groups <<< "$2" command split the group list into an array.

- Check Group Existence: The getent group "$group" command checks if each group exists.

- Create Group: If a group does not exist, it is created using groupadd.

- Add User to Group: The usermod -aG "$group" "$username" command adds the user to each group.

- Logging: Messages are logged for group creation and user addition.

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 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"

```

- Input File Argument: Checks if an input file is provided as an argument. If not, it exits with a usage message.

- Initialize Variables: Sets the input file, log file, and password file paths. Initializes arrays for users and groups.

- Create Log and Password Files: Creates the log and password files if they do not exist and sets appropriate permissions.

- Read Input File: Calls the read_input_file function to populate the users and group_list arrays.

- Process Users: Loops through each user in the users array:
        Skip Empty Usernames: Continues to the next iteration if the 
    username is empty.
        Create User and Group: Calls create_user_with_group to 
    create the user and their personal group.
        Set Password: Calls set_user_password to set and store the 
    user's password.
        Add to Groups: Calls add_user_to_groups to add the user to 
    specified groups.

- Completion Message: Logs a message indicating that user creation and group assignment are complete.

## 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

```

- 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 up 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.