Скрипты: Как узнать время последнего изменения пароля пользователей в AD?

D

diSmiSS

Тут решил на досуге перевести пару статеек, которые могут быть полезными, и решение которых не всегда лежит на поверхности или затруднено их ручное выполнение.
Если подобные вещи покажуться интересными могу продолжить. Все зависит от Вашего желания.... А для примера возьмем задачу которая возникает когда у нас не установлено время действия паролей в AD.
В ручную перепысывать время последнего изменения паролей пользователей неудобно поэтому возник следующий вопрос:

.Q: Как узнать время последнего изменения пароля пользователей в AD?
A: Создаем фалик с именем last_password_change.vbs и копируем туда следующее:
Код:
Option Explicit

Dim strLdapPath, objConnection, objChild
Dim lngTZBias, objUser, objPwdLastSet
Dim objShell, lngBiasKey, k

' Check that all required arguments have been passed
If Wscript.Arguments.Count < 1 Then
  Wscript.Echo "Arguments required. For example:" & vbCrLf _
    & "cscript last_password_change.vbs ou=test,dc=demo"
  Wscript.Quit(0)
End If

strLdapPath = Wscript.Arguments(0)

' Obtain local Time Zone bias from machine registry.
Set objShell = CreateObject("Wscript.Shell")
lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\"_
  & "TimeZoneInformation\ActiveTimeBias")
If UCase(TypeName(lngBiasKey)) = "LONG" Then
  lngTZBias = lngBiasKey
ElseIf UCase(TypeName(lngBiasKey)) = "VARIANT()" Then
  lngTZBias = 0
  For k = 0 To UBound(lngBiasKey)
    lngTZBias = lngTZBias + (lngBiasKey(k) * 256^k)
  Next
End If

Set objConnection = GetObject("LDAP://" & strLdapPath)
objConnection.Filter = Array("user")

For Each objChild In objConnection
     Set objPwdLastSet = objChild.pwdLastSet

     WScript.Echo objChild.Name & vbTab & _
       Integer8Date(objPwdLastSet, lngTZBias)
Next

Wscript.Echo "Operation Completed"

Function Integer8Date(objDate, lngBias)
' Function to convert Integer8 (64-bit) value to a date, adjusted for
' local time zone bias.
  Dim lngAdjust, lngDate, lngHigh, lngLow
  lngAdjust = lngBias
  lngHigh = objDate.HighPart
  lngLow = objdate.LowPart
' Account for error in IADslargeInteger property methods.
  If lngLow < 0 Then
    lngHigh = lngHigh + 1
  End If
  If (lngHigh = 0) And (lngLow = 0) Then
    lngAdjust = 0
  End If
  lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
    + lngLow) / 600000000 - lngAdjust) / 1440
' Trap error if lngDate is ridiculously huge.
  On Error Resume Next
  Integer8Date = CDate(lngDate)
  If Err.Number <> 0 Then
    On Error GoTo 0
    Integer8Date = #1/1/1601#
  End If
  On Error GoTo 0
End Function
Сохраняем и закрываем. Теперь запускаем shell. И запускаем созданный файл со следующими параметрами:
Код:
cscript last_password_change.vbs ou=test_object,dc=test_domain
где
  • ou=test_object - наименование Organizational Unit (например Users, Computers и т.д.)
  • dc=test_domain - название домена

В итоге shell выдаст подобный список такой список:
Код:
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
CN=User1             10/1/2002 4:26:53 PM
CN=User2             9/13/2004 8:55:17 AM
CN=User3             10/2/2002 3:50:50 PM
Operation Completed

Вот и все :). Жду откликов.
PS Тем кто хочет побороться за копирайты ниже привожу автора. Повторюсь, что я лишь перевел небольшую часть и выложил здесь.

.[size=-2]' Copyright by John Savill
' This is based on Richard Mueller's script on Interger8Date
' conversion, which is copyrighted as below.
' Copyright (c) 2003 Richard L. Mueller
' Hilltop Lab Web site - _http://www.rlmueller.net[/size]
 

Dredd2000

Турист
Регистрация
14 Окт 2004
Сообщения
98
Реакции
2
Credits
154
diSmiSS написал(а):
Тут решил на досуге перевести пару статеек, которые могут быть полезными, и решение которых не всегда лежит на поверхности или затруднено их ручное выполнение.
Если подобные вещи покажуться интересными могу продолжить. Все зависит от Вашего желания....

Отлично! А главное, полезно. Может, создать отдельную тему?
 
D

diSmiSS

Отлично! А главное, полезно. Может, создать отдельную тему?
Помойму она и так отдельная :). Если ты имел ввиду создать тему и пихать туда все что найдеться то потом сложно будет найти :(. К тому же поиском и так ни кто не пользуется.
Поэтому отдельные вопросы буду создавать в новых темах (если найдуться еще заинтересованные лица :) ). А все темы по этому поводу можно будет найти в каталоге тем.
 

kevg

Турист
Регистрация
5 Май 2006
Сообщения
4
Реакции
0
Credits
8
C:\last_password_change.vbs(13, 1) (null): 0x80005000

