Thursday, April 2, 2015

PowerShell: Password Alert & Report

This is first of three posts in regards to how admin team at current employer manage expiring password alerting and reporting.  We use 3 versions of PowerShell scripts:


  • Password Alert
  • Password Expiration based on OU Report
  • Report mailer to execute each OU Report and mail all out to admin team
This post will focus on the password alert script.

The script is composed of x number of segments.

  • Capturing max Password age from AD
  • Create function to send email users
  • Gather users not disabled with expiring passwords
  • Send email alert
First part of the script captures max password age from AD.  This is accomplished by maxpwdage from domain controller(s) then dividing it by nano seconds in a day (8.64e13 or 864000000000)

###################################
# Get the max Password age from AD 
# This Section pulls domains maximum password age from your domain controller(s)
###################################
function Get-maxPwdAge{
$root = [ADSI]"LDAP://DOMAIN.COM"
#Change DOMAIN.COM to target your domain
$filter = "(&(objectcategory=domainDNS)(distinguishedName=DC=DOMAIN,DC=COM))"
#Change Distinguished name to target your domain
$ds = New-Object system.DirectoryServices.DirectorySearcher($root,$filter)
$dc = $ds.findone()
[int64]$maxpwdage = [System.Math]::Abs( $dc.properties.item("maxPwdAge")[0])
$maxpwdage/864000000000
#Pulls maxPwdAge from domain for comparison later
}

Next part is to assemble function to email users

Key points to remember here are to update the following variables:

  • $SmtpClient.Host
    • Should be your mail server
  • $mailmessage.from
    • From email address you want messages to appear as
  • $mailmessage.Subject
    • Tweak the subject line of your message as desired
In addition you will want to update the body of the message to instruct your users on ways to reset their passwords.

###################################
# Function to send HTML email to each user
###################################

function send_email ($days_remaining, $email, $name ) 
{
 $today = Get-Date
 $today = $today.ToString("dddd (yyy-MMMM-dd)")
 $date_expire = [DateTime]::Now.AddDays($days_remaining);
 $date_expire = $date_expire.ToString("dddd (yyy-MMMM-dd)")
 $SmtpClient = new-object system.net.mail.smtpClient 
 $mailmessage = New-Object system.net.mail.mailmessage 
 $SmtpClient.Host = "ENTER YOUR MAIL SERVER HERE" 
 $mailmessage.from = "Technology <expiringpassword@donotreply.com>" 
 $mailmessage.To.add($email)
 $mailmessage.Subject = "$name, Your DOMAIN Password will expire soon."
 $mailmessage.IsBodyHtml = $true

 $mailmessage.Body = @"
<font face=Calibri (Body)>Dear $name, </font><br /><br />
<font face=Calibri (Body)>Your password will expire in <font color=red><strong>$days_remaining</strong></font> days on <strong>$date_expire</strong>.<br />
To prevent access issues ensure you change your password prior to $date_expire.<br /><br />

Your domain password is required for Computer Login, Infinite Campus, Email Access, Google Services (Drive, gMail), etc.<br /><br /><br />

You will receive this message until password is changed.<br /><br />


To change your password follow below processes:<br /><br />

<ul>
    <li type=square>Remote User
        <ul>
            <li>Must come onsite to change when connected to District network (Desktop or SaberSecure[WiFi])
        </ul>    
</ul>
<ul>
    <li type=square>PC/Windows User
        <ul>
            <li>Logon to system and press CTRL-ALT-DEL and choose Change Password.
        </ul>    
</ul>
<ul>
    <li type=square>PASSWORD REQUIREMENTS<br /><br />
        <ul>
            <li>must be 8 or more characters long and<br />
            <li>cannot be one of last 7 password used<br />
            <li>contain a mix of THREE of the following FOUR properties:<br />
                <ul>
                    <li type=disc>uppercase letters (A-Z)<br />
                    <li type=disc>lowercase letters (a-z)<br />
                    <li type=disc>numbers (0-9)<br />
                    <li type=disc>symbols (!"£$%^&*)
                </ul>
        </ul>
</ul>    
<br /><br />
Once your password has been changed you will need to update on all mobile devices (ex: cellphone / iPad / etc).  Failure to update could result in your account becoming locked repeatedly due to failed account access.
<br /><br /><br />

If you have any questions, please contact the IT Helpdesk on 
<br /><br />
 Generated on : $today

</font>
"@

 $smtpclient.Send($mailmessage) 
}


Next step is to query your domain for Non-Disabled and expiring users
###################################
# Search for Non-disabled AD users that have a Password Expiry.
###################################

$strFilter = "(&(objectCategory=User)(logonCount>=0)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(userAccountControl:1.2.840.113556.1.4.803:=65536)))"

$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$colResults = $objSearcher.FindAll();

# how many days before PW expiry do we start sending reminder emails?
$max_alert = 14


# Get the maximum password lifetime
$max_pwd_life=Get-maxPwdAge

$userlist = @()
foreach ($objResult in $colResults)
   {$objItem = $objResult.Properties; 
   if ( $objItem.mail.gettype.IsInstance -eq $True) 
      {      
         $user_name = $objItem.name
         $user_email = $objItem.email
         #Transform the DateTime readable format
         $user_logon = [datetime]::FromFileTime($objItem.lastlogon[0])
         $result = $objItem.pwdlastset 
         $user_pwd_last_set = [datetime]::FromFileTime($result[0])

         #calculate the difference in Day from last time a password was set
         $diff_date = [INT]([DateTime]::Now - $user_pwd_last_set).TotalDays;

   $Subtracted = $max_pwd_life - $diff_date
         if (($Subtracted) -le $max_alert) {
            $selected_user = New-Object psobject
           # $selected_user | Add-Member NoteProperty -Name "Name" -Value $objItem.name[0]
            $selected_user | Add-Member NoteProperty -Name "Name" -Value $objItem.Item("displayname")
            $selected_user | Add-Member NoteProperty -Name "Email" -Value $objItem.mail[0]
            $selected_user | Add-Member NoteProperty -Name "LastLogon" -Value $user_logon
            $selected_user | Add-Member NoteProperty -Name "LastPwdSet" -Value $user_pwd_last_set
            $selected_user | Add-Member NoteProperty -Name "RemainingDays" -Value ($Subtracted)
            $userlist+=$selected_user
         }
      }
   }


Lastly we send the email alert to the user

We are almost ready to send out our alerts now.  In this last bit of code we pull together the email message and list of expiring users.  We then send a message to each one.  Now for testing update ENTER_ADMIN_EMAIL_HERE to direct all messages to a single account.  This allows for review and tweaking of alert message.

###################################
# Send email to each user
###################################
   foreach ($userItem in $userlist )
   {
    if ($userItem.RemainingDays -ge 0) 
       {
     #Remove Comment (#) below to perform normal process / email user
     #send_email $userItem.RemainingDays $userItem.Email $userItem.Name
     #Update and remove comment below for testing / troubleshooting.  Allows for mailing a single user all expiring user alerts
     # send_email $userItem.RemainingDays ENTER_ADMIN_EMAIL_HERE $userItem.Name
       }
   }

# END

Download the PowerShell file here:
https://drive.google.com/open?id=0B1fwreWrAZioZW5fYlRxb3BCQms&authuser=0

No comments:

Post a Comment