個人ブログから過去記事を移転。
方法2に関してはこちらのほうが良記事 → ファイルサーバのアクセスログをPowerShellで取得する
サーバーの共有フォルダへのアクセスがどれだけあるのか統計を取りたい。
以下要件
- Windowsの標準機能で実装
- 同時接続100人程度
方法1:SMBを監視する
ネットワーク上にある共有フォルダなら、SMB
のイベントを監視すればいいじゃない。
ということでプロトコルの監視。
- 利点
- 事前の仕掛けが必要ない
- 欠点
- 常時プロセスが動きっぱなし
- ローカルのアクセスは把握できない
WMIEvent
を使う方法を紹介。
NetEvent
を使う場合は注釈参照1。
永続化するにはMOF作成が必要っぽい。
$smb_namespace = "root\Microsoft\Windows\SMB"
$smb_query = "Select * From __InstanceCreationEvent WITHIN 1 Where TargetInstance ISA 'MSFT_SmbOpenFile'"
$fs = New-Object System.IO.StreamWriter("D:\log.txt",$true,[Text.Encoding]::GetEncoding("UTF-8"))
$fs.AutoFlush = $true
# イベントが発生すると実行されるAction
$smb_event = {
$e = $Event.SourceEventArgs.NewEvent
$out = [DateTime]::FromFileTime($e.TIME_CREATED).ToString() + "|" + $e.TargetInstance.ClientUserName + "|" + $e.TargetInstance.Path
$fs.WriteLine($out)
}
# 「SMBLog」という名前のイベントを作成
Register-WmiEvent -Namespace $smb_namespace -Query $smb_query -SourceIdentifier "SMBLog" -Action $smb_event
# Get-EventSubscriberで動作中のイベントを確認
# Unregister-eventでイベント停止
方法2:Windowsログの監査ログを利用する
Windowsの監査ログを使って特定のファイルアクセスを監視する
上記記事を参考に監査ポリシーの設定をいじると、イベントビューアで閲覧可能なログを吐いてくれる。
- 利点
- 常時ジョブを走らせなくていい
- 欠点
- ログの取得が細かく取捨選択出来ないため、不要なログが貯まる。例えば、1ファイル開くだけでハンドル操作やらオープンやらのログが大量に発生する。
XPath
で抽出条件を指定
$fromDay = -20
$days = 20
$startTime = [DateTime](Get-Date).AddDays($fromDay).ToString("yyyy/MM/dd 00:00:00")
$startUTCTime = [System.TimeZoneInfo]::ConvertTimeToUtc($startTime).ToString("yyyy-MM-ddTHH:mm:ssZ")
$endUTCTime = [System.TimeZoneInfo]::ConvertTimeToUtc($startTime.AddDays($days)).ToString("yyyy-MM-ddTHH:mm:ssZ")
# ログ抽出処理
# 対象のEvent=4656
# explorerのアクセスは取得しない
$filter = @"
Event/System/EventID='4656' and
Event/EventData[
Data[@Name='ProcessName']!='C:\Windows\explorer.exe'
] and
Event/EventData[
Data[@Name='ObjectType']='File'
] and
Event/System/TimeCreated[@SystemTime>='$startUTCTime'] and
Event/System/TimeCreated[@SystemTime<'$endUTCTime']
"@
# ログ抽出
try{
Get-WinEvent -LogName security -FilterXPath $filter | % {
$eventxml = [xml]$_.toXML()
#名前空間を指定しないと抽出不可能
$ns = New-Object Xml.XmlNamespaceManager $eventxml.NameTable
$ns.AddNamespace("e", "http://schemas.microsoft.com/win/2004/08/events/event")
$prop = @{"Time"=[DateTime]$eventxml.SelectSingleNode('e:Event/e:System/e:TimeCreated', $ns).Attributes.GetNamedItem("SystemTime").Value;
"User"=$eventxml.SelectSingleNode('e:Event/e:EventData/e:Data[@Name="SubjectUserName"]', $ns).InnerText;
"Domain"=$eventxml.SelectSingleNode('e:Event/e:EventData/e:Data[@Name="SubjectDomainName"]', $ns).InnerText;
"Path"=$eventxml.SelectSingleNode('e:Event/e:EventData/e:Data[@Name="ObjectName"]', $ns).InnerText;
"Process"=$eventxml.SelectSingleNode('e:Event/e:EventData/e:Data[@Name="ProcessName"]', $ns).InnerText}
return New-Object -TypeName PSObject -Property $prop
}
}
catch {
Write-Host "該当ログなし"
$error | Select-Object -Last 1
}