<?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: Ekemini Udongwo</title>
    <description>The latest articles on DEV Community by Ekemini Udongwo (@kemzzydev).</description>
    <link>https://dev.to/kemzzydev</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%2F1179498%2F04637811-12f6-430f-88ae-688610616a22.jpeg</url>
      <title>DEV Community: Ekemini Udongwo</title>
      <link>https://dev.to/kemzzydev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kemzzydev"/>
    <language>en</language>
    <item>
      <title>Implementing an On-Demand Video Streaming Platform on AWS Using Terraform</title>
      <dc:creator>Ekemini Udongwo</dc:creator>
      <pubDate>Tue, 29 Oct 2024 08:06:25 +0000</pubDate>
      <link>https://dev.to/kemzzydev/hosting-an-on-demand-streaming-site-on-aws-with-terraform-1m2j</link>
      <guid>https://dev.to/kemzzydev/hosting-an-on-demand-streaming-site-on-aws-with-terraform-1m2j</guid>
      <description>&lt;p&gt;In this project, we will deploy an on-demand video streaming platform utilizing AWS services and infrastructure automation with Terraform. The solution will incorporate AWS Route 53 for DNS management, CloudFront as a Content Delivery Network (CDN) to optimize content delivery, AWS Certificate Manager for SSL certificates, and Amazon S3 for video file storage. The following diagram outlines the infrastructure architecture that will be implemented.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Prerequisites:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Domain name&lt;/li&gt;
&lt;li&gt;Knowledge of Terraform &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note: Before we move forward, make sure you have Terraform set up on your local machine, including the necessary provider, and that you’ve initialized your project. If you’re all set, let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Register a domain on route53
&lt;/h2&gt;

&lt;p&gt;First, log into the AWS Management Console and head over to the Route 53 service. From there, find the “Registered Domains” section and click on “Register Domain.” &lt;br&gt;
Type in the domain name you want and check its availability. If it’s available, just fill in your details, and AWS will email you a verification link. Once verified, your new domain should be ready within a few minutes to an hour.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Create some variables
&lt;/h2&gt;

&lt;p&gt;Let's create a &lt;strong&gt;&lt;em&gt;vars.tf&lt;/em&gt;&lt;/strong&gt; file and add some variables to it which will be used by other resources.&lt;/p&gt;
&lt;h3&gt;
  
  
  vars.tf
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "domain" {
  type    = string
  default = "your-domain.com"
}

variable "cloudfront_priceClass" {
  type = string
  default = "PriceClass_100"
}

variable "environment" {
  type = string
  default = "dev"
}

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

&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Create the S3 bucket
&lt;/h2&gt;

&lt;p&gt;Next, we need to create an S3 bucket to store our video or videos we wanna serve to our users. In your text editor, create a &lt;em&gt;&lt;strong&gt;S3.tf&lt;/strong&gt;&lt;/em&gt; file where our S3 configuration is going to be written.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create an S3 bucket
resource "aws_s3_bucket" "video_bucket" {
  bucket = "kemzzy-new-video-bucket"

  tags = {
    Name = "Video bucket"
  }
}

