<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ugochukwu Elekwachi</title>
    <description>The latest articles on DEV Community by Ugochukwu Elekwachi (@vale_hash).</description>
    <link>https://dev.to/vale_hash</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1711821%2F3e8494e4-c05c-427f-b755-76f6eb5f2802.jpg</url>
      <title>DEV Community: Ugochukwu Elekwachi</title>
      <link>https://dev.to/vale_hash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vale_hash"/>
    <language>en</language>
    <item>
      <title>Creating users and groups from a file with bash.</title>
      <dc:creator>Ugochukwu Elekwachi</dc:creator>
      <pubDate>Mon, 01 Jul 2024 22:07:27 +0000</pubDate>
      <link>https://dev.to/vale_hash/creating-users-and-groups-from-a-file-with-bash-1jf1</link>
      <guid>https://dev.to/vale_hash/creating-users-and-groups-from-a-file-with-bash-1jf1</guid>
      <description>&lt;p&gt;As a devops engineer creating users and managing them is one of the primary responsibilities as a devops engineer or sysadmin.&lt;/p&gt;

&lt;p&gt;Today we will be creating a bash script that :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Reads a text file containing the employee’s usernames and group names, where each line is formatted as user;groups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;create users and groups as specified&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;set up home directories with appropriate permissions and ownership&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;generate random passwords for the users&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;log all actions to /var/log/user_management.log&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Additionally, store the generated passwords securely in /var/secure/user_passwords.txt&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without further ado let's get started.&lt;/p&gt;

&lt;p&gt;Firstly lets create the file create_user.sh using the &lt;code&gt;touch&lt;/code&gt; command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;touch create_user.sh&lt;/code&gt;&lt;br&gt;
we want to first add our shebang &lt;code&gt;#!/bin/bash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we an start ticking off some of the requirements.&lt;/p&gt;

&lt;p&gt;requirement 5 specifically, let us create the user_management.log file&lt;/p&gt;
&lt;h4&gt;
  
  
  Creating the required log and txt files
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [[ ! -e /var/log/user_management.log ]]; then
    sudo mkdir -p /var/log/
    sudo touch /var/log/user_management.log
fi

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;analyzing the above code: we check if the fire /var/log/user_management.log exist, if it does not we &lt;/p&gt;

&lt;p&gt;create the directory /var/log/ with mkdir and the -p flag for persistence, then we create the file user_management.log using &lt;code&gt;touch&lt;/code&gt;  and then end the if statement using fi.&lt;/p&gt;

&lt;p&gt;lets do the same for the file that all the passwords will be saved in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [[ ! -e /var/secure/user_passwords.txt ]]; then
    sudo mkdir -p /var/secure/
    sudo touch /var/secure/user_passwords.txt
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;/var/secure/user_passwords.txt and /var/log/user_management.log is difficult to type and a mouthful to say so we'll assign the to variables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;log_file="/var/log/user_management.log"
pass_file="/var/secure/user_passwords.txt"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and now we can start sending outputs of all that is going on to our logfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "logfile created..." &amp;gt;&amp;gt; $log_file

echo "checking if text_file exists" &amp;gt;&amp;gt; $log_file

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;checking if a text file containing the users and groups have been passed&lt;/p&gt;

&lt;h4&gt;
  
  
  Confirming a file was passed as an argument
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [[ -z "$1" ]]; then
    echo "Usage: $0 filename"
    echo "Text file does not exist. ...exiting" &amp;gt;&amp;gt; $log_file
    exit 1
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code snippet checks if there is user_input from the terminal&lt;br&gt;
and if there is not it sends a text to the log file and the program ends.&lt;/p&gt;

&lt;p&gt;However assuming there is a file passed/user_input made in the terminal&lt;/p&gt;
&lt;h4&gt;
  
  
  Reading the file
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Reading file" &amp;gt;&amp;gt; $log_file

file_path="$1"
if [[ -f "$file_path" ]]; then
    echo "fetching the usernames and groups" &amp;gt;&amp;gt; $log_file
    while IFS= read -r lines; do
              user_name=$(echo "$lines" | awk -F'; ' '{print $1}')
        groups=$(echo "$lines" | awk -F'; ' '{print $2}')


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above code opens up the file and starts to read from it,&lt;/p&gt;
&lt;h4&gt;
  
  
  Fetching the usernames and groups
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;While IFS = read -r lines; do
    user_name=$(echo "$lines" | awk -F'; ' '{print $1}')
    groups=$(echo "$lines" | awk -F'; ' '{print $2}')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above snippet basically says while there are lines in the file i.e the code has not traveled to the end of the file, we then assign user_name to the $lines being piped through awk and the delimiter '; ' to separate the line&lt;/p&gt;

