[玩转系统] 使用 CIM 和 PowerShell 构建 Active Directory 观察程序
作者:精品下载站 日期:2024-12-14 08:01:24 浏览:12 分类:玩电脑
使用 CIM 和 PowerShell 构建 Active Directory 观察程序
上周,Adam Bertram 发布了一条推文,寻找任何 PowerShell 代码,以便在创建新的 Active Directory 用户帐户时通知用户。我挖出了一些非常非常古老的代码,这些代码使用 WMI 事件订阅来监视 Active Directory 中的此类事件。我分享的代码是我在 PowerShell v2 时代编写的代码,但今天仍然有效。然而,它使用了 Register-WMIEvent,在当今的 PowerShell 世界中我认为已弃用。我们应该使用较新的 CIM 等效 cmdlet。我决定花一点时间完善代码,使其达到(我的)当前标准。
WMI/CIM 事件订阅
在 Windows 世界中,当发生某些事情(例如服务启动或进程结束)时,我们会收到一个事件。在 Active Directory 中,创建新用户帐户也会触发事件。在许多情况下,您可以使用 WMI/CIM 监视这些事件。您可以通过创建临时事件订阅来实现此目的。这就像任何其他订阅一样。你是说,“当有新的事情要报告时,给我发送一个新的问题。”您可能每两周或每 2 分钟收到一个新“问题”。
您将使用 Register-CimInspirationEvent 来创建订阅。您可以在本地计算机或远程计算机上创建事件订阅。此订阅仅在您的 PowerShell 会话期间持续。但请注意,除了小型环境之外,我会谨慎围绕它构建完整的管理系统。虽然很高兴知道何时发生服务停止或用户帐户被修改等情况,但在较大的环境中,您最好投资专为此类监控而设计的工具和软件。我会使用临时事件订阅来进行短期监控或故障排除。考虑到这一点,请将本文中的代码视为概念验证。
注册-CIMInductionEvent
我相信您会花时间阅读此 cmdlet 的完整帮助和示例。 WMI 事件是一个复杂的主题,我不会深入探讨。使用 cmdlet 的方法有多种。我将使用老式查询。
Register-CimIndicationEvent -Query "Select * from __InstanceCreationEvent Within 10 where TargetInstance ISA 'DS_USER'" -Namespace root\directory\ldap -SourceIdentifier NewUser
我在域成员 Windows 10 桌面上运行此代码。该查询表示:“每 10 秒检查一次创建事件,其中对象类型是用户帐户。” 内部部分称为轮询。您不想太快进行民意调查。如果您确实需要在几秒钟内知道事件发生的时间,则需要找到真正的软件解决方案。我的演示用了 10 秒。
这将创建一个事件订阅。
SourceIdentifier是您引用订阅者和后续事件的方式。如果您不指定,您将获得一个 GUID。就我个人而言,我发现定义自己的标识符要容易得多。
事件订阅者在我的本地 PowerShell 会话中运行,每 10 秒检查一次域中的新用户创建事件。我将创建一个新的域用户。 10 秒后,我的会话中没有发生任何事情。我们稍后会改变这一点。相反,我将运行 Get-Event。
有关用户的信息隐藏在事件中。
我稍后会回到这个对象。
注册-ADWatcher
考虑到这些基础知识,我编写了一个包含 Register-CimInductionEvent 的 PowerShell 函数。该函数允许我监视不同类别的 Active Directory 对象的不同类型的事件。
Function Register-ADWatcher {
[cmdletbinding(SupportsShouldProcess)]
Param(
[Parameter(Mandatory, HelpMessage = "What type of object do you want to watch?")]
[ValidateSet("User", "Group", "Computer", "OU")]
[string]$Category,
[Parameter(Mandatory, HelpMessage = "What type of activity watch?")]
[ValidateSet("Create", "Modify", "Remove")]
[string]$Activity,
[Parameter(HelpMessage = "How often do you want to poll? Enter a value in seconds. The minimum and default is 10.")]
[ValidateNotNullOrEmpty()]
[ValidateScript({ $_ -ge 10 })]
[int]$Poll = 10,
[Parameter(HelpMessage = "Specify an action scriptblock when the event fires.")]
[scriptblock]$Action,
[Parameter(HelpMessage = "Specify additional data to associate with the watcher.")]
[string]$MessageData,
[Parameter(HelpMessage = "Specify a name for the watcher")]
[string]$SourceIdentifier,
[parameter(HelpMessage = "Specify the name of a computer where you want to create the watcher.")]
[string]$Computername,
[switch]$Passthru
)
Write-Verbose "Starting $($myinvocation.mycommand)"
#remove bound parameters that don't belong to Register-CimIndicationEvent
$drop = "Category", "Activity", "Poll", "WhatIf", "Confirm","Passthru"
foreach ($item in $drop) {
if ($PSBoundParameters.ContainsKey($item)) {
[void]$PSBoundParameters.Remove($item)
}
}
Switch ($Category) {
"User" { $DS = "DS_USER" }
"Group" { $DS = "DS_GROUP" }
"Computer" { $DS = "DS_COMPUTER" }
"OU" { $DS = "DS_ORGANIZATIONALUNIT" }
}
Switch ($Activity) {
"Create" { $DSAction = "__InstanceCreationEvent" }
"Modify" { $DSAction = "__InstanceModificationEvent" }
"Remove" { $DSAction = "__InstanceDeletionEvent" }
}
$query = "Select * from $DSAction Within $Poll where TargetInstance ISA '$DS'"
$PSBoundParameters.Add("Query", $query)
$PSBoundParameters.Add("Namespace", "root\directory\ldap")
Write-Verbose "Creating an AD Watcher with these parameters"
$PSBoundParameters | Out-String | Write-Verbose
$target = "$Activity $Category within $Poll seconds"
If ($pscmdlet.ShouldProcess($target.toUpper(), "Register AD Watcher")) {
[void](Register-CimIndicationEvent @PSBoundParameters)
if ($Passthru) {
Start-sleep -Seconds 2
Get-EventSubscriber | Sort-Object -property SubscriberID | Select-Object -last 1
}
}
Write-Verbose "Ending $($myinvocation.mycommand)"
}
我将使用此功能来监视新群组。
Register-ADWatcher -Category Group -Activity Create -MessageData "A new group has been created" -SourceIdentifier "NewGroup"
我最终将替换新的用户订阅,因此我将删除当前的订阅。
Get-EventSubscriber newuser | Unregister-Event
现在创建一个新组并查看该事件。
辅助函数
我知道有关该组的信息就在那里,但我懒得解析该对象。相反,我将编写一个辅助函数。
Function Get-TargetInstance {
[cmdletbinding()]
Param(
[Parameter(Mandatory, ValueFromPipeline)]
[object]$EventResult,
[Parameter(HelpMessage = "Only show defined properties")]
[switch]$ShowDefined
)
Process {
if ($ShowDefined) {
$t = $EventResult.SourceEventArgs.NewEvent.TargetInstance
$t.psobject.Properties.where({ $_.name -match "^DS|ADSIPath" -AND $_.value }) |
ForEach-Object -Begin {
#create a temporary ordered hashtable
$h = [ordered]@{
TimeGenerated = $EventResult.timeGenerated
EventClass = $EventResult.SourceEventArgs.NewEvent.CimSystemProperties.Classname
}
} -Process {
#add each property that has a value to the hashtable
$h.add($_.name, $_.value) } -End {
#Create a custom object from the hashtable
New-Object -TypeName PSObject -Property $h
}
}
else {
$EventResult.sourceEventArgs.NewEvent.TargetInstance
}
}
}
因为我知道该对象将具有许多未定义或 null 属性值,所以我添加了一个参数以仅显示填充的属性。
行动
从这个角度来看,我发现我对组名的修改是错误的。完美的。让我们创建一个观察器来监视组对象的更改。我还可以向您展示如何添加操作。这是事件触发时运行的脚本块。我将使用 BurntToast 模块(您可以从 PowerShell 库安装该模块)来向我显示通知。
Register-ADWatcher -Category Group -Activity Modify -SourceIdentifier "GroupChange" -Action { New-BurntToastNotification -Text "A group has changed"}
但使用动作时需要权衡。
没有事件对象。好吧,我应该说,没有对象写入我的控制台。我可以在我的动作脚本块中引用一个对象。但首先让我展示那是什么。
这是更改用户对象的观察者。
Register-ADWatcher -Category User -Activity Modify -SourceIdentifier UserChange -Passthru
当更改事件触发时,您会得到一个“之前”和“之后”对象。您自然想知道发生了什么变化。我尝试使用 Compare-Object 这看起来是合适的工具。但除非我指定一个属性,否则它不会给我结果。所以我写了自己的比较函数。
Function Compare-DSObject {
#get-event -sourceIdentifier changeduser | Compare-DSObject
[cmdletbinding()]
Param(
[Parameter(Mandatory, ValueFromPipeline)]
[object]$EventResult
)
Process {
#write-host "Processing an event" -ForegroundColor Green
$p = $EventResult.SourceEventArgs.NewEvent.PreviousInstance
$t = $EventResult.SourceEventArgs.NewEvent.TargetInstance
$prop = $p.psobject.Properties.name.where( { $_ -match "^DS" })
Write-Verbose "Processing Changes to $($t.ADSIPath)"
foreach ($item in $prop) {
if (Compare-Object -ReferenceObject $p -DifferenceObject $t -Property $item) {
[pscustomobject]@{
PSTypeName = "DSComparison"
ADSIPath = $t.ADSIPath
TimeGenerated = $eventResult.TimeGenerated
Property = $item
PreviousValue = $p.$item
NewValue = $t.$item
}
}
}
} #process
}
正如您所看到的,这实际上取决于您在事件触发时想要执行的操作或看到的内容。
在操作脚本块中,您可以使用内置的 $event 对象引用事件对象。这是新用户帐户的观察程序,它将使用 BurntToast 并显示新对象的可分辨名称。
$action = {
$toast = @{
Text = "$($event.MessageData) $($event.SourceEventArgs.NewEvent.TargetInstance.DS_distinguishedName)"
Sound = "Alarm5"
}
New-BurntToastNotification @toast
}
$watch = @{
Category = "User"
Activity = "Create"
MessageData = "A domain user account has been created."
SourceIdentifier = "NewUser"
Action = $Action
}
Register-ADWatcher @watch
MessageData 的值将在通知中使用。
把它们放在一起
让我将所有内容放在一起来结束这篇文章。我们来看一个删除事件。我想在我的小域中保留审计跟踪。当用户被删除时,我想将事件信息保存到磁盘并获取我的 toast 通知。在我的操作脚本块中,我将使用 Export-CliXML 将事件导出到磁盘。
$action = {
#export event to disk
if (-not (Test-Path C:\ADWatch)) {
New-Item -Path C:\ -Name ADWatch -ItemType Directory
}
$file = "{0}_{1}.xml" -f $event.sourceIdentifier.Replace(" ",""),($event.TimeGenerated.tostring("u").replace(" ","-").replace(":",""))
$export = Join-Path -Path C:\ADWatch -ChildPath $file
$event | Export-Clixml -Path $export
$ti = $event.SourceEventArgs.NewEvent.TargetInstance
$msg = "[$($event.TimeGenerated)] $($event.messagedata) $($ti.DS_DistinguishedName) See $export for details."
$toast = @{
Header = New-BTHeader -Title "AD Watcher"
Text = $msg
SnoozeAndDismiss = $True
AppLogo = "C:\scripts\db.png"
Sound = "alarm10"
}
New-BurntToastNotification @toast
}
Register-ADWatcher -Category User -Activity Remove -Action $action -SourceIdentifier "DeleteUser" -MessageData "ALERT! A domain user account has been removed." -Verbose
已删除用户的目标实例将序列化为 C:\ADWatch 中的 XML 文件。我正在创建 UTC 时间戳作为文件名的一部分。
警报消息指示可以轻松带回 PowerShell 的文件。
我可以使用我的辅助功能来查看已删除的用户信息。
概括
正如您所看到的,当 Active Directory 中发生事件时,可以收到通知。但仅仅因为您可以做到这一点,并不意味着应该。还有很多其他选项是更好的选择,尤其是更接近您需要的实时通知的选项。我想说这还取决于您需要如何处理这些信息。您只是需要知道还是必须发生某些事情?
为了避免我肯定会遇到的一个问题,我不知道这是否或如何与 Azure AD 一起使用。拥有 Azure AD 环境的人必须让我知道。
但对于本地事件,无论是在 Active Directory 还是其他地方,使用 CIM 事件都可以成为 PowerShell 工具箱中的有用工具。
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag