Active-Directory

通過多個 OU 獲取 ADUser 並過濾結果

  • August 9, 2020

該腳本應該從多個 OU 中獲取使用者並將使用者分配給一個變數,然後從該變數中獲取使用者並根據超過 30 天的最後登錄日期過濾每個使用者。然後它會導出到包含一些我想要的資訊的 CSV。

問題是,當我到達foreach部分時,它搜尋整個目錄並且不使用我提供的變數中的使用者。

任何批評都非常感謝。

$30days = (get-date).adddays(-30)

$Users1 = Get-ADUser -SearchBase 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users2 = Get-ADUser -SearchBase 'OU=Users-Remote,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users3 = Get-ADUser -SearchBase 'OU=Contractors,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users4 = Get-ADUser -SearchBase 'OU=Temps,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users5 = Get-ADUser -SearchBase 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'
$Users6 = Get-ADUser -SearchBase 'OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com' -LdapFilter '(UserPrincipalName=*)(extensionAttribute9=*)'

$Users = $Users1,$Users2,$Users3,$Users4,$Users5,$Users6 
$useraccountsover30days = foreach ($user in $($Users)){Get-ADUser -filter {lastlogondate -le $30days} -Properties lastlogondate}

$lastlogonreadable = $useraccountsover30days | Select-Object SamAccountName,lastlogondate

   $lastlogonreadable | Export-Csv C:/Users/myname/Desktop/Usersover30days.csv 

我會對您目前的腳本提出一些建議。

首先,單個大型查詢幾乎總是比許多小型查詢執行得更好。因此get-aduser,我不會為每個目標 OU 單獨執行,而是將它們組合成一個呼叫,使用更高級別的公共 OU 作為搜尋庫。顯然,這最終可能會返回您不想包含的 OU 的結果。但是稍後過濾掉它們要快得多。

您還get-aduser為第一組查詢中的每個結果再次呼叫只是為了過濾 lastLogonDate。但是您可以將該過濾器與-ldapfilter原始查詢中的過濾器結合使用。只需將-filter版本轉換為等效-ldapfilter版本即可。這樣做的秘訣是知道 lastLogonDate 只是 lastLogonTimestamp 屬性的 Powershell 轉換版本。您可以將普通的 Powershell DateTime 值轉換為 lastLogonTimestamp 與該ToFileTime()方法一起使用的格式。

最後讓我感到困惑的是(UserPrincipalName=*)你的 ldapfilter 部分。在我接觸過的每個域中,這個屬性總是有一個值(就像 SamAccountName 或 DistinguishedName)。它可能與 的預設值不同<SamAccoutnName>@<DomainFQDN>,但它永遠不會為空。過濾器不一定會傷害任何東西。AD 在不需要時花費 CPU 週期進行評估只是一件額外的事情。但是,如果你有理由相信它在你的環境中可能是空的,那麼一定要把它留在裡面。

因此,如果我正確理解您的意圖,這就是我將如何修改您的腳本。

# make the comparison value using ToFileTime()
$30daysago = (Get-Date).AddDays(-30).ToFileTime()

# make the combined ldapfilter value
$LdapFilter = "(&(lastLogonTimestamp<=$30daysago)(extensionAttribute9=*)"

# make an array of the OU DNs you care about
$TargetOUs = @(
   "OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
   "OU=Users-Remote,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
   "OU=Contractors,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
   "OU=Temps,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
)

# define your common search base
$base = "OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"

# get your combined results and the additional attributes you care about
$OldUsers = get-aduser -ldapfilter $LdapFilter -searchbase $base -pr lastLogonDate

# convert the target OU list into a regular expression we can compare each DN against in a single comparison call
$regex = ""
$TargetOUs | %{ $regex += ".*," + [Regex]::Escape($_) + "$|" }
$regex = $regex.Substring(0,$regex.Length-1)

# filter the results that aren't in your target OUs
# (depending on your OU layout, it might be more efficient to flip this
#  and define the OUs you explicitly want to leave out)
$FilteredUsers = $OldUsers | ?{ $_.DistinguishedName -match $regex }

# export your CSV (sorted for good measure)
$FilteredUsers | select SamAccountName,LastLogonDate | sort LastLogonDate | export-csv C:/Users/myname/Desktop/Usersover30days.csv

PS 請注意不要將lastLogonTimestamp(或lastLogonDate)視為 100% 準確。根據設計,它可能會過期 9 到 14 天

引用自:https://serverfault.com/questions/782829