Active Directory(AD)で「このユーザーは本当にいつ最後にログインしたのか?」を正確に知ろうとすると、lastLogon・lastLogonTimestamp・LastLogonDate の違いが壁になります。属性の意味や更新タイミングをきちんと理解しておかないと、「毎日ログインしているのに90日未使用として誤削除」「一部アプリのログインが全く見えていない」といった事故につながります。本記事では、それぞれの属性の違いと使い分け、さらに監査ログやクラウド IdP を含めた“実務的な最終ログイン監視”の考え方を、PowerShell の具体例付きで詳しく解説します。
Active Directoryの「最終ログイン」がややこしい理由
Active Directory には「最終ログインっぽい」属性が複数存在します。
lastLogonlastLogonTimestampLastLogonDate(PowerShell で見える表示用のプロパティ)
名前だけ見るとどれも似ているため、以下のような混乱が起こりがちです。
- 「ユーザーは毎日ログインしているのに、
lastLogonTimestampが2週間くらい変わらない。壊れているのでは?」 - 「ドメイン コントローラー(DC)が複数あるが、どの DC の
lastLogonを見ればいいのか分からない」 - 「クラウドアプリにサインインしているのに、AD の最終ログオン属性が一切更新されない」
これらはすべて、「AD の属性がどう更新され、どこまでレプリケートされるのか」を理解していれば説明がつきます。逆に言えば、ここを理解せずに「なんとなくそれっぽい属性」を監視すると、重大な見落としや誤判定につながります。
lastLogon / lastLogonTimestamp / LastLogonDate の基本
まずは3つの属性の意味と違いを整理します。
属性の速習比較表
| 項目 | lastLogon | lastLogonTimestamp | LastLogonDate |
|---|---|---|---|
| 更新タイミング | ユーザーがログオンしたその DC のみで、ログオンごとに更新(秒単位) | レプリケートされるが、約9〜14日おきにしか更新されない(負荷軽減用のしきい値あり) | lastLogonTimestamp を日付型に変換した表示用プロパティ(PowerShell などで参照) |
| レプリケーション | されない(DC ごとに別の値を持つ) | ドメイン全体でレプリケートされる | ―(属性そのものではなく、表示専用) |
| 用途 | 秒単位での「真の最終ログオン時刻」が必要な場合(要:全 DC の値を集約) | 「90日以上未使用」のような非アクティブアカウントの棚卸など、日単位の粗さで十分な用途 | レポート表示・目視確認・PowerShell スクリプトでのフィルタなど |
| 注意点 | 単一の DC だけ見ても正しくない(その DC にログオンしていない可能性がある) | 毎日ログインしていても、2週間近く値が変わらないのが仕様 | 意味は lastLogonTimestamp と同じ。あくまで形式を変えただけと理解する |
特に重要なのが、lastLogonTimestamp の更新ロジックです。
- 「現在時刻 −
lastLogonTimestampの値」 が、既定値(14日)からランダムに短縮されたしきい値以上になったときに更新される - そのため、頻繁にログインしても、値はしばらく変わらないのが正常
つまり lastLogonTimestamp は「最近 2週間のどこかでログインしたか」を判定するには十分ですが、「昨日の15:03が最後」といった精密な情報を求める用途にはまったく向きません。
lastLogon の特徴(DCごとにバラバラ)
lastLogon は各 DC がローカルに持っている「その DC に対する最終ログオン」の値です。
- ユーザーが DC1 でログオンすれば、DC1 の
lastLogonが更新される - その後 DC2 でログオンすると、DC2 の
lastLogonだけが新しくなり、DC1 は古いまま - これらはドメイン内でレプリケートされないため、DC ごとに異なる値を持つ
したがって、「ユーザーの真の最終ログオン」を知りたい場合は、すべての DC から lastLogon を取得し、その中の最大値を採用する必要があります。これを面倒くさいからといって 1台の DC の値だけを見てしまうと、「本当はログインしているのに未使用と判定してアカウントを無効化してしまった」といった事故が起きます。
LastLogonDate の正体
Get-ADUser で -Properties LastLogonDate を指定すると、LastLogonDate という DateTime 型のプロパティが取得できます。これは属性としてスキーマにあるわけではなく、
lastLogonTimestamp(NT 時刻、64bit の整数)を- 人間が読みやすい日付形式(DateTime)に変換したもの
です。つまり、意味は lastLogonTimestamp と完全に同じであり、「表示のための便利プロパティ」と理解すると混乱が減ります。
lastLogon と lastLogonTimestamp の動きをイメージで理解する
DC が3台(DC1 / DC2 / DC3)ある環境を例に、ユーザー user1 のログインの流れを想像してみます。
| 時刻 | ログイン先 DC | DC1.lastLogon | DC2.lastLogon | DC3.lastLogon | lastLogonTimestamp(ドメイン共通) |
|---|---|---|---|---|---|
| 4/1 09:00 | DC1 | 4/1 09:00 | (未ログインのため古い値) | (未ログインのため古い値) | 4/1 09:00 付近に更新される可能性(しきい値次第) |
| 4/2 10:00 | DC2 | 4/1 09:00 | 4/2 10:00 | (古い値) | 4/1 09:00 のまま変わらないかもしれない |
| 4/3 11:00 | DC3 | 4/1 09:00 | 4/2 10:00 | 4/3 11:00 | しきい値条件を満たせば 4/3 に更新される |
このように、
- 直近のログオンは DC3 なので、真の最終ログオンは 4/3 11:00
- しかし
lastLogonTimestampは、更新条件を満たさなければ 4/1 から動かないこともある
という状態が普通に発生します。ここから見えてくる指針は次の通りです。
- 精密な時刻が必要なら:全 DC から
lastLogonを取得し最大値を使う - 「90日未使用か」など大まかな判定なら:
lastLogonTimestamp/LastLogonDateで十分
ユースケース別:どの属性を使うべきか
よくある用途ごとに、どの属性を使うべきかを整理します。
| ユースケース | 推奨属性 | 理由 |
|---|---|---|
| 「そのユーザーが本当に最後にログインした瞬間」を秒単位で知りたい | lastLogon(全 DC の最大値) | 各 DC のローカル値が最も正確。全 DC から取得して最大値を取れば、「真の最終ログオン」が分かる。 |
| 非アクティブアカウントの棚卸(例:90日以上未使用ユーザーの抽出) | lastLogonTimestamp / LastLogonDate | 日単位の粗さで十分。レプリケートされるので、ドメイン全体を1回の検索で判定でき、処理も高速。 |
| 定期レポートで「最終ログイン日」を一覧表示したい | LastLogonDate | すでに DateTime に変換されており、Export-Csv などで扱いやすい。 |
| インシデント調査の補助情報として「直近ログオン」を確認したい | lastLogon+DCのセキュリティログ | 秒精度の時刻と、実際のログオンイベント(4624)などを組み合わせると、より正確なタイムラインが作れる。 |
実務でそのまま使える PowerShell レシピ
非アクティブアカウントの棚卸(例:90日未使用ユーザー)
最もよく使うのが「長期間ログインしていないアカウントの棚卸」です。LastLogonDate を使うと非常にシンプルに書けます。
Get-ADUser -Filter * -Properties LastLogonDate |
Where-Object { $_.LastLogonDate -lt (Get-Date).AddDays(-90) } |
Select-Object SamAccountName, LastLogonDate |
Export-Csv -Path ".\InactiveUsers_90days.csv" -NoTypeInformation -Encoding UTF8
ポイント:
- ドメイン全体で一貫した値を、1回のクエリで取得できる(DCを意識しなくてよい)
Export-Csvまで一気に書いておくと、棚卸レポートを定期的に生成しやすい- OU を限定したい場合は
-SearchBaseを併用する
Get-ADUser -SearchBase "OU=Users,OU=Tokyo,DC=example,DC=com" `
-Filter * -Properties LastLogonDate |
Where-Object { $_.LastLogonDate -lt (Get-Date).AddDays(-90) } |
Select-Object SamAccountName, LastLogonDate
正確な最終ログオン(全DCから lastLogon を集約)
特定ユーザーの真の最終ログイン時刻を、秒単位で知りたい場合の定番パターンです。
$User = "samAccountName"
$DCs = (Get-ADDomainController -Filter *).HostName
$max = 0
foreach ($dc in $DCs) {
$u = Get-ADUser $User -Server $dc -Properties lastLogon
if ($u.lastLogon -gt $max) { $max = $u.lastLogon }
}
[DateTime]::FromFileTimeUtc($max) # これが真の最終ログオン(UTC)
さらに実務では、複数ユーザーを一括で処理したいケースがほとんどです。たとえば CSV で samAccountName を受け取り、全 DC の lastLogon を集約して出力するスクリプト例は次のようになります。
$users = Import-Csv .\target_users.csv # 列名は SamAccountName を想定
$dcs = (Get-ADDomainController -Filter *).HostName
$result = @()
foreach ($user in $users) {
$max = 0
foreach ($dc in $dcs) {
$u = Get-ADUser $user.SamAccountName -Server $dc -Properties lastLogon -ErrorAction SilentlyContinue
if ($u -and $u.lastLogon -gt $max) { $max = $u.lastLogon }
}
$obj = [PSCustomObject]@{
SamAccountName = $user.SamAccountName
LastLogon = if ($max -gt 0) { [DateTime]::FromFileTimeUtc($max) } else { $null }
}
$result += $obj
}
$result | Export-Csv .\LastLogon_AllDC.csv -NoTypeInformation -Encoding UTF8
これをタスクスケジューラやジョブとして定期的に実行すれば、「秒単位の最終ログオン一覧」を社内の監査部門などへ提供することもできます。
NT 時刻(lastLogonTimestamp)の変換
lastLogon や lastLogonTimestamp は、NT 時刻という 64bit の整数(1601/01/01 からの100ナノ秒単位)で保存されています。PowerShell で変換するには以下の通りです。
[DateTime]::FromFileTimeUtc(<lastLogonTimestampの値>)
コマンドプロンプトから確認したい場合は、w32tm コマンドが便利です。
w32tm /ntte <値>
ただし、普段は LastLogonDate を使えば自動的に変換されるため、NT 時刻を直接扱う機会は多くありません。トラブルシューティングや低レベルな調査の際に覚えておく程度で十分です。
「ログインしているのに属性が更新されない」典型パターン
現代的な環境では、「ユーザーはクラウドアプリをバリバリ使っているのに、AD の lastLogon や lastLogonTimestamp がほとんど動かない」という状況がよくあります。その理由は、「AD が直接認証していない」からです。
フェデレーション・クラウド認証の場合
代表的なパターンとして、次のような構成が挙げられます。
- ユーザーはブラウザから SaaS(例:Microsoft 365、Salesforce など)にアクセス
- 認証は Azure AD(Microsoft Entra ID)や外部 IdP(Okta など)が担当
- オンプレ AD は、あくまで IdP への同期元 or 連携元に過ぎない
この場合、ユーザーが日々 SaaS にサインインしていても、
- オンプレ AD の DC に対して Kerberos/NTLM の認証が発生しない
- 結果として
lastLogon/lastLogonTimestampが一切更新されない
という状況になります。「AD の属性だけを見て、ユーザーの実際の利用状況を完全に把握することは不可能」である、ということを前提に設計する必要があります。
キャッシュ/トークン再利用による未更新
AD で直接認証している場合でも、次のような事情で属性がなかなか更新されないことがあります。
- Kerberos チケットがキャッシュされており、一定期間は再認証が発生しない
- SSO により OS へのログオンのみで、その後のアプリ利用はトークン再利用で済んでしまう
- アプリが内部的にサービスアカウントを使い、ユーザー本人の AD 認証が発生していない
このようなケースでは、「アプリの利用=AD への新規ログオン」とは限らないため、lastLogon や lastLogonTimestamp をアプリ利用の指標として使うのは危険です。
AD属性だけに頼らない監視設計:監査ログと IdP/アプリログの活用
実務的に「ログイン状況を監視したい」という要求に答えるには、AD の属性だけでは不十分です。次のようなログを組み合わせて設計するのがベストプラクティスです。
1. DC のセキュリティ監査ログ
- イベント ID 4624(アカウントのログオンに成功しました)
- イベント ID 4768(Kerberos 認証チケット要求)
- イベント ID 4776(ドメイン コントローラーがアカウントの資格情報を検証しました)
これらは「AD で実際に認証処理が走った」という事実を示してくれます。lastLogon と組み合わせて、次のようなことが可能になります。
- 最終ログオン属性では見えない、「一時的なログオン試行」の洗い出し
- 特定期間中の異常なログオン(深夜のログオン、海外 IP からのアクセスなど)の検出
2. IdP(Azure AD / AD FS 等)のサインインログ
クラウドアプリやフェデレーション環境では、IdP 側がサインインログを持っています。代表例:
- Azure AD(Microsoft Entra ID)のサインインログ
- AD FS の監査ログ
- サードパーティ IdP のサインイン履歴
オンプレ AD の属性では見えない SaaS ログインも、これらのログには記録されています。特にハイブリッド環境では、オンプレ AD のログとクラウド IdP のログを組み合わせて分析することが重要です。
3. アプリケーション・プロキシのアクセスログ
さらに一部の重要システムでは、アプリケーション自体の監査ログやリバースプロキシ(WAF / SWG など)のアクセスログも重要な情報源になります。
- アプリケーション固有の操作履歴(ログイン後の行動を追跡)
- プロキシレベルでの接続元 IP・UserAgent・地理情報など
4. SIEM / SOAR による集約と可視化
これら各種ログは、最終的に SIEM(Security Information and Event Management)や SOAR に集約し、ダッシュボードや検知ルールとして活用するのが理想です。
- 「過去90日間一度もログインしていない AD アカウント」
- 「過去30日間で1回しかクラウドにサインインしていない VIP アカウント」
- 「通常とは異なる国からのアクセスが急増しているユーザー」
などのルールを組み合わせることで、単に「ログインした/していない」を超えた、より高度なアカウント監視が可能になります。
ハイブリッド環境での「最終ログイン」設計の考え方
オンプレ AD と Azure AD(Entra ID)を併用している環境では、次のような方針を取ると整理しやすくなります。
- オンプレシステムの最終ログイン:
lastLogon(全 DC 集約)+ DC 監査ログ - クラウドサービスの最終サインイン:Azure AD サインインログ
- アカウント棚卸:
lastLogonTimestamp/LastLogonDateをベースにしつつ、必要に応じてクラウドのログも加味
よくある失敗例として、
- 「Azure AD のみで使っているアカウントなのに、オンプレ AD の
lastLogonTimestampを見て未使用判定してしまう」 - 「オンプレ AD では使われていないが、クラウドでは重要な管理用アカウントである」
といったケースがあります。「どの認証基盤で、どのシステムにアクセスしているのか」を整理し、それぞれに合った最終ログイン指標を選ぶことが重要です。
よくある質問と落とし穴
Q. 「lastLogonTimestamp が 0(未設定)のユーザー」がたくさんいる
新規に作成したばかりのアカウントや、長期間一度もログインしていないアカウントでは、lastLogonTimestamp が 0 のままということがあります。その場合は、
lastLogonTimestampが 0 かどうかを条件に加える- 必要に応じて
whenCreatedなどの属性と組み合わせて判断する
といった工夫が必要です。
Q. コンピューターアカウントの最終ログオンはどう見る?
基本的な考え方はユーザーと同じですが、コンピューターアカウントの場合は「起動してドメインに参加したとき」や「パスワード変更時」などにログオンが発生します。サーバーの退役やクライアントの棚卸では、
Get-ADComputerでLastLogonDateを取得- 長期間ログオンしていないコンピューターを洗い出す
というパターンがよく使われます。ただし、常時起動のサーバーなどはログオン頻度が低くても正常なことがあるため、システムの性質も踏まえて判断することが重要です。
Q. RODC(読み取り専用 DC)がある場合は?
RODC は一部属性の書き込みが制限されるため、lastLogon / lastLogonTimestamp の扱いが通常の DC と異なる点があります。RODC 経由だけでログオンしている端末が多い拠点では、「最終ログイン情報をどの DC で見るか」をあらかじめ設計しておくと混乱が少なくなります。可能であれば、ログオンのルートとなる書き込み可能 DC の監査ログも併せて参照できるようにしておきましょう。
Q. サービスアカウントの棚卸にも使える?
サービスアカウントは、人間のユーザーとはログオンパターンが異なります。たとえば、
- スケジュールタスクや Windows サービスとしてログオンしている
- アプリケーションプールの ID として使われている
などです。この場合も lastLogon / lastLogonTimestamp は参考になりますが、
- 「誰も使っていないサービスが残っているだけなのに、最終ログオンだけは定期的に更新されている」
- 逆に、「重要なサービスだが、たまたま再起動しておらずログオンイベントが少ない」
といったケースもあり得ます。サービスアカウントの棚卸では、属性だけでなく、「どのサーバーでどのサービスに紐付いているか」という構成情報と組み合わせて判断するのが安全です。
まとめ:最終ログイン監視の指針
最後に、本記事の要点を整理します。
- 厳密な“最新ログイン時刻”が必要な場合は、
lastLogonを全 DC から取得し、最大値を採用する。 - 非アクティブアカウントの棚卸(例:90日未使用)には、レプリケートされる
lastLogonTimestampまたは表示用のLastLogonDateを使う。 lastLogonTimestampは9〜14日程度のラグを持って更新されるのが仕様であり、「毎日ログインしているのに変わらない」のは正常。- クラウドアプリやフェデレーション認証の場合、オンプレ AD の属性は更新されないことが多い。DC の監査ログや Azure AD(Entra ID)などのサインインログを必ず併用する。
- AD の属性だけではすべてのログイン履歴を網羅できない。DC 監査ログ+IdP ログ+アプリログを SIEM 等で統合し、「どの認証基盤で、どのシステムにアクセスしているか」を意識した設計が重要。
これらのポイントを押さえておけば、「なぜこのユーザーの最終ログインがこうなっているのか?」を説明できるようになり、アカウント棚卸やセキュリティ監視の精度が大きく向上します。単に属性を眺めるのではなく、その裏でどのような認証フローとレプリケーションが行われているのかをイメージしながら、最適な監視方式を設計していきましょう。

コメント