En otitelerad blog

Not just another Systems Administrator weblog – Fast på svenska

PowerShell: Notifiera användare att byta lösenord

lämna en kommentar »

Att ha en policy som kräver att dator användare i en domän byter lösenord varje eller var annan månad är ett måste, så att man får en viss förhöjd säkerhet. För de flesta användare följer ju ett rätt enkelt lösenord. Men en sådan policy kan också skapa lite problem när man har användare som inte loggar in så ofta, och som använder till exempel VPN.

Jag har länge velat lära mig mer om PowerShell, så jag tänkte att detta kunde vara ett perfekt tillfälle att göra just detta. Jag insåg dock snabbt att skapa ett skript för att notifiera användarna skulle vara lite överkurs för mig. Så jag sökte runt på Internet och hittade faktiskt ett skript, som jag kunde modifiera för att passa mina behov.

Kopiera texten mellan ##START## och ##END##.

##START##
Function Get-UTCAge {
  #get date time of the last password change
      Param([int64]$Last=0)
      if ($Last -eq 0) {
          write 0
      } else {
          #clock starts counting from 1/1/1601.
          [datetime]$utc="1/1/1601"
          #calculate the number of days based on the int64 number
          $i=$Last/864000000000
          #Add the number of days to 1/1/1601
          #and write the result to the pipeline
          write ($utc.AddDays($i))
      }
  } # end Get-UTCAge function
Function Get-PwdAge {

Param([int64]$LastSet=0)
  if ($LastSet -eq 0) {
      write "0"
  } else {
      #get the date the password was last changed
      [datetime]$ChangeDate=Get-UTCAge $LastSet
      #get the current date and time
      [datetime]$RightNow=Get-Date
      #write the difference in days
      write $RightNow.Subtract($ChangeDate).Days
  }
} #end Get-PwdAge function

#main code
#define some constants

New-Variable ADS_UF_ACCOUNTDISABLE 0×0002 -Option Constant
New-Variable ADS_UF_PASSWD_CANT_CHANGE 0×0040 -Option Constant
New-Variable ADS_UF_DONT_EXPIRE_PASSWD 0×10000 -Option Constant
New-Variable ADS_UF_PASSWD_EXPIRED 0×800000 -Option Constant

$strfilter="(&(objectCategory=person)(objectClass=user))"

#—————————————————–
# Change strADSI to limit the search for users with expirering passwords
#—————————————————–
#$strADSI="LDAP://OU=OU-NAME,DC=DOMAIN,DC=COM" (Change to limit search to one OU structure)
$strADSI=""    (Default: search whole domain)
#—————————————————–

$objDomain = New-Object System.DirectoryServices.DirectoryEntry($strADSI)

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"

$users=$objSearcher.findAll()