&lt;p&gt;basically,&lt;br&gt;
we have a line vale; sudo, vale, data&lt;br&gt;
when we pipe it into  &lt;code&gt;awk -F'; ' '{print $1}'&lt;/code&gt; it splits the line into tow parts which are &lt;code&gt;vale&lt;/code&gt; and  &lt;code&gt;sudo, vale, data&lt;/code&gt; and {print $1} let's us access the first part of the line before the delimiter. while the line below does the same thing but {print $2} gives us access to the second part of the line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file_path="$1"
if [[ -f "$file_path" ]]; then
    echo "fetching the usernames and groups" &amp;gt;&amp;gt; $log_file
    while IFS= read -r lines; do
        user_name=$(echo "$lines" | awk -F'; ' '{print $1}')
        groups=$(echo "$lines" | awk -F'; ' '{print $2}')

        if id -u "$user_name"&amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
            echo "user $user_name already exists"
            echo "user $user_name already exists" &amp;gt;&amp;gt; $log_file
        else
            IFS=',' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups" #explain in the post
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now that we have access to the users we can check if a user already exist, to do that we simply check if a user has an id, if the name already has an id it exist and we simply make it known to the user that the user_name has been created already&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        if id -u "$user_name"&amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
            echo "user $user_name already exists"
            echo "user $user_name already exists" &amp;gt;&amp;gt; $log_file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  checking if user already exists
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;id -u "$user_name"&lt;/code&gt; is used to get the id of a user and &lt;code&gt;&amp;gt;dev/null 2&amp;gt;&amp;amp;1&lt;/code&gt; is used to send the output to a null file so no output is displayed&lt;/p&gt;

&lt;p&gt;&lt;code&gt;else&lt;br&gt;
            IFS=',' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups"&lt;/code&gt; is used to read the elements in groups and put them into an array group_array where the elements are split by the ',' delimiter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file_path="$1"
if [[ -f "$file_path" ]]; then
    echo "fetching the usernames and groups" &amp;gt;&amp;gt; $log_file
    while IFS= read -r lines; do
        user_name=$(echo "$lines" | awk -F'; ' '{print $1}')
        groups=$(echo "$lines" | awk -F'; ' '{print $2}')

        if id -u "$user_name"&amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
            echo "user $user_name already exists"
            echo "user $user_name already exists" &amp;gt;&amp;gt; $log_file
        else
            IFS=',' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups" #explain in the post
            for group in "${group_array[@]}"; do
                if ! getent group "$group" &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
                    sudo groupadd "$group"
                    echo "Group $group created"

                    echo "Group $group created" &amp;gt;&amp;gt; $log_file
                fi
            done


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Group creation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for group in "${group_array[@]}"; do
                if ! getent group "$group" &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then
                    sudo groupadd "$group"
                    echo "Group $group created"

                    echo "Group $group created" &amp;gt;&amp;gt; $log_file
                fi
            done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lets break down the above block of code :&lt;br&gt;
&lt;code&gt;for group in "{$group_array[@]};&lt;/code&gt; this creates a variable group that is equal to the current item in the group array that was created before and it keeps on changing according to the number of elements in that group &lt;br&gt;
&lt;code&gt;do&lt;br&gt;
                if ! getent group "$group" &amp;gt;/dev/null 2&amp;gt;&amp;amp;1;&lt;/code&gt; remember when we wanted to find out if a user exists or not? This is basically the same thing but instead of a user we use the getent function to get entities that belong to a particular group and if no entity belongs to a particular group the group most likely does not exists so we pipe the output to the null folder and create the group.&lt;/p&gt;
&lt;h3&gt;
  
  
  password creation
&lt;/h3&gt;

&lt;p&gt;we can generate a random password using openssl&lt;/p&gt;

&lt;p&gt;&lt;code&gt;password=$(openssl rand -base64 12)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This creates a variable password which would have a 12 digit password in base 64&lt;/p&gt;
&lt;h4&gt;
  
  
  creating users with their assigned group and passwords
&lt;/h4&gt;

&lt;p&gt;luckily someone asked this question on stackoverflow and got a response &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flrtsrf7veedr5z5rriyx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flrtsrf7veedr5z5rriyx.png" alt="Image description" width="658" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you very much Netzego and Damien&lt;br&gt;
sudo useradd -m -G "$groups" -p "$(openssl passwd -1 "$password")" "$user_name"&lt;/p&gt;

&lt;p&gt;echo "adding groups :$groups for user: $user_name and password in $pass_file " &amp;gt;&amp;gt; $log_file&lt;br&gt;
group_fold="/home/$user_name"&lt;/p&gt;

