On-Prem-AD-User-Creator.ps1

<#PSScriptInfo
 
.VERSION 23.04.28
 
.GUID eaaca86c-2a1f-4caf-b2f9-05868186d162
 
.AUTHOR Mike Galvin Contact: mike@gal.vin / twitter.com/mikegalvin_ / discord.gg/5ZsnJ5k
 
.COMPANYNAME Mike Galvin
 
.COPYRIGHT (C) Mike Galvin. All rights reserved.
 
.TAGS Active Directory User Creation CSV Import
 
.LICENSEURI
 
.PROJECTURI https://gal.vin/utils/on-prem-ad-user-creator-utility/
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
#>


<#
    .SYNOPSIS
    On-Prem AD User Creator Utility - Configurable Script to create new Active Directory user accounts.
 
    .DESCRIPTION
    This script will create AD users based on first and last names in a specified CSV file.
    Run with -help or no arguments for usage.
#>


## Set up command line switches.
[CmdletBinding()]
Param(
    [alias("CSV")]
    $UsersList,
    [alias("OU")]
    $OrgUnit,
    [alias("UPN")]
    $AdUpn,
    [alias("HomeLetter")]
    $HomeDrive,
    [alias("HomePath")]
    $HomeUncUsr,
    [alias("Groups")]
    $AdGrps,
    [alias("L")]
    $LogPathUsr,
    [alias("LogRotate")]
    $LogHistory,
    [alias("Subject")]
    $MailSubject,
    [alias("SendTo")]
    $MailTo,
    [alias("From")]
    $MailFrom,
    [alias("Smtp")]
    $SmtpServer,
    [alias("Port")]
    $SmtpPort,
    [alias("User")]
    $SmtpUser,
    [alias("Pwd")]
    [ValidateScript({Test-Path -Path $_ -PathType Leaf})]
    $SmtpPwd,
    [switch]$UseSsl,
    [switch]$Help,
    [switch]$NoBanner)

If ($NoBanner -eq $False)
{
    Write-Host -ForegroundColor Yellow -BackgroundColor Black -Object "
           ____ ____ ___ ____
          / __ \____ / __ \________ ____ ___ / | / __ \ Mike Galvin
         / / / / __ \______/ /_/ / ___/ _ \/ __ '__ \ / /| | / / / / https://gal.vin
        / /_/ / / / /_____/ ____/ / / __/ / / / / / / ___ |/ /_/ /
        \____/_/_/_/ /_/ /_/ __\___/_/ /_/ /_/ /_/__|_/_____/ __ ____ _ ___ __
          / / / /_______ _____ / ____/_______ ____ _/ /_____ _____ / / / / /_(_) (_) /___ __
         / / / / ___/ _ \/ ___/ / / / ___/ _ \/ __ '/ __/ __ \/ ___/ / / / / __/ / / / __/ / / /
        / /_/ (__ ) __/ / / /___/ / / __/ /_/ / /_/ /_/ / / / /_/ / /_/ / / / /_/ /_/ /
        \____/____/\___/_/ \____/_/ \___/\__,_/\__/\____/_/ \____/\__/_/_/_/\__/\__, /
                                                                                           /____/
            Version 23.04.28
          See -help for usage Donate: https://www.paypal.me/digressive
"

}

If ($PSBoundParameters.Values.Count -eq 0 -or $Help)
{
    Write-Host -Object "Usage:
    From a terminal run: [path\]On-Prem-AD-User-Creator.ps1 -csv [path\]user-list.csv
    This will create new users from the names in the csv file.
    The user objects will be created in the 'Computers' builtin OU.
 
    To set the users UPN use: -upn [domain.name]
    To set where the user objects are created: -ou [""'Full OU DN path'""]
    To set the Home letter and Home path: -HomeLetter [drive letter] -HomePath [path]
    To set which group(s) the new users should be a member of: -Groups [UserGroup1,UserGroup2]
 
    To output a log: -L [path\].
    To remove logs produced by the utility older than X days: -LogRotate [number].
    Run with no ASCII banner: -NoBanner
 
    To use the 'email log' function:
    Specify the subject line with -Subject ""'[subject line]'"" If you leave this blank a default subject will be used
    Make sure to encapsulate it with double & single quotes as per the example for Powershell to read it correctly.
 
    Specify the 'to' address with -SendTo [example@contoso.com]
    For multiple address, separate with a comma.
 
    Specify the 'from' address with -From [example@contoso.com]
    Specify the SMTP server with -Smtp [smtp server name]
 
    Specify the port to use with the SMTP server with -Port [port number].
    If none is specified then the default of 25 will be used.
 
    Specify the user to access SMTP with -User [example@contoso.com]
    Specify the password file to use with -Pwd [path\]ps-script-pwd.txt.
    Use SSL for SMTP server connection with -UseSsl.
 
    To generate an encrypted password file run the following commands
    on the computer and the user that will run the script:
"

    Write-Host -Object ' $creds = Get-Credential
    $creds.Password | ConvertFrom-SecureString | Set-Content [path\]ps-script-pwd.txt'

}

