Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Thursday, September 3, 2015

Windows Administrators should learn PowerShell

Why should Windows Administrators learn PowerShell? My answer is a simple flow chart:


Monday, June 11, 2012

Active Directory Password Expiration Email Notification

This is a PowerShell script that will send an email notification to Active Directory users when their password will expire in 14, 7, 3, 1, and Zero days. Administrators/helpdesk also get a daily report of passwords that are expired and the users who got an email reminder, a great heads up for your helpdesk.

The script generates a different message when there are zero days remaining (password is expired and must be changed today) and won't continue to notify users when there are less than zero days remaining. Negitive dedlines are used for some account options such as the passwords must be changed at next logon account flag, and you don't want to fill up a user's mailbox when they can't access their mail before changing their password anyway.

To setup the script, search for the "# CONFIG:" strings and edit the following line as documented, then set it up on a server as a daily scheduled task.

Active Directory Password Expiration Email Notification Script
Import-Module ActiveDirectory

$maxdays=(Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge.TotalDays
$summarybody="Name `t ExpireDate `t DaysToExpire `n"

(Get-ADUser -filter {(mail -like "*@domain.com") -and (Enabled -eq "True") -and (PasswordNeverExpires -eq "False")} -properties *) | Sort-Object pwdLastSet |
foreach-object {

    $lastset=Get-Date([System.DateTime]::FromFileTimeUtc($_.pwdLastSet))
    $expires=$lastset.AddDays($maxdays).ToShortDateString()
    $daystoexpire=[math]::round((New-TimeSpan -Start $(Get-Date) -End $expires).TotalDays)
    $samname=$_.samaccountname
    $firstname=$_.GivenName
    if (($daystoexpire -eq 14) -or ($daystoexpire -eq 7) -or ($daystoexpire -eq 3) -or ($daystoexpire -eq 1) -or ($daystoexpire -eq 0)) {
    #if ($daystoexpire -le 14) {
        $ThereAreExpiring=$true
        
         # CONFIG: Enter from email address.
        $emailFrom = "helpdesk@domain.com"
        # CONFIG: Replace domain domain.com with your email domain. Do not change $samname.
        $emailTo = "$samname@domain.com"
        if ($daystoexpire -eq 0) {
        # CONFIG: Enter text for subject and body of email notification for zero days remaining.
            $subject = "$firstname, your password has expried!"
            $body = "$firstname,
Your password has expired and you must change it immediately. No further email notifications will be sent.

Contact support at extension XXXX for assistance."
        }
        Else {
        # CONFIG: Enter text for subject and body of email notification for 14, 7, 3, and 1 days remaining. 
            $subject = "$firstname, your password expires in $daystoexpire day(s)!"
            $body = "$firstname,
Your password expires in $daystoexpire day(s).

If you are using a Windows computer, press Ctrl + Alt + Del the click Change password.

If you are using a Mac computer follow the instructions at http://sharepoint/Documentation to change your password.
"
        }
        # CONFIG: Enter your smtp server here.
        $smtpServer = "email.domain.com"
        $smtp = new-object Net.Mail.SmtpClient($smtpServer)
        $smtp.Send($emailFrom, $emailTo, $subject, $body)   
       
        $summarybody += "$samname `t $expires `t $daystoexpire `n"
    }
    elseif ($daystoexpire -lt 0) {
        $ThereAreExpiring=$true
        # Add a note to the report email, but don't notify user.
        $summarybody += "$samname `t $expires `t $daystoexpire `n"
    }
}
if ($ThereAreExpiring) {
    # CONFIG: From address for report to Helpdesk/IT Admin staff.
    $emailFrom = "helpdesk@domain.com"
    # CONFIG: Address to send report email to (for Helpdesk/IT Admin staff.
    $emailTo = "helpdesk@domain.com"
    # CONFIG: Subject for report email.
    $subject = "Expiring passwords"
    $body = $summarybody
    # CONFIG: SMTP Server.
    $smtpServer = "email.domain.com"
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $smtp.Send($emailFrom, $emailTo, $subject, $body)
}



Thursday, May 31, 2012

Active Directory Account Lockout Notifications using PowerShell

I've found it's often helpful to get an email notification when an Active Directory account is locked out. In a previous job we used Account Lockout Examiner from NetWrix for this functionality. A few years and a job or two later and I've found a way to do this with the Windows Task Scheduler and PowerShell. You also need to have a Windows Server 2008 Domain Controller. Your Active Directory domain does not need to be in 2008 Native Mode.

Before going on, I should mention that the following scripts were originally created by Joe0126 and shared in this post on the SpiceWorks Community site. I simply took what Joe0126 created and updated the output to meet my needs. The email notification will look like this:

Subject: Account Locked Out: ADDOMAIN\username
Email Body:
Account Name: ADDOMAIN\username
Workstation: ADCOMPUTERNAME
Time: 05/28/2012 17:45:43


In the case of an account lock event, the workstation will tell you what computer or server the account was locked out on. Usually this will be the user's workstation or one of your Exchange CAS servers. If the lockout happened on a computer that isn't joined to the domain workstation will be blank.

The account unlock notification is slightly different. The workstation will be the workstation AD Users and Computers is running on, and who is responsible for unlocking the account will be in the notification as well.

Subject: Account Unlocked: ADDOMAIN\username
Email Body:
Account Name: ADDOMAIN\username
Workstation: somecomputer.domain.com
Time: 05/29/2012 11:03:31

Unlocked By:
ADDOMAIN\someadmin


To start, grab the code for the scripts below. One will generate an email notification for an account lock event, the other will generate an email notification for an account unlock event. Update the script with the SMTP server and email addresses for your domain (update lines with domain.com) and save them to your Domain Controller.

On your domain controller, open Task Scheduler and create a new task (Not create basic task). Your trigger should be "On an Event." Select the Security Log and enter 4740 for the EventID. EventID 4740 is an Account Lock. For your action run your PowerShell Script. For the unlock notification, do the same for EventID 4767 and use the Unlock Notification Script.

Notifications won't be instantaneous as PowerShell's get-eventlog commandlet isn't very fast when it comes to finding events in the Windows log, but it has been fast enough for our environment. In most cases we get the account lockout notification before the user calls the helpdesk to report a problem.

Account Lock Notification Script:
$SMTPServer = "mail.example.com"
$MailFrom = "no-reply@example.com"
$MailTo = "account-lockout-notifications@example.com"

Import-Module activedirectory

$Event=Get-EventLog -LogName "Security" -InstanceId "4740" -Newest 1000

$User = $Event.ReplacementStrings[0]

$Computer = $Event.ReplacementStrings[1]

$Domain = $Event.ReplacementStrings[5]

$MailSubject= "Account Locked Out: " + $Domain + "\" + $User

$MailBody = "Account Name: " + $Domain + "\" + $User + "`r`n" + "Workstation: " + $Computer + "`r`n" + "Time: " + $Event.TimeGenerated + "`r`n"

$lockedAccounts = Search-ADAccount -LockedOut | Select -Property SamAccountName | Out-String

$MailBody = $MailBody + "`r`nThe following accounts are currently locked out:`r`n" +  $lockedAccounts

Send-MailMessage -To $MailTo -From $MailFrom -Subject $MailSubject -SmtpServer $SMTPServer -Body $MailBody

Account Unlock Notification Script:
$SMTPServer = "mail.example.com"
$MailFrom = "no-reply@example.com"
$MailTo = "account-lockout-notifications@example.com"




Import-Module activedirectory

$Event=Get-EventLog -LogName "Security" -InstanceId "4767" -Newest 1000

$User = $Event.ReplacementStrings[0]


$Domain = $Event.ReplacementStrings[1]

$UnlockBy =  $Event.ReplacementStrings[4]


$UnlockByDomain = $Event.ReplacementStrings[5]

$Computer = $Event.MachineName

$MailSubject= "Account Unlocked: " + $Domain + "\" + $User

$MailBody = "Account Name: " + $Domain + "\" + $User + "`r`n" + "Workstation: " + $Computer + "`r`n" + "Time: " + $Event.TimeGenerated + "`r`n`r`n Unlocked By: " + $UnlockByDomain + "\" + $UnlockBy

Send-MailMessage -To $MailTo -From $MailFrom -Subject $MailSubject -SmtpServer $SMTPServer -Body $MailBody

For the extra lazy, unlock everyone:
Import-Module activedirectory
Search-ADAccount -LockedOut | Unlock-ADAccount

Update 1, 2012-06-18: I added the Unlock notification to all our Server 2008 R2 domain controllers. We were only getting notifications when an account was unlocked on the domain controller running the script. I don't think this is a similar issue with the lock notification script.

Update 2, 2014-12-29: Checked this post and found I've made a few more improvements since my last posting. Configuration for mail server is now at the top, and I added a line to get all locked accounts to the lock notification, just in case your IT Service Desk missed a few accounts. Also added PowerShell to unlock all locked accounts. Use with caution obviously.