概要・前提

Active Directory(AD)ユーザーの棚卸には net user /domain(コマンドプロンプト)PowerShell の Active Directory モジュール(Get-ADUser)の2通りがあります。PowerShell 版のほうが取得できる情報が豊富で一括処理も容易です。

前提・必要権限

  • ドメインコントローラー、またはドメイン参加済みの Windows Server で実行
  • PowerShell モジュール:ActiveDirectory(RSAT 機能または AD DS サーバーに同梱)
  • 最低限 Domain Users 権限で読み取り可能。ロック解除などの変更操作は Domain Admins 以上が必要

Active Directory モジュールのインポート

# モジュールのインポート(未インストールの場合は RSAT をインストール)
Import-Module ActiveDirectory

# RSAT インストール(Windows Server)
Install-WindowsFeature RSAT-AD-PowerShell

# RSAT インストール(Windows 10/11)
Add-WindowsCapability -Online -Name "Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0"

ユーザー一覧の取得

【net user /domain】ユーザー一覧

REM ドメイン上の全ユーザー一覧
net user /domain

REM 特定ユーザーの詳細
net user ユーザー名 /domain

【PowerShell】全ドメインユーザーを取得

# 基本情報を一覧表示
Get-ADUser -Filter * -Properties LastLogonDate, PasswordExpired, PasswordNeverExpires, Enabled |
  Select-Object SamAccountName, DisplayName, Enabled, LastLogonDate, PasswordExpired, PasswordNeverExpires |
  Sort-Object SamAccountName |
  Format-Table -AutoSize

【PowerShell】CSV エクスポート

Get-ADUser -Filter * -Properties * |
  Select-Object SamAccountName, DisplayName, GivenName, Surname, Enabled,
    LastLogonDate, PasswordExpired, PasswordNeverExpires, PasswordLastSet,
    LockedOut, AccountExpirationDate, Description, Department, Title |
  Export-Csv -Path "C:\audit\ad_users.csv" -NoTypeInformation -Encoding UTF8

【PowerShell】特定 OU 配下のユーザーを取得

$ou = "OU=Users,DC=example,DC=com"
Get-ADUser -Filter * -SearchBase $ou -Properties LastLogonDate, Enabled |
  Select-Object SamAccountName, DisplayName, Enabled, LastLogonDate |
  Format-Table -AutoSize

ロック状態の確認

【net user /domain】ロック状態の確認

REM "Account lockout" 行が Yes の場合はロック中
net user ユーザー名 /domain

【PowerShell】ロック中ユーザーを一覧表示

Search-ADAccount -LockedOut | Select-Object SamAccountName, DisplayName, LockedOut, LastLogonDate |
  Format-Table -AutoSize

【PowerShell】全ユーザーのロック状態を確認

Get-ADUser -Filter * -Properties LockedOut, LastLogonDate |
  Select-Object SamAccountName, Enabled, LockedOut, LastLogonDate |
  Where-Object { $_.LockedOut -eq $true }

ロック解除

# 単一ユーザーのロック解除
Unlock-ADAccount -Identity "ユーザー名"

# 全ロックユーザーを一括解除(注意:棚卸後に実施すること)
Search-ADAccount -LockedOut | Unlock-ADAccount

最終ログイン日時

AD の最終ログイン情報は LastLogon(各 DC に個別保存)と LastLogonDate(レプリケーション済み、約14日遅延あり)の2属性があります。棚卸では通常 LastLogonDate を使用します。

【net user /domain】最終ログイン確認

REM "Last logon" 行で確認
net user ユーザー名 /domain

【PowerShell】全ユーザーの最終ログイン日時を一覧

Get-ADUser -Filter * -Properties LastLogonDate |
  Select-Object SamAccountName, DisplayName, Enabled, LastLogonDate |
  Sort-Object LastLogonDate -Descending |
  Format-Table -AutoSize

【PowerShell】より正確な LastLogon を全 DC から収集

# 全ドメインコントローラーから LastLogon を取得して最新値を選択
$users = Get-ADUser -Filter * -Properties SamAccountName, DisplayName
$dcs   = Get-ADDomainController -Filter *

