Using a Bash script to Automate the Creation of Users and Groups
Published: 2024-07-02 22:15:53

is a typical responsibility for a DevOps engineer to add, modify, and remove users and groups. Time can be saved and mistakes can be decreased by automating this procedure, particularly when onboarding numerous new developers. This tutorial will guide you through the building of a Bash script that can be used to automatically create users and their groups, create home directories, generate random passwords, and log all activity.

**Goals**

1. Make users and the groups they belong to
2. Users can be added to designated groups. Create home directories and grant the necessary access. Create random passwords and save them safely. 
3. Keep track of every action for auditing needs.

**Requirements**

• Input File: A text file with the format username;group1,group2 that contains usernames and groups. 
• Log File: A file used to keep track of every action. 
• Password File: A file where generated passwords are safely kept.

**Now let's get started.**

A _**"shebang"**_ is the first line that we write at the beginning of every shell script we write; it sounds catchy, doesn't it?

```
#!/bin/bash

```
An executable file is indicated by the existence of a _**shebang**_.

We can now discuss the juicy specifics now that it is out of the way.

**Launching the Script**

The script begins by specifying the locations of the password and log files (you are free to give them any names you choose):

```
LOGFILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.csv"
```
**Check the File Input**

The script determines whether an input file has been supplied as an argument:

```
if [ -z "$1" ]; then
  echo "Usage: $0 <name-of-text-file>"
  exit 1
fi
```
The script exits with a usage message instructing our users on how to utilize our script if no file is supplied.

**Make Password and Log Files**
This little piece of code creates the required files and directories and sets the right permissions:

```
mkdir -p /var/secure
touch $LOGFILE $PASSWORD_FILE
chmod 600 $PASSWORD_FILE
```
We make a directory called "/var/secure/" which will keep our passwords. After that we create the two files that were defined above for logging and saving passwords. Modifying our $PASSWORD_FILE with chmod 600 will ensure that only the user with appropriate permissions can view it(which happens to be the current user we are logged in as).

**Function to Generate Random Passwords**
We will create a function to provide our various users with secure, random passwords.

```
generate_random_password() {
    local length=${1:-10} # Default length is 10 if no argument is provided
    tr -dc 'A-Za-z0-9!?%+=' < /dev/urandom | head -c $length
}
```
The function accepts an argument specifying the desired password length; if none is supplied, it defaults to 10.


- tr -dc 'A-Za-z0-9!?%+=': This command is used to translate and delete characters that are not in the regex A-Za-z0-9!?%+=
- < /dev/urandom: uses the Linux kernel's random number generator and passes the result to the command above.
- | head -c $length: outputs the length of the random string specified.

**Function of Logging**

```
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOGFILE
}
```
logs the message's date and time in the $LOGFILE after receiving an argument.

**Make a User Function**

The function create_user() manages the process of creating users and their groups. Username and groups are the two arguments it requires.

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

  # Add user to specified groupsgroup
  groups_array=($(echo $groups | tr "," "\n"))

  for group in "${groups_array[@]}"; do
    if ! getent group "$group" >/dev/null; then
      groupadd "$group"
      log_message "Created group $group"     
    fi
    usermod -aG "$group" "$username"
    log_message "Added user $username to group $group"
  done

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

  # Generate a random password
  password=$(generate_random_password 12) 
  echo "$username:$password" | chpasswd
  echo "$username,$password" >> $PASSWORD_FILE
  log_message "Set password for user $username"
}
```

**Let's dissect it together.**

- Verifying the Existence of the User

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

Our script logs users if they already exist and then continues; if not, a new user is generated and signed in.

NOTE: In order to prevent it from interfering with our logs, /dev/null is forwarding the response to null.

_**NOTE: Unix handles the creation of personal groups for us when we establish a new user, so we won't be creating them manually for each user.**_

- User Addition to Identified Groups
After that, we continue by adding the users to their respective groups.

```
groups_array=($(echo $groups | tr "," "\n"))
for group in "${groups_array[@]}"; do
  if ! getent group "$group" > /dev/null; then
    groupadd "$group"
    log_message "Created group $group"   
  fi
  usermod -aG "$group" "$username"
  log_message "Added user $username to group $group"
done
```
By using commas, the code sample divides the groups string and stores the pieces in a groups_array variable. Next, it iterates over each group, adding the user and making sure the group is created if it doesn't already exist:

- Creating Permissions for the Home Directory

```
chmod 700 /home/$username
chown $username:$username /home/$username
log_message "Set up home directory for user $username" 
```
chmod 700 /home/$username:: Sets the home directory permissions so only the user has full access (read, write, execute).

chown $username:$username /home/$username: Changes the ownership of the home directory to the specified user and their group.

echo "Set up home directory for user $username" | tee -a $LOGFILE: Logs a message indicating the home directory setup to a specified log file.

- Giving Every User A Random Password

```
password=$(generate_random_password 12) 
echo "$username:$password" | chpasswd
echo "$username,$password" >> $PASSWORD_FILE
log_message "Set password for user $username"
```
This little code generates a new password using the function we previously built, updates the user's password to the produced password, saves the username and password to the $PASSWORD_FILE, and then logs a message confirming the change was successful.

**Examining the Input File**
The script reads the input file line by line, providing the arguments $username and $groups to the create_user() function on each line:

```
while IFS=';' read -r username groups; do
  create_user "$username" "$groups"
done < "$1"
```
**Now, Compile Everything...**

```
#!/bin/bash

# Log file location
LOGFILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.csv"

# Check if the input file is provided
if [ -z "$1" ]; then
  echo "Error: No file was provided"
  echo "Usage: $0 <name-of-text-file>"
  exit 1
fi

# Create log and password files
mkdir -p /var/secure
touch $LOGFILE $PASSWORD_FILE
chmod 600 $PASSWORD_FILE

generate_random_password() {
    local length=${1:-10} # Default length is 10 if no argument is provided
    LC_ALL=C tr -dc 'A-Za-z0-9!?%+=' < /dev/urandom | head -c $length
}

# Function to create a user
create_user() {
  local username=$1
  local groups=$2

  if getent passwd "$username" > /dev/null; then
    echo "User $username already exists" | tee -a $LOGFILE
  else
    useradd -m $username
    echo "Created user $username" | tee -a $LOGFILE
  fi

  # Add user to specified groupsgroup
  groups_array=($(echo $groups | tr "," "\n"))

  for group in "${groups_array[@]}"; do
    if ! getent group "$group" >/dev/null; then
      groupadd "$group"
      echo "Created group $group" | tee -a $LOGFILE      
    fi
    usermod -aG "$group" "$username"
    echo "Added user $username to group $group" | tee -a $LOGFILE
  done

  # Set up home directory permissions
  chmod 700 /home/$username
  chown $username:$username /home/$username
  echo "Set up home directory for user $username" | tee -a $LOGFILE

  # Generate a random password
  password=$(generate_random_password 12) 
  echo "$username:$password" | chpasswd
  echo "$username,$password" >> $PASSWORD_FILE
  echo "Set password for user $username" | tee -a $LOGFILE
}

# Read the input file and create users
while IFS=';' read -r username groups; do
  create_user "$username" "$groups"
done < "$1"

echo "User creation process completed." | tee -a $LOGFILE
```
**In summary**

This script offers a streamlined method for managing the creation of users and groups while making sure that all required actions are taken securely and recorded for audit purposes. SysOps engineers can save time and lower the possibility of mistakes during user onboarding by automating these procedures.

For additional information and to begin your programming career, go to https://hng.tech/internship or https://hng.tech/premium.

Please get in touch if you have any queries or ideas for enhancements. Cheers to automation!