我正在尝试编写一个由事件执行的PowerShell脚本。 然后,该PowerShell脚本应运行:
Get-WinEvent -FilterHashtable @{Logname='security';ID=$instanceID} -MaxEvents 1
获取触发PS脚本的事件。
到目前为止,一切顺利,一旦我有这个活动,我想发送一封电子邮件。该邮件应包含事件消息中的某些内容。
例如:事件ID 4720(已创建用户帐户) 用户帐户xx由xx在xx时间创建。
现在我有大约10个事件ID,我想通过电子邮件对其进行响应。这些事件ID在消息中有所不同。
有动态的方法吗?
我尝试了以下操作:
param(
[Parameter(Mandatory = $true)]$instanceID
)
#$instanceIDs = @(4661,4662,5139,5136,5137,5138,5139,5141,4720,4722,4723,4724,4725,4726,4738,4740,4767,4780,4781,4794,5376,5377,4741,4742,4743,4727,4728,4729)
$event = Get-WinEvent -FilterHashtable @{Logname='security';ID=$instanceID} -MaxEvents 1
Function EventIDxxx{
Get-WinEvent -FilterHashtable @{Logname='security';ID=$instanceID} -MaxEvents 1 |
Select-Object -Property timecreated,
@{label='username';expression={$_.properties[0].value}},
@{label='computername';expression={$_.properties[1].value}}
}
但是我必须为每个事件创建一个新功能。 有人有主意吗?
非常感谢您
**编辑**
我想拥有一个Powershell脚本,该脚本可以读取事件消息,并将需要的部分写入变量中。
A user account was created.
Subject:
Security ID: Contoso\Conlil
Account Name: Conlil
Account Domain: Contoso
Logon ID: 0x1468731E
New Account:
Security ID: Contoso\ASD
Account Name: ASD
Account Domain: Contoso
Attributes:
SAM Account Name: ASD
Display Name: wSDSAD D. DSA
User Principal Name: ASD@Contoso.com
Home Directory: -
Home Drive: -
Script Path: -
Profile Path: -
User Workstations: -
Password Last Set: <never>
Account Expires: <never>
Primary Group ID: 513
Allowed To Delegate To: -
Old UAC Value: 0x0
New UAC Value: 0x15
User Account Control:
Account Disabled
'Password Not Required' - Enabled
'Normal Account' - Enabled
User Parameters: -
SID History: -
Logon Hours: <value not set>
Additional Information:
Privileges -
例如,在此事件中,我想要 1.创建者的用户名和域 2.创建的帐户名称 3.创建帐户的域 4.创建帐户的电子邮件 5.也许HomeDrive 6. UserAccount控件
我可以使用以下代码进行此操作:
@{label='Username';expression={$_.properties[x].value}},
但这是静态的,我必须为每个事件创建一个新函数。
答案 0 :(得分:1)
除了使用脚本(方法)之外,还可以使用事件查看器将Windows任务附加到该事件:
您右键单击事件,然后单击“将任务附加到此事件…”。然后您有多种选择,例如可以运行一个程序(可以是powershell.exe)或发送电子邮件。
更新
我不好的“从任务事件发送电子邮件”是deprecated。
另一种替代方法是创建任务并使用“ powershell.exe”运行该任务,并将调用Send-MailMessage
cmdlet的脚本作为参数传递:
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage?view=powershell-5.1
答案 1 :(得分:0)
This is what WMI Event consumers / watchers are designed for。您可以设置temporary或permanent。
这是很常见的事情,并且在网络上有很多有关如何进行设置的示例,甚至可以使用预构建的脚本,也可以根据需要进行调整。
Powershell Centralized Log Monitor
监视指定日志事件的服务器集合,并在捕获监视的事件时发送电子邮件警报。
## Powershell Log Monitor Script ##
## Contributing authors - mck74,mjolinor,
param([switch]$ShowEvents = $false,[switch]$NoEmail = $false,[switch]$useinstanceid = $false)
$log = "Application"
$hist_file = $log + "_loghist.xml"
$seed_depth = 200
#run interval in minutes - set to zero for runonce, "C" for 0 delay continuous loop.
$run_interval = 1
$EmailFrom = "<user@domain.tld>"
$EmailTo = "<user@domain.tld>"
$EmailSubject = "Server event notification"
$SMTPServer = "smtphost.domain.tld"
$SMTPAuthUsername = "username"
$SMTPAuthPassword = "password"
$computers = @(gc monitored_computers.txt)
$event_list = @{}
Import-Csv alert_events.csv |% {$event_list[$_.source + '#' + $_.id] = 1}
#see if we have a history file to use, if not create an empty $histlog
if (Test-Path $hist_file){$loghist = Import-Clixml $hist_file}
else {$loghist = @{}}
$timer = [System.Diagnostics.Stopwatch]::StartNew()
function send_email {
$mailmessage = New-Object system.net.mail.mailmessage
$mailmessage.from = ($emailfrom)
$mailmessage.To.add($emailto)
$mailmessage.Subject = $emailsubject
$mailmessage.Body = $emailbody
$mailmessage.IsBodyHTML = $true
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("$SMTPAuthUsername", "$SMTPAuthPassword")
$SMTPClient.Send($mailmessage)
}
#START OF RUN PASS
$run_pass = {
$EmailBody = "Log monitor found monitored events. `n"
$computers |%{
$timer.reset()
$timer.start()
Write-Host "Started processing $($_)"
#Get the index number of the last log entry
$index = (Get-EventLog -ComputerName $_ -LogName $log -newest 1).index
#if we have a history entry calculate number of events to retrieve
# if we don't have an event history, use the $seed_depth to do initial seeding
if ($loghist[$_]){$n = $index - $loghist[$_]}
else {$n = $seed_depth}
if ($n -lt 0){
Write-Host "Log index changed since last run. The log may have been cleared. Re-seeding index."
$events_found = $true
$EmailBody += "`n Possible Log Reset $($_)`nEvent Index reset detected by Log Monitor`n" | ConvertTo-Html
$n = $seed_depth
}
Write-Host "Processing $($n) events."
#get the log entries
if ($useinstanceid){
$log_hits = Get-EventLog -ComputerName $_ -LogName $log -Newest $n |
? {$event_list[$_.source + "#" + $_.instanceid]}
}
else {$log_hits = Get-EventLog -ComputerName $_ -LogName $log -Newest $n |
? {$event_list[$_.source + "#" + $_.eventid]}
}
#save the current index to $loghist for the next pass
$loghist[$_] = $index
#report number of alert events found and how long it took to do it
if ($log_hits){
$events_found = $true
$hits = $log_hits.count
$EmailBody += "`n Alert Events on server $($_)`n"
$log_hits |%{
$emailbody += "<br><br>"
$emailbody += $_ | select MachineName,EventID,Message | ConvertTo-Html
$emailbody += "<br><br>"
}
}
else {$hits = 0}
$duration = ($timer.elapsed).totalseconds
write-host "Found $($hits) alert events in $($duration) seconds."
"-"*60
" "
if ($ShowEvents){$log_hits | fl | Out-String |? {$_}}
}
#save the history file to disk for next script run
$loghist | export-clixml $hist_file
#Send email if there were any monitored events found
if ($events_found -and -not $NoEmail){send_email}
}
#END OF RUN PASS
Write-Host "`n$("*"*60)"
Write-Host "Log monitor started at $(get-date)"
Write-Host "$("*"*60)`n"
#run the first pass
$start_pass = Get-Date
&$run_pass
#if $run_interval is set, calculate how long to sleep before the next pass
while ($run_interval -gt 0){
if ($run_interval -eq "C"){&$run_pass}
else{
$last_run = (Get-Date) - $start_pass
$sleep_time = ([TimeSpan]::FromMinutes($run_interval) - $last_run).totalseconds
Write-Host "`n$("*"*10) Sleeping for $($sleep_time) seconds `n"
#sleep, and then start the next pass
Start-Sleep -seconds $sleep_time
$start_pass = Get-Date
&$run_pass
}
}
答案 2 :(得分:0)
我得到了答案。
$event = Get-WinEvent -FilterHashtable @{Logname='security';ID=$instanceID} -MaxEvents 1
foreach($entry in $event){
#Get the XML...
$XML = [xml]$entry.ToXml()
#Some events use other nodes, like 'UserData' on Applocker events...
$XMLData = $null
if( $XMLData = @( $XML.Event.EventData.Data )) {
For( $i=0; $i -lt $XMLData.count; $i++ ) {
#We don't want to overwrite properties that might be on the original object, or in another event node.
Add-Member -InputObject $entry -MemberType NoteProperty -name "EventData$($XMLData[$i].name)" -Value $XMLData[$i].'#text' -Force
}
}
}
$entry | select EventData*