I'm working on scripts which send emails to users 14, 10, 7, 3 days before password expiring. Password expires in 60 days.
If I set like below it works for accounts with 3 and less days to expiring. I don't want accounts with 2 days, 1 day, etc.
$ExpiringUsers = $AdUsers | where PasswordLastSet -lt (get-date).AddDays(-57)
If I set like below it doesn't work at all
$ExpiringUsers = $AdUsers | where PasswordLastSet -eq (get-date).AddDays(-57)
How to set equal 3 days not more not less.
Thanks!
CodePudding user response:
You need to define and filter by a time range, for example, set equal 3 days not more not less would be like this:
$start = [datetime].AddDays(-3) # => April 2 at 12:00 AM
$finish = [datetime].AddDays(-2) # => April 3 at 12:00 AM
# Note `-lt $finish` instead of `-le $finish`
$AdUsers | Where-Object { $_.PasswordLastSet -ge $start -and $_.PasswordLastSet -lt $finish }
CodePudding user response:
A better approach is to use msDS-UserPasswordExpiryTimeComputed
for checking how long until the account credential expires:
$serviceAccounts =
'[email protected]',
'[email protected]
$daysLeft = 20
$expiringAccounts = ( $serviceAccounts | Foreach-Object {
Get-AdUser -Filter "(UserPrincipalName -eq '$_' -Or sAMAccountName -eq '$_' ) -And ( PasswordNeverExpires -eq 'false' )" -Properties msDS-UserPasswordExpiryTimeComputed |
Where-Object { ( New-TimeSpan -Start $currentDate -End ( [DateTime]::FromFileTime( $_.'msDS-UserPasswordExpiryTimeComputed' ) ) ).Days -le $daysLeft }
} )
- As written, this code will gather the accounts expiring within 20 days. Adjust
$daysLeft
to control the remaining threshold until expiry. - Note that
[DateTime]::FromFileTime
is required to transpose the value ofmsDS-UserPasswordExpiryTimeComputed
from the file-time format it is stored in AD as to a workableDateTime
object. - You can define the account as a
sAMAccountName
or inUniversal Principal Name (UPN)
format. - This also exemplifies using AD filters in order to have AD return only the objects you need for this query, minimizing the local processing performed with
Where-Object
.- The notable exception is
msDS-UserPasswordExpiryTimeComputed
; because it is a Constructed Attribute within Active Directory, neither AD filters or LDAP filters can evaluate it and so this must be done via additional local processing. - Here is an answer I have also written which goes into deeper detail on using the AD filter syntax.
- The notable exception is
What is wrong with PasswordLastSet
for checking credential expiration if you know the account's lifecycle?
The problem with checking PasswordLastSet
is that, while it works, if the threshold until expiry changes on the Active Directory side, your script will need to be updated or it will incorrectly identify accounts whose credential is set to expire soon. It also becomes more difficult to track which accounts are beholden to different lifecycles in environments where not all accounts are beholden to the same security policies.