# Enable versioning
resource "aws_s3_bucket_versioning" "video_bucket_versioning" {
  bucket = aws_s3_bucket.video_bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates our bucket and also enables versioning on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Upload a video to the S3 bucket
&lt;/h2&gt;

&lt;p&gt;Next we upload our video to the created S3 bucket&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# replace with the path to the video you want to upload
resource "aws_s3_object" "new_video" {
  bucket       = aws_s3_bucket.video_bucket.id
  key          = "awesome-video"
  source       = "path-to-your-video-file"
  etag         = filemd5("path-to-your-video-file")
  content_type = "video/mp4"

  depends_on = [aws_s3_bucket.video_bucket]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;make sure to upload a mp4 video format otherwise you might have an issue (Speaking from personal experience )&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Create and verify a SSL certificate with ACM
&lt;/h2&gt;

&lt;p&gt;In other to use our domain with cloudfront we need a domain with SSL enabled. You can use the following terraform config to create and validate your SSL certificate for your domain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Create an ACM certificate
resource "aws_acm_certificate" "video_cert" {
  domain_name               = var.domain
  validation_method         = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}

# Cert validation
resource "aws_acm_certificate_validation" "validate_cert" {
  certificate_arn         = aws_acm_certificate.video_cert.arn
  validation_record_fqdns = [for record in aws_route53_record.certificate_validation : record.fqdn]

  depends_on = [ aws_route53_record.certificate_validation ]
}

# create a record to use for validation
resource "aws_route53_record" "certificate_validation" {
  for_each = {
    for dvo in aws_acm_certificate.video_cert.domain_validation_options : dvo.domain_name =&amp;gt; {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = aws_route53_zone.primary.zone_id

  depends_on = [ aws_acm_certificate.video_cert ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Create a CloudFront origin access identity
&lt;/h2&gt;

&lt;p&gt;Now we can proceed to create our OAI for our cloudfront distribution. Create another file called &lt;strong&gt;&lt;em&gt;main.tf&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_cloudfront_origin_access_identity" "cloudfront_OAI" {
  comment = "OAI for video streaming S3 bucket"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, now that we’ve tackled that part, let’s move on to creating our CloudFront distribution!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_cloudfront_distribution" "s3_distribution" {
  origin {
    domain_name = aws_s3_bucket.video_bucket.bucket_regional_domain_name
    origin_id   = aws_s3_bucket.video_bucket.id

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.cloudfront_OAI.cloudfront_access_identity_path
    }
  }

  enabled         = true
  is_ipv6_enabled = true
  comment         = "play video"

  aliases = [var.subdomain]


  default_cache_behavior {
    allowed_methods  = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = aws_s3_bucket.video_bucket.id

    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "allow-all"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }

  price_class =var.cloudfront_priceClass

  restrictions {
    geo_restriction {
      restriction_type = "none"
      locations        = []
    }
  }

  tags = {
    Environment = var.environment
  }

  viewer_certificate {
    acm_certificate_arn = data.aws_acm_certificate.cert.arn
    ssl_support_method  = "sni-only"

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Access the video through the CloudFront distribution
&lt;/h2&gt;

&lt;p&gt;To set this up, we’ll create a bucket policy that restricts read access exclusively to our CloudFront service. This setup adds a layer of security by making sure users can only access content through CloudFront, not directly from the bucket. Simply add this policy to your *&lt;em&gt;s3.tf *&lt;/em&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Bucket policy to allow read access from CloudFront and prevent direct access to our bucket
resource "aws_s3_bucket_policy" "video_stream" {
  bucket = aws_s3_bucket.video_bucket.id
  policy = &amp;lt;&amp;lt;POLICY
  {
    "Version": "2012-10-17",
    "Statement": [
         {
            "Sid": "AllowLegacyOAIReadOnly",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${aws_cloudfront_origin_access_identity.cloudfront_OAI.id}"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::${aws_s3_bucket.video_bucket.bucket}/*"
        }
      ]
  }
  POLICY
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Create an outputs file to get your outputs (optional)
&lt;/h2&gt;

&lt;p&gt;Create an output.tf file and add these outputs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output "cloudfront_url" {
  value = aws_cloudfront_distribution.s3_distribution.domain_name
}

output "domain_url" {
  value = aws_route53_record.video_subdomain.name
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Deploy your infrastructure
&lt;/h2&gt;

&lt;p&gt;Phew! That was a journey, but you’ve made it to the finish line. Now, it’s time to bring your project to life! Run &lt;code&gt;terraform validate&lt;/code&gt; to check for any issues, then use &lt;code&gt;terraform plan -out="tfplan"&lt;/code&gt; to generate a plan, and finally, &lt;code&gt;terraform apply "tfplan"&lt;/code&gt; to deploy your infrastructure to AWS. &lt;/p&gt;

&lt;p&gt;Now, to watch the video, just use your domain name, like &lt;em&gt;your-domain.com/awesome-video&lt;/em&gt;, or the CloudFront URL provided in the output. Enjoy!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations on completing this tutorial. Make sure your you run &lt;code&gt;terraform destroy&lt;/code&gt; when you are done to avoid accumulating any bills.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automating User and Group Creation with a Bash Script</title>
      <dc:creator>Ekemini Udongwo</dc:creator>
      <pubDate>Mon, 01 Jul 2024 14:42:38 +0000</pubDate>
      <link>https://dev.to/kemzzydev/automating-user-and-group-creation-with-a-bash-script-1c0f</link>
      <guid>https://dev.to/kemzzydev/automating-user-and-group-creation-with-a-bash-script-1c0f</guid>
      <description>&lt;p&gt;As a DevOps engineer, it is quite a common task to create, update and delete users and groups. Automating this process can save time and reduce errors, especially when onboarding multiple new developers. In this article, we'll walk through a Bash script designed to automate the creation of users and their respective groups, set up home directories, generate random passwords, and log all actions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Objectives&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create users and their personal groups.&lt;br&gt;
Add users to specified groups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up home directories with appropriate permissions.&lt;br&gt;
Generate and securely store random passwords.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log all actions for auditing purposes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input File: A text file containing usernames and groups, formatted as username;group1,group2.&lt;/li&gt;
&lt;li&gt;Log File: A log file to record all actions.&lt;/li&gt;
&lt;li&gt;Password File: A file to securely store generated passwords.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let's Begin
&lt;/h2&gt;

&lt;p&gt;First and foremost, at the beginning of any shell script we're writing, we start the first line with a line called a &lt;strong&gt;"shebang"&lt;/strong&gt;, sounds catchy right?&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The presence of a &lt;strong&gt;shebang&lt;/strong&gt; indicates that a file is executable. &lt;/p&gt;

&lt;p&gt;Now that that is out of the way we can move on to the juicy details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Script Initialization
&lt;/h2&gt;

&lt;p&gt;The script starts by defining the locations of the log file and the password file(you can name these file whatever you want, ):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LOGFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/log/user_management.log"&lt;/span&gt;
&lt;span class="nv"&gt;PASSWORD_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/secure/user_passwords.csv"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Check File Input
&lt;/h2&gt;

&lt;p&gt;The script checks if an input file is provided as an argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;name-of-text-file&amp;gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If no file is provided, the script exits with a usage message, telling our users how to use our script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Log and Password Files
&lt;/h2&gt;

&lt;p&gt;This code snippet creates the necessary directories and files, setting appropriate permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/secure
&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt; &lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 &lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;code&gt;chmod 600&lt;/code&gt; will ensure that only the user with appropriate permissions can view it(which happens to be the current user we are logged in as).&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate Random Password Function
&lt;/h2&gt;

&lt;p&gt;We're gonna write a function to generate some random and secure passwords for our different users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;generate_random_password&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;10&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="c"&gt;# Default length is 10 if no argument is provided&lt;/span&gt;
    &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-dc&lt;/span&gt; &lt;span class="s1"&gt;'A-Za-z0-9!?%+='&lt;/span&gt; &amp;lt; /dev/urandom | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$length&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function takes an argument which is how long you want the passwords to be, if none is passed, it defaults to 10.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Logging Function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;log_message&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="s1"&gt;'+%Y-%m-%d %H:%M:%S'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Takes an argument and logs the date and time of the message in the $LOGFILE&lt;/p&gt;

&lt;h2&gt;
  
  
  Create User Function
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;create_user()&lt;/code&gt; function handles the creation of users and their groups. It takes two arguments: username and groups.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;create_user&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
  &lt;span class="nb"&gt;local groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;getent passwd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log_message &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; already exists"&lt;/span&gt;
  &lt;span class="k"&gt;else
    &lt;/span&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"Created user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;

  &lt;span class="c"&gt;# Add user to specified groupsgroup&lt;/span&gt;
  &lt;span class="nv"&gt;groups_array&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$groups&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s2"&gt;","&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;group &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;groups_array&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      log_message &lt;span class="s2"&gt;"Created group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;     
    &lt;span class="k"&gt;fi
    &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"Added user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;done&lt;/span&gt;

  &lt;span class="c"&gt;# Set up home directory permissions&lt;/span&gt;
  &lt;span class="nb"&gt;chmod &lt;/span&gt;700 /home/&lt;span class="nv"&gt;$username&lt;/span&gt;
  &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;:&lt;span class="nv"&gt;$username&lt;/span&gt; /home/&lt;span class="nv"&gt;$username&lt;/span&gt;
  log_message &lt;span class="s2"&gt;"Set up home directory for user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 

  &lt;span class="c"&gt;# Generate a random password&lt;/span&gt;
  &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;generate_random_password 12&lt;span class="si"&gt;)&lt;/span&gt; 
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | chpasswd
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;
  log_message &lt;span class="s2"&gt;"Set password for user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Let's break it down.....
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Checking if User Already Exists&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;log_message &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; already exists"&lt;/span&gt;
&lt;span class="k"&gt;else
  &lt;/span&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;
  log_message &lt;span class="s2"&gt;"Created user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a user exists our script logs it and moves on else the user is created and then logged.&lt;/p&gt;

&lt;p&gt;NOTE: &lt;code&gt;&amp;gt; /dev/null&lt;/code&gt; is passing the response to null so that it doesn't interfere with our logs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE: We are not going to create a personal group for each user because unix does this for us automatically when we create a new user&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Adding User to Specified Groups&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We then proceed to add the users to their different groups&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;groups_array&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$groups&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s2"&gt;","&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;group &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;groups_array&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    log_message &lt;span class="s2"&gt;"Created group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;   
  &lt;span class="k"&gt;fi
  &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  log_message &lt;span class="s2"&gt;"Added user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code snippet splits the groups string by commas and saves them in a groups_array variable. It then loops through each group and adds the user to it, also making sure to create the group if it doesn't exist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setting Up Home Directory Permissions&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;700 /home/&lt;span class="nv"&gt;$username&lt;/span&gt;
&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;:&lt;span class="nv"&gt;$username&lt;/span&gt; /home/&lt;span class="nv"&gt;$username&lt;/span&gt;
log_message &lt;span class="s2"&gt;"Set up home directory for user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;chmod 700 /home/$username:&lt;/code&gt;: Sets the home directory permissions so only the user has full access (read, write, execute).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;chown $username:$username /home/$username&lt;/code&gt;: Changes the ownership of the home directory to the specified user and their group.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;echo "Set up home directory for user $username" | tee -a $LOGFILE&lt;/code&gt;: Logs a message indicating the home directory setup to a specified log file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assigning A Random Password To Each User&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;generate_random_password 12&lt;span class="si"&gt;)&lt;/span&gt; 
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | chpasswd
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;
log_message &lt;span class="s2"&gt;"Set password for user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This snippet uses the function we wrote earlier to create a password, update the user's password to the generated password, saves the username and the corresponding password to the &lt;code&gt;$PASSWORD_FILE&lt;/code&gt; and finally logs a message indicating it has been successfully changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the Input File
&lt;/h2&gt;

&lt;p&gt;The script reads the input file line by line, calling the &lt;code&gt;create_user()&lt;/code&gt; function for each line and passing the $username and $groups as arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;';'&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; username &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;create_user &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Now Put It All Together...
&lt;/h2&gt;



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

&lt;span class="c"&gt;# Log file location&lt;/span&gt;
&lt;span class="nv"&gt;LOGFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/log/user_management.log"&lt;/span&gt;
&lt;span class="nv"&gt;PASSWORD_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/secure/user_passwords.csv"&lt;/span&gt;

&lt;span class="c"&gt;# Check if the input file is provided&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error: No file was provided"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Usage: &lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;name-of-text-file&amp;gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Create log and password files&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/secure
&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt; &lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 &lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;

generate_random_password&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;10&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="c"&gt;# Default length is 10 if no argument is provided&lt;/span&gt;
    &lt;span class="nv"&gt;LC_ALL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;C &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-dc&lt;/span&gt; &lt;span class="s1"&gt;'A-Za-z0-9!?%+='&lt;/span&gt; &amp;lt; /dev/urandom | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nv"&gt;$length&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Function to create a user&lt;/span&gt;
create_user&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
  &lt;span class="nb"&gt;local groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;getent passwd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"User &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; already exists"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt;
  &lt;span class="k"&gt;else
    &lt;/span&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Created user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;

  &lt;span class="c"&gt;# Add user to specified groupsgroup&lt;/span&gt;
  &lt;span class="nv"&gt;groups_array&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$groups&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s2"&gt;","&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;group &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;groups_array&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; getent group &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;groupadd &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Created group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt;      
    &lt;span class="k"&gt;fi
    &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Added user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt; to group &lt;/span&gt;&lt;span class="nv"&gt;$group&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt;
  &lt;span class="k"&gt;done&lt;/span&gt;

  &lt;span class="c"&gt;# Set up home directory permissions&lt;/span&gt;
  &lt;span class="nb"&gt;chmod &lt;/span&gt;700 /home/&lt;span class="nv"&gt;$username&lt;/span&gt;
  &lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;:&lt;span class="nv"&gt;$username&lt;/span&gt; /home/&lt;span class="nv"&gt;$username&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Set up home directory for user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt;

  &lt;span class="c"&gt;# Generate a random password&lt;/span&gt;
  &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;generate_random_password 12&lt;span class="si"&gt;)&lt;/span&gt; 
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | chpasswd
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$PASSWORD_FILE&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Set password for user &lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Read the input file and create users&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;';'&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; username &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;create_user &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$groups&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"User creation process completed."&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$LOGFILE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This script provides an efficient way to manage user and group creation, ensuring that all necessary steps are handled securely and logged for auditing. By automating these tasks, SysOps engineers can save time and reduce the risk of errors during user onboarding.&lt;/p&gt;

&lt;p&gt;To learn more and kickstart your programming journey you can visit:&lt;br&gt;
&lt;a href="https://hng.tech/internship"&gt;https://hng.tech/internship&lt;/a&gt; or &lt;a href="https://hng.tech/premium"&gt;https://hng.tech/premium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feel free to reach out with questions or suggestions for improvements. Happy automating!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