foreach ($user in $users) {

if (-not $user.path) {
  Write-Warning "Could not find $samaccountname"
  Return
}

$user | ForEach-Object {

#get password properties from useraccountcontrol field
  if ($_.properties.item("useraccountcontrol")[0] -band $ADS_UF_DONT_EXPIRE_PASSWD) {
      $pwdNeverExpires=$True
   }
   else {
      $pwdNeverExpires=$False
   }
   #Password expired should be calculated from a computed UAC value
   $user=$_.GetDirectoryEntry()
   $user.psbase.refreshcache("msDS-User-Account-Control-Computed")
   [int]$computed=$user.psbase.properties.item("msDS-User-Account-Control-Computed").value
   if ($computed -band $ADS_UF_PASSWD_EXPIRED) {
      $pwdExpired=$True
   }
   else {
      $pwdExpired=$False
   }
   if ($_.properties.item("useraccountcontrol")[0] -band $ADS_UF_ACCOUNTDISABLE) {
      $accDisabled=$True
   }
   else {
      $accDisabled=$False
   }

#has email check
   if ($_.properties.item("mail")[0] -eq $Null) {
      $mailAllowed=$False
   }
   else {
      $mailAllowed=$True
   }
   #check if user can change their password
   if ($_.properties.item("useraccountcontrol")[0] -band $ADS_UF_PASSWD_CANT_CHANGE) {
      $pwdChangeAllowed=$False
   }
   else {
      $pwdChangeAllowed=$True
   }

#—————————————————–
   #check if password age is more och equal to 46 days.
   #change 46 for a number of days that suites your needs.
   #—————————————————–
   if ((Get-PwdAge $_.properties.item("pwdlastset")[0]) -ge 46) {
      $pwdAboutExpire=$True
   }
   else {
      $pwdAboutExpire=$False
   }
   #—————————————————–

if (-not $accDisabled -and $mailAllowed -and $pwdAboutExpire -or $pwdExpired) {

#create a custom object for the account and password properties
      $obj=New-Object PSObject
      #add properties to the object
      $obj | Add-Member -MemberType NoteProperty -Name "<br/>Name" -Value $_.properties.item("name")[0]
      #$obj | Add-Member -MemberType NoteProperty -Name "DN" -Value $_.properties.item("distinguishedname")[0]
      #$obj | Add-Member -MemberType NoteProperty -Name "samAccountName" -Value $_.properties.item("samaccountname")[0]
      #$obj | Add-Member -MemberType NoteProperty -Name "Description" -Value $_.properties.item("description")[0]
      #$obj | Add-Member -MemberType NoteProperty -Name "Email" -Value $_.properties.item("mail")[0]
      #$obj | Add-Member -MemberType NoteProperty -Name "<br/>AccountCreated" -Value $_.properties.item("whencreated")[0]
      #$obj | Add-Member -MemberType NoteProperty -Name "<br/>AccountModified" -Value $_.properties.item("WhenChanged")[0]
      #$obj | Add-Member -MemberType NoteProperty -Name "AccountDisabled" -Value $accDisabled
      $obj | Add-Member -MemberType NoteProperty -Name "<br/>LastLogon" -Value (Get-UTCAge $_.properties.item("lastlogon")[0])
      $obj | Add-Member -MemberType NoteProperty -Name "<br/>PasswordLastChanged" -Value (Get-UTCAge $_.properties.item("pwdlastset")[0])
      $obj | Add-Member -MemberType NoteProperty -Name "<br/>PasswordAge" -Value (Get-PwdAge $_.properties.item("pwdlastset")[0])
      #$obj | Add-Member -MemberType NoteProperty -Name "PasswordExpired" -Value $pwdExpired
      #$obj | Add-Member -MemberType NoteProperty -Name "PasswordNeverExpires" -Value $pwdNeverExpires
      #$obj | Add-Member -MemberType NoteProperty -Name "PasswordChangeAllowed" -Value $pwdChangeAllowed
      $obj | Add-Member -MemberType NoteProperty -Name "<br/>BadPasswordTime" -Value (Get-UTCAge $_.properties.item("BadPassWordTime")[0])
      #write object to the pipeline
      #—————————————————–
      # Change: emailFrom to match your environment
      #—————————————————– 
      $emailFrom = "noreply@domain.com"

       #—————————————————–
      # Change: emailTo to match your environment, this reads the entered email address from the user properties in Active Directory
      #—————————————————–
      $emailTo =$_.properties.item("mail")[0]
      #—————————————————–
      $subject = "Change your password reminder"
      $body = "<html><body>Your password is about to expire or has expired, please change your password as soon as possible. This email will be sent every day until the password has been changed. If you have any issues, then please contact IT Department. <br/><br/>" + $obj + "</body></html>"
      #—————————————————–
      # Change: smtpServer to match your environment
      #—————————————————– 
      $smtpServer = "smtp.domain.com"
      #—————————————————–
      $smtp = new-object Net.Mail.SmtpClient($smtpServer)
      $msg = new-object Net.Mail.MailMessage($emailFrom,$emailTo,$subject,$body)
      $msg.IsBodyHTML = $true
      $smtp.Send($msg)
      #write $obj
  }
} #end foreach
}

##END###

Skriptet schema lagde jag med “Task Scheduler” på en Windows Server 2008 “member” server i domänen. Användare som har ett lösenord som är 46 dagar gammalt eller äldre, kommer att få ett e-post meddelande som påminner dem att byta lösenord.

Referens:
Skriptet hittade jag i följande forum tråd: Powershell ms-DS-User-Account-Control-Computed (Jag fick dock modifiera det för att passa mina behov).

Written by marfelt

juli 4, 2009 vid 10:59

Lämna ett svar