&lt;p&gt;so far we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file_path="$1"
if [[ -f "$file_path" ]]; then
    echo "fetching the usernames and groups" &amp;gt;&amp;gt; $log_file
    while IFS= read -r lines; do
        user_name=$(echo "$lines" | awk -F'; ' '{print $1}') #explain in the post
        groups=$(echo "$lines" | awk -F'; ' '{print $2}')

        if id -u "$user_name"&amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then #explain in the post
            echo "user $user_name already exists"
            echo "user $user_name already exists" &amp;gt;&amp;gt; $log_file
        else
            IFS=',' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups" #explain in the post
            for group in "${group_array[@]}"; do
                if ! getent group "$group" &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then #explain in the post
                    sudo groupadd "$group"
                    echo "Group $group created"

                    echo "Group $group created" &amp;gt;&amp;gt; $log_file
                fi
            done

            password=$(openssl rand -base64 12)


            sudo useradd -m -G "$groups" -p "$(openssl passwd -1 "$password")" "$user_name" #explain in post
            echo "adding groups :$groups for user: $user_name and password in $pass_file " &amp;gt;&amp;gt; $log_file
            group_fold="/home/$user_name"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now we just have to create the users home folders with the appropriate permissions and groups&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chmod 700 $group_fold &amp;gt; $log_file 2&amp;gt;&amp;amp;1
            sudo chown $user_name:$user_name $group_fold &amp;gt; $log_file 2&amp;gt;&amp;amp;1

            echo "Home directory for $user set up with appropriate permissions and ownership" &amp;gt;&amp;gt; $log_file

            echo "$user_name,$password" &amp;gt;&amp;gt; "$pass_file"
        fi
    done &amp;lt; "$file_path"
    sudo chmod 600 "$password_file"
        sudo chown "$(id -u):$(id -g)" "$password_file"
        echo "File permissions for $password_file set to owner-only read" &amp;gt;&amp;gt; $log_file
else
    echo "File not found: $file_path" &amp;gt;&amp;gt; "$log_file"
    exit 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The  complete code:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

if [[ ! -e /var/log/user_management.log ]]; then
    sudo mkdir -p /var/log/
    sudo touch /var/log/user_management.log
fi

if [[ ! -e /var/secure/user_passwords.txt ]]; then
    sudo mkdir -p /var/secure/
    sudo touch /var/secure/user_passwords.txt
fi

log_file="/var/log/user_management.log"
pass_file="/var/secure/user_passwords.txt"

echo "logfile created..." &amp;gt;&amp;gt; $log_file
echo "checking if text_file exists" &amp;gt;&amp;gt; $log_file

if [[ -z "$1" ]]; then
    echo "Usage: $0 filename"
    echo "Text file does not exist. ...exiting" &amp;gt;&amp;gt; $log_file
    exit 1
fi

echo "Reading file" &amp;gt;&amp;gt; $log_file

file_path="$1"
if [[ -f "$file_path" ]]; then
    echo "fetching the usernames and groups" &amp;gt;&amp;gt; $log_file
    while IFS= read -r lines; do
        user_name=$(echo "$lines" | awk -F'; ' '{print $1}') #explain in the post
        groups=$(echo "$lines" | awk -F'; ' '{print $2}')

        if id -u "$user_name"&amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then #explain in the post
            echo "user $user_name already exists"
            echo "user $user_name already exists" &amp;gt;&amp;gt; $log_file
        else
            IFS=',' read -ra group_array &amp;lt;&amp;lt;&amp;lt; "$groups" #explain in the post
            for group in "${group_array[@]}"; do
                if ! getent group "$group" &amp;gt;/dev/null 2&amp;gt;&amp;amp;1; then #explain in the post
                    sudo groupadd "$group"
                    echo "Group $group created"

                    echo "Group $group created" &amp;gt;&amp;gt; $log_file
                fi
            done

            password=$(openssl rand -base64 12)


            sudo useradd -m -G "$groups" -p "$(openssl passwd -1 "$password")" "$user_name" #explain in post
            echo "adding groups :$groups for user: $user_name and password in $pass_file " &amp;gt;&amp;gt; $log_file
            group_fold="/home/$user_name"

            sudo chmod 700 $group_fold &amp;gt; $log_file 2&amp;gt;&amp;amp;1
            sudo chown $user_name:$user_name $group_fold &amp;gt; $log_file 2&amp;gt;&amp;amp;1

            echo "Home directory for $user set up with appropriate permissions and ownership" &amp;gt;&amp;gt; $log_file

            echo "$user_name,$password" &amp;gt;&amp;gt; "$pass_file"
        fi
    done &amp;lt; "$file_path"
    sudo chmod 600 "$password_file"
        sudo chown "$(id -u):$(id -g)" "$password_file"
        echo "File permissions for $password_file set to owner-only read" &amp;gt;&amp;gt; $log_file
else
    echo "File not found: $file_path" &amp;gt;&amp;gt; "$log_file"
    exit 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This task was assigned to me during my &lt;a href="https://hng.tech/internship"&gt;HNG&lt;/a&gt; internship devops track&lt;/p&gt;

</description>
      <category>hng</category>
      <category>sysadmin</category>
      <category>bash</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