else {
    ## If logging is configured, start logging.
    ## If the log file already exists, clear it.
    If ($LogPathUsr)
    {
        ## Clean User entered string
        $LogPath = $LogPathUsr.trimend('\')

        ## Make sure the log directory exists.
        If ((Test-Path -Path $LogPath) -eq $False)
        {
            New-Item $LogPath -ItemType Directory -Force | Out-Null
        }

        $LogFile = ("On-Prem-AD-User-Creator_{0:yyyy-MM-dd_HH-mm-ss}.log" -f (Get-Date))
        $Log = "$LogPath\$LogFile"

        If (Test-Path -Path $Log)
        {
            Clear-Content -Path $Log
        }
    }

    ## Function to get date in specific format.
    Function Get-DateFormat
    {
        Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    }

    ## Function for logging.
    Function Write-Log($Type, $Evt)
    {
        If ($Type -eq "Info")
        {
            If ($LogPathUsr)
            {
                Add-Content -Path $Log -Encoding ASCII -Value "$(Get-DateFormat) [INFO] $Evt"
            }
            
            Write-Host -Object "$(Get-DateFormat) [INFO] $Evt"
        }

        If ($Type -eq "Succ")
        {
            If ($LogPathUsr)
            {
                Add-Content -Path $Log -Encoding ASCII -Value "$(Get-DateFormat) [SUCCESS] $Evt"
            }

            Write-Host -ForegroundColor Green -Object "$(Get-DateFormat) [SUCCESS] $Evt"
        }

        If ($Type -eq "Err")
        {
            If ($LogPathUsr)
            {
                Add-Content -Path $Log -Encoding ASCII -Value "$(Get-DateFormat) [ERROR] $Evt"
            }

            Write-Host -ForegroundColor Red -BackgroundColor Black -Object "$(Get-DateFormat) [ERROR] $Evt"
        }

        If ($Type -eq "Conf")
        {
            If ($LogPathUsr)
            {
                Add-Content -Path $Log -Encoding ASCII -Value "$Evt"
            }

            Write-Host -ForegroundColor Cyan -Object "$Evt"
        }
    }

    ## Function for Update Check
    Function UpdateCheck()
    {
        $ScriptVersion = "23.04.28"
        $RawSource = "https://raw.githubusercontent.com/Digressive/On-Prem-AD-User-Creator-Utility/master/On-Prem-AD-User-Creator.ps1"

        try {
            $SourceCheck = Invoke-RestMethod -uri "$RawSource"
            $VerCheck = $SourceCheck -split '\n' | Select-String -Pattern ".VERSION $ScriptVersion" -SimpleMatch -CaseSensitive -Quiet

            If ($VerCheck -ne $True)
            {
                Write-Log -Type Conf -Evt "*** There is an update available. ***"
            }
        }

        catch {
        }
    }

    ## Check for required options
    If ($Null -eq $UsersList)
    {
        Write-Log -Type Err -Evt "You must specify a users list with -CSV"
        Exit
    }

    If ($Null -eq $HomeDrive -And $HomeUncUsr)
    {
        Write-Log -Type Err -Evt "You need to set both -HomeLetter and -HomePath"
        Exit
    }

    If ($Null -eq $HomeUncUsr -And $HomeDrive)
    {
        Write-Log -Type Err -Evt "You need to set both -HomeLetter and -HomePath"
        Exit
    }

    # Set variables for options not set
    If ($Null -eq $OrgUnit)
    {
        $OrgUnit = 'CN=Computers,DC=contoso,DC=com'
    }

    If ($Null -eq $AdUpn)
    {
        $AdUpn = Get-addomain | Select-Object Forest -ExpandProperty Forest
    }

    If ($HomeUncUsr)
    {
        $HomeUnc = $HomeUncUsr.trimend('\')
    }

    If ($Null -eq $LogPathUsr -And $SmtpServer)
    {
        Write-Log -Type Err -Evt "You must specify -L [path\] to use the email log function."
        Exit
    }

    ## getting Windows Version info
    $OSVMaj = [environment]::OSVersion.Version | Select-Object -expand major
    $OSVMin = [environment]::OSVersion.Version | Select-Object -expand minor
    $OSVBui = [environment]::OSVersion.Version | Select-Object -expand build
    $OSV = "$OSVMaj" + "." + "$OSVMin" + "." + "$OSVBui"

    ##
    ## Display the current config and log if configured.
    ##
    Write-Log -Type Conf -Evt "--- Running with the following config ---"
    Write-Log -Type Conf -Evt "Utility Version: 23.04.28"
    Write-Log -Type Conf -Evt "Hostname: $Env:ComputerName."
    Write-Log -Type Conf -Evt "Windows Version: $OSV."

    If ($UsersList)
    {
        Write-Log -Type Conf -Evt "CSV file: $UsersList."
    }

    If ($OrgUnit)
    {
        Write-Log -Type Conf -Evt "OU for users: $OrgUnit."
    }

    If ($AdUpn)
    {
        Write-Log -Type Conf -Evt "User UPN: $AdUpn."
    }

    If ($HomeDrive)
    {
        Write-Log -Type Conf -Evt "Home Letter: $HomeDrive."
    }

    If ($HomeUncUsr)
    {
        Write-Log -Type Conf -Evt "Home UNC Path: $HomeUncUsr."
    }

    If ($AdGrps)
    {
        Write-Log -Type Conf -Evt "Groups to add user to:"

        ForEach ($Grp in $AdGrps)
        {
            Write-Log -Type Conf -Evt " $Grp"
        }
    }

    If ($LogPathUsr)
    {
        Write-Log -Type Conf -Evt "Logs directory: $LogPath."
    }

    If ($Null -ne $LogHistory)
    {
        Write-Log -Type Conf -Evt "Logs to keep: $LogHistory days."
    }

    If ($MailTo)
    {
        Write-Log -Type Conf -Evt "E-mail log to: $MailTo."
    }

    If ($MailFrom)
    {
        Write-Log -Type Conf -Evt "E-mail log from: $MailFrom."
    }

    If ($MailSubject)
    {
        Write-Log -Type Conf -Evt "E-mail subject: $MailSubject."
    }

    If ($SmtpServer)
    {
        Write-Log -Type Conf -Evt "SMTP server: Configured."
    }

    If ($SmtpUser)
    {
        Write-Log -Type Conf -Evt "SMTP auth: Configured."
    }

    Write-Log -Type Conf -Evt "---"
    Write-Log -Type Info -Evt "Process started"
    ##
    ## Display current config ends here.
    ##

    If ($Null -ne $UsersList)
    {
        If (Test-Path -Path $UsersList)
        {
            ## Use this for password generation
            Add-Type -AssemblyName System.Web

            #Creating array for the sam account names for use later
            $SamsList = @()

            #Get the users names from the CSV
            $UserCsv = Import-Csv -Path $UsersList

            ForEach ($User in $UserCsv) {
                ## Clean ' from first names
                $FirstnameClean = $User.Firstname -replace "[']"

                ## If firstname is long, shorten for samaccountname limit + rand number
                $NameSafeLen = $FirstnameClean.substring(0, [System.Math]::Min(16, $FirstnameClean.Length))

                # Create a random number
                $RandNum = (Get-Random -Minimum 0 -Maximum 9999).ToString('0000')

                $SamName = $NameSafeLen + $RandNum
                $SamsList += $SamName
                $UserFirstName = $User.Firstname
                $UserLastName = $User.Lastname
                $UserFullName = $UserFirstName + " " + $UserLastName

                ## The UPN set as the new sam account name and the email domain.
                $Upn = $SamName + "@$AdUpn"
                $DisplayName = $UserFullName
                $Pwrd = ([System.Web.Security.Membership]::GeneratePassword(8,0))

                ## If no home letter or path is configured, set to null
                If ($HomeUncUsr)
                {
                    $HomeUncFull = "$HomeUnc\$SamName"
                }

                else {
                    $HomeUncFull = $null
                    $HomeDrive = $null
                }

                ## Check for existance of existing users with same name
                $UserExist = Get-ADUser -filter "SamAccountName -eq '$SamName'"

                ## If a user does already exist with name sam name, regenerate the nummber and try to create again. Do this until user does not exist.
                do {
                    # Create a random number
                    $RandNum = (Get-Random -Minimum 0 -Maximum 9999).ToString('0000')
                    $UserExist = Get-ADUser -filter "SamAccountName -eq '$SamName'"

                    try {
                        New-ADUser -Name "$SamName" -GivenName "$UserFirstName" -Surname "$UserLastName" -DisplayName "$DisplayName" -SamAccountName $SamName -UserPrincipalName $Upn -Path $OrgUnit -AccountPassword (ConvertTo-SecureString $Pwrd -AsPlainText -Force) -ChangePasswordAtLogon $true -Enabled $true -HomeDirectory $HomeUncFull -HomeDrive $HomeDrive
                        Write-Log -Type Info -Evt "(User) Creating new user $UserFirstName $UserLastName - Username: $SamName, Password: $Pwrd [END]"
                    }

                    catch {
                        Write-Log -Type Err -Evt $_.Exception.Message
                    }

                } until ($null -eq $UserExist)
            }

            ## If Groups are configured, find and add them
            If ($AdGrps)
            {
                ForEach ($Sams in $SamsList) {
                    ForEach ($AdGrp in $AdGrps) {
                        try {
                            Add-ADGroupMember -Identity $AdGrp -Members $Sams
                            Write-Log -Type Info -Evt "(Group) Adding user: $Sams to $AdGrp"
                        }
                        catch {
                            Write-Log -Type Err -Evt $_.Exception.Message
                        }
                    }
                }
            }

            ## Jobs done.
            Write-Log -Type Info -Evt "Process finished"
        }

        else {
            Write-Log -Type Err -Evt "The specified file was not found."
        }
    }

    else {
        Write-Log -Type Err -Evt "No csv file specified."
    }

    If ($Null -ne $LogHistory)
    {
        ## Cleanup logs.
        Write-Log -Type Info -Evt "Deleting logs older than: $LogHistory days"
        Get-ChildItem -Path "$LogPath\On-Prem-AD-User-Creator_*" -File | Where-Object CreationTime -lt (Get-Date).AddDays(-$LogHistory) | Remove-Item -Recurse
    }

    ## This whole block is for e-mail, if it is configured.
    If ($SmtpServer)
    {
        If (Test-Path -Path $Log)
        {
            ## Default e-mail subject if none is configured.
            If ($Null -eq $MailSubject)
            {
                $MailSubject = "On-Prem AD User Creator Utility Log"
            }

            ## Default Smtp Port if none is configured.
            If ($Null -eq $SmtpPort)
            {
                $SmtpPort = "25"
            }

            ## Setting the contents of the log to be the e-mail body.
            $MailBody = Get-Content -Path $Log | Out-String

            ForEach ($MailAddress in $MailTo)
            {
                ## If an smtp password is configured, get the username and password together for authentication.
                ## If an smtp password is not provided then send the e-mail without authentication and obviously no SSL.
                If ($SmtpPwd)
                {
                    $SmtpPwdEncrypt = Get-Content $SmtpPwd | ConvertTo-SecureString
                    $SmtpCreds = New-Object System.Management.Automation.PSCredential -ArgumentList ($SmtpUser, $SmtpPwdEncrypt)

                    ## If -ssl switch is used, send the email with SSL.
                    ## If it isn't then don't use SSL, but still authenticate with the credentials.
                    If ($UseSsl)
                    {
                        Send-MailMessage -To $MailAddress -From $MailFrom -Subject $MailSubject -Body $MailBody -SmtpServer $SmtpServer -Port $SmtpPort -UseSsl -Credential $SmtpCreds
                    }

                    else {
                        Send-MailMessage -To $MailAddress -From $MailFrom -Subject $MailSubject -Body $MailBody -SmtpServer $SmtpServer -Port $SmtpPort -Credential $SmtpCreds
                    }
                }

                else {
                    Send-MailMessage -To $MailAddress -From $MailFrom -Subject $MailSubject -Body $MailBody -SmtpServer $SmtpServer -Port $SmtpPort
                }
            }
        }

        else {
            Write-Host -ForegroundColor Red -BackgroundColor Black -Object "There's no log file to email."
        }
    }
    ## End of Email block
}
## End