Вот ответ на выполнение данного скрипта
 

wildman

Турист
Регистрация
5 Апр 2004
Сообщения
19
Реакции
2
Credits
32
на 2000(srv, wrk), не получилось...
 

okun

Местный
Регистрация
3 Май 2005
Сообщения
2,042
Реакции
2,996
Credits
0
Active Directory является LDAP-совместимой реализацией службы каталогов, а всякая запись в каталоге LDAP состоит из одного или нескольких атрибутов и обладает уникальным именем (DN — англ. Distinguished Name).
Уникальное имя состоит из одного или нескольких относительных уникальных имен (RDN — англ. Relative Distinguished Name), разделённых запятой. Относительное уникальное имя имеет вид имяАтрибута=значение.
Уникальное имя может выглядеть, например, следующим образом: «cn=Иван Петров, ou=Сотрудники, dc=example, dc=com». На одном уровне каталога не может существовать двух записей с одинаковыми относительными уникальными именами.

Так, о чем это я :confused: Ага :)

Как правило, домены Active Directory именуются с использованием имен DNS, поэтому имя домена AD в общем случае состоит из нескольких уровней, разделенных точкой. Например ИМЯ_ДОМЕНА.COM.

Так как скрипт использует LDAP-запрос к AD, в параметрах скрипта нужно точно указывать полное имя домена, как (dc=ИМЯ_ДОМЕНА,dc=COM)

В примере, если test_domain=ИМЯ_ДОМЕНА.COM

cscript last_password_change.vbs ou=test_object,dc=test_domain
использовать как
cscript last_password_change.vbs ou=test_object,dc=ИМЯ_ДОМЕНА,dc=COM
 
  • Like
Реакции: htym

htym

Турист
Регистрация
22 Апр 2004
Сообщения
5
Реакции
0
Credits
4
вопрос вдогонку

Q: Как узнать время последнего изменения пароля пользователей в AD?

Отлично работает, глючит правда с русскими буквами, например если имя группы "Пользователи портала".

Возник другой вопрос:
Q: Как узнать время окондания действия пароля пользователей в AD?
Т.е. пусть пароль действует 42 дня, как изменить скрипт, чтобы показал когда пользователю настанет время сменить пароль или уже просрочено время?
 
Последнее редактирование модератором:

SoftIce

Местный
Регистрация
11 Янв 2007
Сообщения
82
Реакции
15
Credits
144
Можно использовать класс Win32_UserAccount и его свойство PasswordExpires

Для просмотра ссылки Войди или Зарегистрируйся можно забрать инструмент Scriptomatic, который поможет вам немного автоматизировать процесс написания скриптов и ориентироваться в свойствах классов.
Также можно воспользоваться обалденным инструментом того же мелкософта Для просмотра ссылки Войди или Зарегистрируйся

А Для просмотра ссылки Войди или Зарегистрируйся содержит огромное количество образцов скриптов, которыми можно пользоваться в готовом виде или изменять по своему усмотрению.
 

al_b1

Турист
Регистрация
26 Ноя 2013
Сообщения
5
Реакции
0
Credits
10
Для просмотра ссылки Войди или Зарегистрируйся

Pwd-Last-Set attribute

The date and time that the password for this account was last changed. This value is stored as a large integer that represents the number of 100 nanosecond intervals since January 1, 1601 (UTC). If this value is set to 0 and the User-Account-Control attribute does not contain the UF_DONT_EXPIRE_PASSWD flag, then the user must set the password at the next logon.
 

al_b1

Турист
Регистрация
26 Ноя 2013
Сообщения
5
Реакции
0
Credits
10
Determining Password Expiration Date (msDS-UserPasswordExpiryTimeComputed)

PowerShell script to get a simple list of all user accounts and see when their password was going to expire

$userInfo = @()
Import-Module ActiveDirectory
Get-ADuser -Filter * | %{
$sAMAccountName = $null
$sAMAccountName = $_.sAMAccountName
$pwdExpire = $null
$pwdExpire = (Get-ADuser $sAMAccountName -Properties "msDS-UserPasswordExpiryTimeComputed")."msDS-UserPasswordExpiryTimeComputed"
If ($pwdExpire -ne 9223372036854775807){
$pwdExpire = Get-Date -Date ([DateTime]::FromFileTime([Int64]::parse($pwdExpire))) -Format "yyyy-MM-dd HH:mm:ss"
} Else {
$pwdExpire = "PWD Never Expires"
}
$userInfoEntry = "" | Select "Logon Account","Pwd Expire"
$userInfoEntry."Logon Account" = $sAMAccountName
$userInfoEntry."Pwd Expire" = $pwdExpire
$userInfo += $userInfoEntry
}
Clear-Host
$userInfo | FT -AutoSize

image_thumb46.png
 

lexazam

Турист
Регистрация
24 Дек 2015
Сообщения
4
Реакции
0
Credits
8
Спасибо, у меня работает:)
 

bokcep

Турист
Регистрация
28 Апр 2016
Сообщения
1
Реакции
0
Credits
2
Подскажите пожалуйста, а как переделать этот скрипт если нет домена?