Linux User Creation Bash Script
Published: 2024-07-03 17:26:19

This Bash script automates the creation of user accounts and group memberships in Ubuntu. It takes a text file as input, where each line specifies a username and the groups they should belong to (comma-separated). The script performs the following actions:

- Reads the user and group information from the text file.
- Creates user accounts if they don't already exist.
- Creates groups if they don't already exist.
- Adds users to the specified groups.
- Generates random passwords for each user.
- Sets permissions and ownership for user home directories.
- Logs its actions in a file for reference.
- This script simplifies user and group management, saving time and reducing the risk of errors compared to manual configuration.


 Each User must 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 ";"- Ignore whitespace
e.g.
 Tolu;developer,tester,security



Code Breakdown.

`#!/bin/bash`

Helps the script to run in a bash shell once called.
This shebang! establishes a well-defined environment for the script

 **Defining Variables:**
```bash
logfile="/var/log/user_management.log"

password_file="/var/secure/user_passwords.csv"

text_file=$1
```

The script utilizes variables to store crucial paths and user input. This enhances readability and maintainability. Here's a breakdown of the defined variables:
       

1. `logfile`: This variable holds the path for the log file where the script's actions are recorded. By default, it points to `/var/log/user_management.log`.
2.        `password_file`: This variable stores the path to the password file. This file securely stores usernames and their corresponding randomly generated passwords. The default location is `/var/secure/user_passwords.csv`.
3.        `text_file`: This variable captures the filename provided by the user as the first argument (`$1`). This file is expected to contain a list of usernames and their associated groups, separated by semicolons.

 **Input Validation:**

   The script ensures proper user input by performing validation. It checks if the user has provided the essential text file containing user and group information. Here's the code snippet for this validation:

   ```bash
   if [ -z "$text_file" ]; then
       echo "Error: Usage: $0 <name of text file>"
       exit 1
   fi
   ```

   This block of code checks if the `text_file` variable is empty.
   - If the file is missing, an error message is displayed, informing the user of the correct usage (`echo`).
   - The script exits with an error code (`exit 1`) to indicate an issue with the input.


## File Management: Creating Essential Files

 **Creating Directories:**

   - The script employs the `mkdir -p` command to create the directory structure for the password file if it doesn't already exist. This ensures the script doesn't encounter errors due to missing directories. The `-p` flag in `mkdir` instructs it to create parent directories if necessary.

 **Creating Log and Password Files:**

   - The `touch` command is used to create the log file (`$logfile`) and password file (`$password_file`). This establishes empty files for the script to record its actions and store passwords.

 **Setting Permissions:**

   - The script prioritizes security by setting strict permissions (600) for the password file using `chmod 600 "$password_file"`. This restricts access to the file, allowing only the owner to read and write to it. This prevents unauthorized access to sensitive password information.




## Building Users and Groups: The actual automation section 

 **`generate_random_password`**

   - This function generates a secure and random password for each user. 
      ```bash
      function generate_random_password() {
          local length=${1:-10}  # Default length of 10 characters
          tr -dc 'A-Za-z0-9!?%+=' < /dev/urandom | head -c "$length"
      }
      ```
      - The function leverages `/dev/urandom` to access a cryptographically secure random number generator.
      - It utilizes the `tr` command for character filtering. This ensures the password includes alphanumeric characters, special symbols (`!?%+=`), and avoids potential issues with spaces in passwords.
      - Finally, `head -c "$length"` extracts the desired number of characters to form the random password.

 **`log_message` Function**

   - This function simplifies logging by appending a timestamp and the script filename (`$text_file`) to the log file (`$logfile`). Here's the code:
      ```bash
      function log_message() {
          echo "$(date '+%Y-%m-%d %H:%M:%S') - $text_file" >> "$logfile"
      }
      ```
      - The `date` command with the `'+%Y-%m-%d %H:%M:%S'` format generates a timestamp for each log message.
      - The entire message is then appended to the log file using `echo >>`.

 **`create_user` Function and User Creation **

   - This function handles user creation based on the user information in the text file. Here's a breakdown:
      ```bash
      function create_user() {
          local username="$1"
          local groups="$2"

          if getent passwd "$username" > /dev/null; 
      then
              log_message "User $username already exists"
          else
              useradd -m "$username"
              log_message "Created user $username"
          fi
      }
      ```
      - It takes two arguments: `username` and `groups` (comma-separated list).
      - The function first checks if the user already exists using `getent passwd "$username" > /dev/null`. If the command exits successfully, it means the user exists.
      - If the user doesn't exist:
          - The script creates the user's home directory with `useradd -m "$username"`. The `-m` flag instructs `useradd` to create a home directory for the user.
          - A success message regarding user creation is logged using `log_message`.
      - Otherwise, a message indicating the user already exists is logged.

 **Group Management and User-Group Associations**

   - The script iterates through each line in the text file, processing users and their assigned groups. Here's the process:
      

