SelfService Active Directory Powershell script

Hi everybody,

We have a need for self service portal in our IT department. We arranged after work shifts, and if I’m not near my VPN connected PC, I needed to unlock or reset user passwords, or give users the ability to have their mangers do that for them.

I needed unlock or password reset solution for users, that will trigger a script on mail recieve. So I searched for simillar powershell script, and I found it DeployHappiness AD Self Service Portal.
This blog show us how to send SMS to mail, but our provider does not have this kind of service.

Still, this gave me a logic of things, and how to connect ot Exhange via API on specific mailbox, and query that mailbox for specific mails.

Then I needed to make sure that only users from our Organization can request, and that the person requesting is direct or indirect manager of the user.

Example:

  • IT Admins
    • John
      • Dave
      • Julia
        • Peter
        • Sandra
      • Steve
    • Angela
      • David
      • Jeremy
        • Marco

IT admins can request Unlock or Reset for everybody
John can request Unlock or Reset for his group (Dave,Julia,Peter,Sandra), but not for himself or Angela’s group.
Angela can request Unlock or Reset for hers group (David,Jeremy,Marco), but not for herself or John’s group.
Julia can request Unlock or Reset for hers group (Peter,Sandra), but not for herself or Dave and Steve.
Jeremy can request Unlock or Reset for Marco, but not for himself or David.

(Hope you got it) Smiješak

 

Next on Prerequisites:

  • Create a user with mail adress
  • Create Recieve connector on Exchange for server that will host the script
  • On server that will host a script install Feature: Active Directory module for Window Powershell
  • Setup Active Directory Users Manager on Users Organization Tab (example)
  • Define Mail Subject and Body field (For me Subject = User for Unlock or rest, Body = what to do Unlock user or Reset password)
  • Create taks scheduler (run as user to which you send mail requests), triggers set to 5 minutes (more or less is up to you)

Script:
Explanations are in my script commented.

<#

Script for SelService AD


This script enables IT to unlock or reset passwords to AD users. Mangers can also request for theirs employees.


        Author: Luka Gros

        Website: blog.lukagros.com

        Email: luka@lukagros.com

        Date created: 20.Octobar.2015

        Last modified: 20.Octobar.2015

        Version: 1.1


    .LINK


        http://blog.lukagros.com

        https://twitter.com/lukagros


#>

####Parts of Script from http://deployhappiness.com/reset-user-passwords-with-ad-self-service-portal/#######

##############################################################Config##############################################################

$SmtpServer = "10.10.10.1"

$ResetEmail = "Reset Notification <reset.password@domain.com>"

$Username = "DOMAIN\user"

$Password = "Passw0rd"

$MailServer = "https://mail.domain.com/ews/exchange.asmx"

$ExchangeVersion = "Exchange2013" ##"Exchange2010_sp1"

####ALERT MAIL####################

$LoggingUser = "InformationMail@domain.com"

####NEW USER RESET PASSWORD######

$NewPassword = "Passw0rd" #You can also find function that creates random password, but we use ours default. And be careful of character length in GPO


#######Download for API assembley file is here: http://www.microsoft.com/en-us/download/details.aspx?id=35371 (There is 2.2 that works better with Exchange 2013)

[Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll")



##############################################################Config##############################################################


###############################Function that checks if requester is manager to user###############################

#######http://www.lazywinadmin.com/2014/10/powershell-who-reports-to-whom-active.html########

function Get-ADdirectReports

{

    PARAM ($SamAccountName)

    Get-Aduser -identity $SamAccountName -Properties directreports | %{

        $_.directreports | ForEach-Object -Process {

            # Output the current Object information

            Get-ADUser -identity $Psitem -Properties mail,manager | Select-Object -Property Name, SamAccountName, Mail, @{ L = "Manager"; E = { (Get-Aduser -iden $psitem.manager).samaccountname } }


            # Find the DirectReports of the current item ($PSItem / $_)

            Get-ADdirectReports -SamAccountName $PSItem

        }

    }

}#CLOSE SECTION function Get-ADdirectReports


###############################Connect to Exchange mailbox###############################

 $email = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013)

 $email.Credentials = New-Object Net.NetworkCredential($Username, $Password)

 $uri=[system.URI] $MailServer

 $email.Url = $uri

 $inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($email,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

###############################Connect to Exchange mailbox###############################


###############################Check if there are unread mails###############################

if ($inbox.UnreadCount -gt 0)

 {

        $PropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)

        $PropertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text;

        # Set search criteria - unread only

        $SearchForUnRead = New-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::IsRead, $false)

        $items = $inbox.FindItems($SearchForUnRead,10)  #return only 10 unread mail items


        Import-Module -Name ActiveDirectory


 ###############################CHECK IF UNREAD ITEMS - IF NOT END###############################

 foreach ($item in $items.Items)

 {

  # load the property set to allow us to view the body

 $item.load($PropertySet)


    #######Get Subject and Body fields###

        $getsubjecttext = $item.subject

        $getsubjecttext = $getsubjecttext+"*" #add right wildcard

        $getbodytext = $item.body

        $getsubjectuser = Get-ADUser -Filter {DisplayName -like $getsubjecttext -and employeetype -eq'1'} -Properties UserPrincipalName,SamAccountName,cn,DisplayName,mail

        If ($getsubjectuser -eq $null) #If IT cannot be found by full name, try by SamAccountName

            {

            $getsubjectuser = Get-ADUser -Filter {SamAccountName -like $getsubjecttext -and employeetype -eq'1'} -Properties UserPrincipalName,SamAccountName,cn,DisplayName,mail

            }


        $managerEmployeOK = '0' ##Reset Manager Flag


        #######Get-requestere###

        $address = $item.From.address

        $user = Get-ADUser -Filter {UserPrincipalName -eq $address} -Properties UserPrincipalName,SamAccountName,cn


  ###Reset Unlock nad Reset flags for every mail####

  $UnlockAccount = '0'

  $ResetpwdAccount = '0'

#######IF Keywords in body

  if (($item.body.text -Like "Unlock account*") -and $getsubjectuser -ne $null) #THIS IS STRICT OR PEOPLE WILL WRITE RUBBISH

        {

            $UnlockAccount = '1'

        }


  if ($item.body.text -Like "Reset Password" -and $getsubjectuser -ne $null -and $UnlockAccount -eq '0') #THIS IS STRICT OR PEOPLE WILL WRITE RUBBISH

        {

            $ResetpwdAccount = '1'

        }


#################################If requester is found GO - IF NOT do nothing#######################################

if($user -ne $null)

{

<# If user is under requester set flag $managerEmployeOK=1, if not send mail NO RIGHTS

#>

    $usersToDo = Get-ADDirectReports $user.SamAccountName

    foreach ($Name in $usersToDo)

    {

        if ($Name.SamAccountName -eq $getsubjectuser.SamAccountName)

            {

                #Write-Output $Name.SamAccountName

                $managerEmployeOK = '1'

            }

    }

####Allow IT admins######

If ($user.SamAccountName -eq 'userAdmin1' -or $user.SamAccountName -eq 'userAdmin2') ##You can write if userAdmin is in some AdminGroup that can send requests

    {

    $managerEmployeOK = '1'

    }

##################################


IF ($managerEmployeOK -eq 1)

{

###UNLOCK SECTION################################################################################

 if($UnlockAccount -eq '1')

    {

            ##The line below is commented for e-mail testing, no command is issued

            ###Unlock-ADAccount -identity $getsubjectuser.samaccountname


            ##Send MAIL TO $LoggingUser = "InformationMail@domain.com"###################################

            $body="

                <p style='font-family:arial'>User Account " + $getsubjectuser.cn + " (" + $getsubjectuser.SamAccountName + ") has been unlocked. Request was from: $address</p>

                <p>&nbsp;

                <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                "

            send-mailmessage -to $LoggingUser -from $ResetEmail -subject "Action: User unlock requested!" -body $Body  -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8


            ##Send MAIL TO Requester###################################

            $body="

                <p style='font-family:arial'>HI,</p>

                <p style='font-family:arial'>User " + $getsubjectuser.cn + " (" + $getsubjectuser.SamAccountName + ") has been unlocked.</p>

                <p>&nbsp;

                 <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                "

            send-mailmessage -to $item.From.address -from $ResetEmail -subject "User is unlocked!" -body $Body -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8


            ##SEND MAIL TO unlocked user###################################

                $body="

                <p style='font-family:arial'>Hi " + $getsubjectuser.cn + ",</p>

                <p style='font-family:arial'>User " + $user.cn + " (" + $item.From.address + ") has requested unlocking of your account.</p>

                <p style='font-family:arial'>Your account <b>" + $getsubjectuser.SamAccountName +"</b> is now unlocked</p>

                <p>&nbsp;

                 <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                "

            send-mailmessage -to $getsubjectuser.mail -from $ResetEmail -subject "Your account has been unlocked!" -body $body -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8

            $Unlock = $True



    }#UNLOCK CLOSE SECTION


###RESET SECTION################################################################################

 if($ResetpwdAccount -eq '1')

    {

                <#The line below is commented for e-mail testing, no command is issued

                ###Set-ADAccountPassword -identity $user.samaccountname -Reset -NewPassword (ConvertTo-SecureString -AsPlainText $NewPassword -Force) #Set users new password

                ###Unlock-ADAccount -identity $user.samaccountname #Probably user locked, so unlock

###Set-ADUser -Identity $user.samaccountname -ChangePasswordAtLogon $true #Set must change password on next logon

                #>

                ##If the password was reseted in the last 10 minutes do nothing

                $PasswordAge = (Get-ADUser $getsubjectuser -Properties PasswordLastSet | Select PasswordLastSet)

                if ((Get-Date).AddMinutes(-10) -ge $PasswordAge.PasswordLastSet)

                 {


                ##Send MAIL TO $LoggingUser = "InformationMail@domain.com"###################################

                    $body="

                        <p style='font-family:arial'>Request for password reset for user " + $getsubjectuser.cn + " (" + $getsubjectuser.SamAccountName + "). Request was from: $address</p>

                        <p>&nbsp;

                        <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                      "

                    send-mailmessage -to $LoggingUser -from $ResetEmail -subject "Action: User password reset requested!" -body $Body  -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8


                    ##Send MAIL TO Requester###################################

                    $body="

                        <p style='font-family:arial'>Hi,</p>

                        <p style='font-family:arial'>Password reset for user" + $getsubjectuser.cn + " (" + $getsubjectuser.SamAccountName + ").</p>

                        <p style='font-family:arial'>New password is : <b>" + $NewPassword + "</b></p> ##If user cannot read their mail, then their manager can let them now

                        <p style='font-family:arial'>User can now try to logon with his/hers new password, but password must be changed on first logon!</p>

                        <p>&nbsp;

                        <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                        "

                    send-mailmessage -to $item.From.address -from $ResetEmail -subject "Reset user password complete!" -body $Body -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8


                    ##SEND MAIL TO user###################################

                    $body="

                        <p style='font-family:arial'>Hi " + $getsubjectuser.cn + ",</p>

                        <p style='font-family:arial'>User " + $user.cn + " (" + $item.From.address + ") requested your password to be changed. Your new password is: <b>" + $NewPassword +"</b></p>

                        <p>&nbsp;

                        <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                           "

                    send-mailmessage -to $getsubjectuser.mail -from $ResetEmail -subject "Your password has been reseted!" -body $body -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8

                } #CLOSE SECTION when was password last set

    }#CLOSE RESET SECITON


 ###Command or user unknown################################################################################

 if (($UnlockAccount -eq '0' -and $ResetpwdAccount -eq '0') -or ($getsubjectuser -eq $null))

    {

                        ##Send MAIL TO $LoggingUser = "InformationMail@domain.com"###################################

                        $body="

                        <p style='font-family:arial'>There was request " + $getsubjecttext +"; with body " + $getbodytext +"</p>

                        <p style='font-family:arial'>Request was  from: $address</p>

                        <p>&nbsp;

                        <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                        "

                        send-mailmessage -to $LoggingUser -from $ResetEmail -subject "Action:request error" -body $Body  -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8


                        ##Send MAIL TO Requester###################################

                        ##Don't forget here to write the instructions how the mail was supose to look

                        $body ="

                        <p style='font-family:arial'>Hi " + $user.cn + ",</p>

                        <p style='font-family:arial'>YOur mail, with title <b>" + $item.subject + "</b> is unknown.</p>

                        <p style='font-family:arial'>Please write correct user FirsName and Surname, or loginname.</p>

                        <p style='font-family:arial'>Keywords:</p>

                        <ul style='font-family:arial'>

                        <li><b>Unlock</b> - unlocks</li>

                        <li><b>Reset</b> - password reset</li>

                        </ul>

                        <p>&nbsp;

                        <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                        "

                        send-mailmessage -to $item.From.address -from $ResetEmail -subject "Mail command unknown" -body $Body -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8

      }#CLOSE SECTION Command or user unknown

} #CLOSE SECTION managerEmployeOK

else #If not manager

{

                        ##Send MAIL TO $LoggingUser = "InformationMail@domain.com"###################################

                        $body="

                        <p style='font-family:arial'>Stigao je mail sa naslovom <b>" + $getsubjecttext +"</b></p>

                        <p style='font-family:arial'>i tekstom <b>" + $getbodytext +"</b></p>

                        <p style='font-family:arial'>Zahtjev je došao sa adrese: $address</p>

                        <p>&nbsp;

                        <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                        "

                        send-mailmessage -to $LoggingUser -from $ResetEmail -subject "Action:manager error" -body $Body  -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8


                        ##Send MAIL TO Requester###################################

                        $body ="

                        <p style='font-family:arial'>Hi " + $user.cn + ",</p>

                        <p style='font-family:arial'>According to our specifications, you are not manager to user " + $getsubjectuser.cn + " (" + $getsubjectuser.SamAccountName + "). </p>

                        <p style='font-family:arial'>Request denied!</p>

                        <p>&nbsp;

                        <p style='font-family:arial;font-size:12px;color:red'>Please do not respond to this automatic e-mail!</p>

                        "

                        send-mailmessage -to $item.From.address -from $ResetEmail -subject "Manager request error" -body $Body -SmtpServer $SmtpServer -BodyAsHtml -Encoding UTF8

}#CLOSE SECTION if not manager

##Set mail read

$item.Isread = $true

$item.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)


 }#CLOSE SECTION Requester OK

 } #CLOSE SECTION foreach ($item in $items.Items)

 } #CLOSE SECTION ($inbox.UnreadCount -gt 0)

 