$results = foreach ($user in $users) {
  $latest = $null
  foreach ($dc in $dcs) {
    $logon = Get-ADUser -Identity $user.SamAccountName -Server $dc.HostName `
               -Properties LastLogon -ErrorAction SilentlyContinue |
               Select-Object -ExpandProperty LastLogon
    if ($logon -gt $latest) { $latest = $logon }
  }
  [PSCustomObject]@{
    SamAccountName = $user.SamAccountName
    DisplayName    = $user.DisplayName
    LastLogon      = if ($latest) { [DateTime]::FromFileTime($latest) } else { "未ログイン" }
  }
}
$results | Sort-Object LastLogon -Descending | Format-Table -AutoSize

特権の確認

AD における特権グループは Domain AdminsEnterprise AdminsSchema AdminsAdministrators です。

【net group /domain】特権グループのメンバー確認

REM Domain Admins
net group "Domain Admins" /domain

REM Enterprise Admins
net group "Enterprise Admins" /domain

REM Schema Admins
net group "Schema Admins" /domain

【PowerShell】Domain Admins のメンバーを取得

Get-ADGroupMember -Identity "Domain Admins" -Recursive |
  Get-ADUser -Properties LastLogonDate, Enabled |
  Select-Object SamAccountName, DisplayName, Enabled, LastLogonDate |
  Format-Table -AutoSize

【PowerShell】主要特権グループをまとめて確認

$privilegedGroups = @("Domain Admins","Enterprise Admins","Schema Admins","Administrators","Account Operators","Backup Operators")

foreach ($group in $privilegedGroups) {
  Write-Host "=== $group ===" -ForegroundColor Cyan
  Get-ADGroupMember -Identity $group -Recursive -ErrorAction SilentlyContinue |
    Where-Object { $_.objectClass -eq "user" } |
    Get-ADUser -Properties Enabled, LastLogonDate |
    Select-Object SamAccountName, Enabled, LastLogonDate |
    Format-Table -AutoSize
}

グループに所属しているユーザー一覧

【net group /domain】グループ一覧の取得

REM ドメイングループの一覧
net group /domain

REM 特定グループのメンバー一覧
net group "グループ名" /domain

【PowerShell】全グループとメンバーをフラット表示

Get-ADGroup -Filter * | ForEach-Object {
  $group = $_.Name
  Get-ADGroupMember -Identity $_ -ErrorAction SilentlyContinue |
    Where-Object { $_.objectClass -eq "user" } |
    ForEach-Object {
      [PSCustomObject]@{
        Group = $group
        User  = $_.SamAccountName
      }
    }
} | Sort-Object Group | Format-Table -AutoSize

【PowerShell】特定ユーザーが所属するグループを確認

$username = "testuser"
(Get-ADUser -Identity $username -Properties MemberOf).MemberOf |
  ForEach-Object { (Get-ADGroup $_).Name } |
  Sort-Object

【PowerShell】グループ・メンバー一覧を CSV エクスポート

Get-ADGroup -Filter * | ForEach-Object {
  $group = $_.Name
  Get-ADGroupMember -Identity $_ -ErrorAction SilentlyContinue |
    Where-Object { $_.objectClass -eq "user" } |
    ForEach-Object {
      [PSCustomObject]@{
        Group = $group
        User  = $_.SamAccountName
      }
    }
} | Export-Csv "C:\audit\ad_group_members.csv" -NoTypeInformation -Encoding UTF8

パスワード期限

【net user /domain】パスワード期限の確認

REM "Password expires" 行で確認
net user ユーザー名 /domain

【PowerShell】パスワード無期限ユーザーを抽出

Get-ADUser -Filter { PasswordNeverExpires -eq $true } -Properties PasswordNeverExpires, Enabled, LastLogonDate |
  Select-Object SamAccountName, DisplayName, Enabled, LastLogonDate |
  Format-Table -AutoSize

【PowerShell】パスワード期限切れユーザーを抽出

Get-ADUser -Filter { Enabled -eq $true } -Properties PasswordExpired, PasswordLastSet, LastLogonDate |
  Where-Object { $_.PasswordExpired -eq $true } |
  Select-Object SamAccountName, DisplayName, PasswordLastSet, LastLogonDate |
  Format-Table -AutoSize

【PowerShell】30 日以内に期限切れになるユーザー

$threshold = (Get-Date).AddDays(30)
Get-ADUser -Filter { Enabled -eq $true } -Properties PasswordExpired, msDS-UserPasswordExpiryTimeComputed |
  Where-Object {
    $_."msDS-UserPasswordExpiryTimeComputed" -ne 0 -and
    [DateTime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed") -lt $threshold
  } |
  Select-Object SamAccountName,
    @{N="期限切れ日"; E={ [DateTime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed") }} |
  Sort-Object "期限切れ日"

一定期間未使用ユーザー

【PowerShell】90 日以上ログインしていない有効ユーザーを抽出

$threshold = (Get-Date).AddDays(-90)
Get-ADUser -Filter { Enabled -eq $true } -Properties LastLogonDate |
  Where-Object { $_.LastLogonDate -lt $threshold -or $_.LastLogonDate -eq $null } |
  Select-Object SamAccountName, DisplayName, LastLogonDate |
  Sort-Object LastLogonDate |
  Format-Table -AutoSize

【PowerShell】Search-ADAccount を使う方法

# 90 日以上未ログイン
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -UsersOnly |
  Select-Object SamAccountName, LastLogonDate, Enabled |
  Sort-Object LastLogonDate |
  Format-Table -AutoSize

【PowerShell】CSV エクスポート

$inactiveDays = 90
$threshold    = (Get-Date).AddDays(-$inactiveDays)

Get-ADUser -Filter { Enabled -eq $true } -Properties LastLogonDate, Department, Title |
  Where-Object { $_.LastLogonDate -lt $threshold -or $_.LastLogonDate -eq $null } |
  Select-Object SamAccountName, DisplayName, Department, Title, LastLogonDate |
  Export-Csv "C:\audit\inactive_ad_users.csv" -NoTypeInformation -Encoding UTF8

無効化されたユーザー

【net user /domain】無効化ユーザーの確認

REM "Account active" が No のユーザーが無効状態
net user ユーザー名 /domain

【PowerShell】無効化されたユーザーを一覧表示

Get-ADUser -Filter { Enabled -eq $false } -Properties LastLogonDate, Department, WhenChanged |
  Select-Object SamAccountName, DisplayName, Department, LastLogonDate, WhenChanged |
  Sort-Object WhenChanged -Descending |
  Format-Table -AutoSize

【PowerShell】有効期限切れのユーザーを一覧表示

Search-ADAccount -AccountExpired -UsersOnly |
  Select-Object SamAccountName, DisplayName, AccountExpirationDate, Enabled |
  Format-Table -AutoSize

【PowerShell】有効・無効ユーザーを区分して全件 CSV 出力

Get-ADUser -Filter * -Properties Enabled, LastLogonDate, AccountExpirationDate, Department, Title |
  Select-Object SamAccountName, DisplayName,
    @{N="状態"; E={ if ($_.Enabled) { "有効" } else { "無効" } }},
    LastLogonDate, AccountExpirationDate, Department, Title |
  Export-Csv "C:\audit\ad_users_all.csv" -NoTypeInformation -Encoding UTF8