web-dev-qa-db-ja.com

複数のOUに対するGet-ADUserと結果のフィルター

このスクリプトは、複数のOUからユーザーを取得し、ユーザーを1つの変数に割り当てます。次に、その変数からユーザーを取得し、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 
2
Andrew Davis

現在のスクリプトで私が作成するいくつかの推奨事項があります。

まず、単一の大きなクエリは、ほとんどの場合、多くの小さなクエリよりもパフォーマンスが優れています。したがって、ターゲットOUごとに_get-aduser_を個別に実行するのではなく、より高いレベルの共通OUを検索ベースとして使用して、それらを1つの呼び出しに結合します。明らかに、これはあなたが含めたくないOUから結果を返すことになるかもしれません。しかし、後でそれらを除外する方がはるかに高速です。

また、lastLogonDateでフィルタリングするために、クエリの最初のセットからの結果ごとに_get-aduser_を再度呼び出しています。ただし、代わりにそのフィルターを元のクエリの_-ldapfilter_と組み合わせることができます。 _-filter_バージョンを同等の_-ldapfilter_バージョンに変換するだけです。これを行う秘訣は、lastLogonDateが、PowerShellで変換されたlastLogonTimestamp属性のバージョンであることを知っていることです。そして、通常のPowershell DateTime値を、lastLogonTimestampが ToFileTime() メソッドで使用する形式に変換できます。

最後に混乱したのは、ldapfilterの_(UserPrincipalName=*)_部分です。これまでに触れたすべてのドメインで、この属性には常に値があります(SamAccountNameやDistinguishedNameのように)。 _<SamAccoutnName>@<DomainFQDN>_のデフォルト値とは異なる場合がありますが、空になることはありません。フィルターは必ずしも何も傷つけていません。 ADがCPUサイクルを費やして、必要がない場合に評価を行うことは、1つ余分なことです。しかし、あなたの環境でそれが空であるかもしれないと信じる理由があるなら、必ずそれを残してください。

ですから、私があなたの意図を正しく理解した場合にスクリプトを変更する方法は次のとおりです。

_# 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 = @()
$TargetOUs += "OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
$TargetOUs += "OU=Users-Remote,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
$TargetOUs += "OU=Contractors,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com"
$TargetOUs += "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
_

追伸lastLogonTimestamp(またはlastLogonDate)を100%正確に扱うことに注意してください。 設計上、9〜14日古くなっています のいずれかになります。

4
Ryan Bolger

私は、OUを指定して次のように同じセットを複数回繰り返すことで、複数のOUに対する同様の要求を解決しました。

get-aduser -filter 'enabled -eq $true' -Properties Name, LastLogonDate, AccountExpirationDate, description, Department, title, UserPrincipalName -SearchBase "OU=Users,OU=US-Location,OU=Americas,DC=Domain,DC=Domain,DC=com" | Where-object {$_.lastlogondate -lt (get-date).AddDays(-30)} | Select-Object Name, LastLogonDate, AccountExpirationDate, description, Department, title, UserPrincipalName | Export-csv C:\temp\users-nologin-30.csv -Encoding UTF8 -Append -NoTypeInformation -Force -Delimiter ";"

Name、LastLogonDate、AccountExpirationDate、description、Department、title、UserPrincipalNameのプロパティを持つすべての有効なアカウントを取得し、csv-Fileに追加します。他の回答で述べたように、30日間は正確ではない可能性があるので、念のために44日間電話をかけることをお勧めします。

「LastLogonDate」が空の場合、ユーザーは一度もログオンしたことがなく、おそらく新しいアカウントです。

0
Crujach