```
      while IFS=';' read -r username groups; do
          create_user "$username" "$groups"

          groups_array=($(echo $groups | tr "," "\n"))

          for group in "${groups_array[@]}";

         do

          if ! getent group "$group" > /dev/null; 

   then

  groupadd "$group"

  log_message "Group created $group"

  else

  log_message "Group $group already exists"

  fi

  usermod -aG "$group" "$username"

  log_message "Added user $username to group $group"

done
```
      - A `while` loop iterates through each line in the `text_file` 
          - Inside the loop:
              - The `create_user` function is called to create the user (already described earlier).
              - The comma-separated groups are split into an array (`groups_array`) using `tr` for easier processing.
              - Another loop iterates through each group in the `groups_array`.
                  - It checks if the group exists using `getent group "$group" > /dev/null`.
    `getend` is a command used to request file from database in the CLI



##  Security Home and Password Assignment:
security and finalizing the user setup:

 **Home Directory Permissions**

   - The script prioritizes security by setting appropriate permissions for each user's home directory. Here's the code:
      ```bash
      chmod 700 "/home/$username"
      chown "$username:$username" "/home/$username"
      log_message "Set up home directory for user $username"
      ```
      - The script restricts access to the user's home directory by setting permissions to 700 with `chmod 700 "/home/$username"`. This grants read, write, and execute permissions only to the owner (the user).
      - Ownership of the home directory is then transferred to the user with `chown "$username:$username" "/home/$username"`. This ensures the user has full control over their home directory and its contents.
      - A success message regarding home directory setup is logged.

 **Password Assignment**

   - The script assigns a unique and secure password to each user. Here's the process:
      ```bash
      password=$(generate_random_password   # Generate 10-character password
      echo "$username:$password" | chpasswd
      echo "$username,$password" >> "$password_file"
      log_message "Set password for $username"
      ```
      - It utilizes the `generate_random_password` function (described earlier) to create a 10-character random password for each user.
      - The username and password are combined (`"$username:$password"`) and used with `chpasswd` to set the password for the user.
      - The script then stores both the username and the randomly generated password in the secure password file (`"$password_file"`) for reference.
      - Finally, a success message regarding password assignment is logged.

**Bringing it All Together:**

```
#!/bin/bash

#Log file and password location
logfile="/var/log/user_management.log"
password_file="/var/secure/user_passwords.csv"
text_file=$1

#check for file input
if [ -z "$text_file" ]
then
echo "Usage is: $0 <name of text file>"
exit 1
fi

#Create Log file and password files
mkdir -p /var/secure
touch $logfile $password_file
chmod 600 $password_file

#function to generate randompasswords
generate_random_password() {
  local length=${1:-10}
  tr -dc 'A-Za-z0-9!?%+=' < /dev/urandom | head -c $length
}

log_message() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') - $text_file" >> $logfile
}

#FUNCTION TO CREATE USER
create_user() {
local username=$1
local groups=$2

if getent passwd "$username" > /dev/null;
then
 log_message "User $username already exists"
else
  useradd -m $username
  log_message "Created  user $username"
fi

#Adding user to groups
groups_array=($(echo $groups | tr "," "\n"))
for group in "${groups_array[@]}";
do
  if ! getent group "$group" > /dev/null; 
then
  groupadd "$group"
  log_message "Group created $group"
  else
  log_message "Group $group already exists"
  fi
  usermod -aG "$group" "$username"
  log_message "Added user $username to group $group"
done

chmod 700 /home/$username
chown $username:$username /home/$username
log_message "Set up home directory for user $username"

#Assigning Random password to users
password=$(generate_random_password 12)
echo "$username:$password" | chpasswd
echo "$username,$password" >> $password_file
log_message "Set password for $username"
}

while IFS=';' read -r username groups;
do
  create_user "$username" "$groups"
  done < "$text_file"

echo "User creation done." | tee -a $logfile
```


By combining these steps, the script automates the creation of user accounts, assigns them to designated groups, ensures secure home directory permissions, and provides a record of usernames and randomly generated passwords. This script streamlines user and group management, saving time and effort while promoting security best practices.

To learn more and push your programming journey  forward you can visit:
https://hng.tech/internship or https://hng.tech/hire

I am open to receiving comments with questions or suggestions that improves the script. Cheers!

[Link to github repo](https://github.com/Toluwanee/linux-user-creation-bash-script.git)