So , this would be it.

Teamviewer – a great ad-hoc support

As I wrote earlier in my blog post Working with Batch, we had a problems connecting to all computers in our branch offices. Since we live on VPN, provided by ISP on his modems/routers, there was always war with theirs technicians.
First of all, we had an old software Symantec PCAnywhere 11 which we used to connect to one computer in that remote office. from that computer we connected to all others. But, PcAnywhare had a problem, you had to setup a port forwarding (PcAnywhere ports are TCP 5631 and UDP 5632) on ISP’s modem to one of those computers. That computer had to have a fixed IP address, or setup DHCP MAC address assignment. But on power outage, thunder struck or clumsy maid, who needed a power source for her vacuum, the modem/router would reset and loose it’s settings. Then you call ISP’s technician to set it up again, hence the war begins. Then we switched to Win7, but PCAnywhere had issues with it. Connection drops, no picture to display and etc.

image Then came the revolutionary Teamviewer (further TW).
The free version, set limited time for sessions, when it discovered that you are using it for non-commercial use.
I suggested to my bosses that we should buy this little piece of software. And we did. We bought TEAMVIEWER 6. I must say it isn’t the cheapest software but it worth’s every €cent.

Teamviewer works on the principal of fixed addresses. TW server assigns 9 digit address ID code to every computer. BE CAREFUL after reinstalling a computer the ID CANNOT be changed back!!

Several TW products are there to use 
TW Full is used to connect to other TW devices. It can be used as a standalone software, or you can install it and use it as installed software. image
TW Quicksupport is standalone program which user starts on demand. It shows him his ID and generates a random password. TW QS can be also edited (for commercial users) with custom logo or text.
TW Host is an installation of TW as a service on a remote device.
TW QuickJoin is a standalone software, with which an user can connect to your presentation.
TW Portable is a standalone program, which allows you to use it on a USB stick and connect everywhere from anywhere.
TW Manager is a product for central managing your partner ID’s. It can use either a file as a database or a MSSQL database.
TW Web is a web service. You must create your username on TW and you use it as a partner list. Then login to TW Web and you can connect also from anywhere.

With TW you can easy set black and white list (BE CAREFUL after reinstalling a computer the ID CANNOT be changed back!!). Set access control, set password complexity, or set permission to change TW settings. You can transfer files,record sessions, transfer audio or video, and even chat. Organize presentations and meetings.
You can even install VPN adapters on each side and connect through VPN.
The TW is a great time and nerve saver.

Good Luck