PowerShell 框架的 Active Directory 健康檢查

這是關於Active Directory健康檢查的兩部分系列的第二部分。雖然不需要閱讀,但如果你想了解本文中將要介紹的PowerShell腳本是如何構建的,建議你閱讀構建Active Directory健康檢查工具[詳解]:第一部分

在第一部分中,你學到了許多不同的多項測試以及它們的重要性。現在,讓我們把它們全部結合起來並建立一個工具。在這部分中,你將把第一部分中解釋的所有Active Directory健康檢查轉換為一個測試框架。你還將學習如何將各種AD健康檢查的結果輸出到像Pester和一個名為PRTG的監控工具中。

要按照本文的內容進行操作,或者查看你將在本文中學習的工具的完成版本,請從GitHub下載ADHealthCheck-NoResult.ps1腳本。

定義輸出

擁有一個統一的對象類型和一種簡單的生成方式將使將測試結果轉換為所選工具變得更加容易。

為了為所有可能的工具創建統一的輸出,我選擇使用了一個PowerShell類。雖然不是必需的,但這是我在這裡選擇的方法。主要目的是確保所有AD健康檢查返回相同類型的輸出。

A PowerShell class is a schema that defines how a PowerShell object should look and what it should do. Each line you see below represents a property the objects return will have. You can see below I’m planning on each AD health check to return ten properties.

Class AdhcResult {
    [string]$Source
    [string]$TestName
    [bool]$Pass
    $Was
    $ShouldBe
    [string]$Category
    [string]$SubCategory
    [string]$Message
    $Data
    [string[]]$Tags
}

為了加快這個課程的創建過程,我將使用一個名為New-AdhcResult的輔助函數。此函數將創建類和您所需的一切,並輸出一個自定義的[AdhcResult]類型對象。

運行AD健康檢查工具

首先,下載並將AD健康檢查腳本複製到域控制器上。使用PowerShell ISE打開它並運行。該工具的此部分不會返回任何信息。

此腳本將運行並將每個檢查的結果存儲在多個[AdhcResult]對象中的$TestResults變量中。稍後您將使用這些對象來生成報告或將其輸出到各種工具中。將健康檢查結果存儲在此類變量中,使您可以在需要創建另一個並使用New-AdHcResult命令時添加更多結果。

腳本運行完成後,您現在應該有一組完整的AD健康檢查對象存儲在$TestResults變量中。現在您可以從控制台運行$TestResults並查看原始結果。

在工具中顯示AD健康檢查結果

由於所有檢查都是以共同的對象類型存在的,您可以通過一些工具(如Pester和PRTG)更好地檢查它們。

在這個部分,您將學習如何使用一個名為extent的工具來創建HTML報告,並在PRTG中顯示報告。

使用Pester創建nUnit XML文件

首先,您需要將PowerShell對象轉換為您的工具可以理解的格式。大多數工具都理解XML,或者更具體地說,nUnit XML。這是一種您可以導入到各種工具以顯示結果的格式。

由於您正在使用PowerShell,您將使用Pester測試框架來讀取AD健康檢查腳本的輸出並生成nUnit XML文件

首先下載最新版本的Pester。您可以在提升的PowerShell控制台中運行Install-Module來下載Pester。下面的命令將強制安裝最新版本的Pester。由於Pester使用的發行者憑證隨Windows 10一起提供,因此我們需要使用SkipPublisherCheck參數來安裝它。

PS51> Install-Module Pester -Force -Verbose -SkipPublisherCheck

一旦Pester可用,您就可以運行腳本並動態創建一組Pester測試。

注意:您也可以自己創建Pester測試,而不使用我提供的PowerShell腳本。

下面的PowerShell腳本將使用Pester從ADHealthCheck-NoResult.ps1腳本中定義的$TestResults變量的輸出生成一個nUnit XML文件。

將此檔案另存為Pester.ps1,放在AD健康檢查腳本的相同資料夾中。

#在ADHealthCheck檔案中引用
. $PSScriptRoot\ADHealthCheck-NoResult.ps1
$Grouped = $TestResults | Group-Object Category

Foreach($Category in $Grouped) {
    Describe -Name $Category.Name -Tags ($Category.Group.Tags | Select -Unique) {
        Foreach($Result in $Category.Group){
            Context "$($Result.Source) - $($Result.TestName)" {
                It -Name "Should've passed" {
                    $Result.Pass | Should -Be -ExpectedValue $True -Because $Result.data
                }
            }
        }
    }
}

最後,執行下面的程式碼Invoke-Pester,以調用Pester.ps1檔案並以NUnitXml格式儲存結果。

PS51 > Invoke-Pester -Script @{Path = '.\Pester.ps1'} -OutputFile .\NunitReport.xml -OutputFormat NUnitXml

使用Extent工具建立HTML報告

當您擁有NUnit XML檔案後,現在可以使用該檔案傳遞給能夠將其轉換為HTML的工具。其中一個工具稱為extent。Extent是一個方便的工具,可以從Nunit XML檔案中建立HTML報告。

首先,將extent下載到之前建立的NunitReport.xml檔案相同的目錄中。然後在PowerShell會話中執行以下命令。這些命令將創建存儲HTML檔案的目錄,然後執行extent.exe進行轉換。

#創建報告目錄
PS51> mkdir .\HTMLReports

#創建報告
PS51> .\extent.exe -i .\NunitReport.xml -o .\HTMLReports\

完成後,您將在HTMLReports目錄中找到兩個HTML檔案。當您使用網頁瀏覽器打開這些檔案時,它們將如下所示。

HTML report for Pester test output
HTML report for Pester test output

將AD健康檢查結果匯入PRTG

PRTG 是由 Paessler 开发的一款流行的监控工具,您可以使用它来监控您的基础架构和服务。在本节中,您将学习如何在健康检查脚本运行后将健康检查结果推送到 PRTG。

与工具拉取信息相比,将结果推送到 PRTG 需要更多的工作,但您最终会发现设置是值得花费时间的。

先决条件

为了成功地将 PRTG 设置为本文中构建的 AD 健康检查脚本的监控工具,请确保您已经完成以下准备工作:

  • 已安装并配置好 PRTG
  • 在 PRTG 中设置了所有域控制器
  • 从 GitHub 下载了名为 Send-AdhcResultToPrtg.ps1 的 PowerShell 脚本
  • 您的 PRTG 传感器的 URL 和端口

如果您已经完成了每个先决条件,那么您可以按照下面的逐步说明来推送这些 AD 健康检查结果到 PRTG。

  1. 在 PRTG 中创建一个名为 Domain 或您喜欢的任意名称的设备。
  2. 使用 高级 HTTP 推送传感器 创建一个 IdentityTokendirectory-adhealthcheck 的传感器。请注意,这是区分大小写的!
  3. 对于 PRTG 中的每个域控制器设备,创建一个 高级 HTTP 推送传感器。对于每个 IdentityToken,请在每个传感器后附加 -adhealthcheck,例如 dc01-adhealthcheck
  4. Send-AdhcResultToPrtg.ps1 PowerShell 腳本的內容添加到我們已經介紹過的ADHealthCheck-NoResult.ps1 PowerShell 腳本的末尾。
  5. 將變量$PRTGUrl更改為您的 PRTG 服務器的 URL 和端口。
  6. 執行該腳本。

完成後,AD 健康檢查腳本應將狀態推送到您的 PRTG 服務器,如下所示。

PRTG sensors showing AD health

安排執行 Active Directory 健康檢查腳本

監控 AD 健康狀態是一個持續進程。您應該始終運行測試,而不是臨時實例。讓我們安排 Active Directory 健康檢查腳本以定期運行。

自動運行這些檢查的最簡單方法是將腳本添加到任務計劃程序中,並在 AD 使用者帳戶或組管理的服務帳戶下運行。

使用組管理的服務帳戶(gMSA)是執行計劃任務的更安全方式,因為只有指定的計算機帳戶可以從 AD 中獲取密碼。但是,某些組織可能沒有這種特權。

創建一個 AD 使用者帳戶

首先,讓我們分解設置 AD 使用者帳戶以運行計劃任務所需的步驟。

如果您要以用户帐户运行计划任务,请务必不要使用您自己的帐户来运行!请始终为此目的创建一个单独的用户帐户。

为了节省时间,您可以看到下面的PowerShell脚本。这是一个示例脚本,您可以使用它来创建一个属于Domain Admins组的AD用户帐户。然后,您可以使用此帐户来运行计划任务。

# 将此更改为服务帐户的OU
$OU = "OU=Service Accounts,DC=contoso,DC=com"
# 将此更改为要使用的帐户密码
$Password = "JägareTvå"
$SecureString = $Password | ConvertTo-SecureString -AsPlainText -Force
New-ADUser -Enabled $True -Path $OU -Name svcADHealthCheck -AccountPassword $SecureString
# 限制帐户仅适用于域控制器
$DomainControllers = (Get-ADDomainController -Filter *).Name

Set-ADAccount -Identity svcADHealthCheck -LogonWorkstations ($DomainControllers -Join ",")

# 将其设置为域管理员(抱歉)
Add-ADGroupMember -Identity "Domain Admins" -Members svcADHealthCheck

创建组管理的服务帐户

如果您的环境中尚未使用gMSA,使用gMSA来运行健康检查会更加棘手,但更加安全。

创建KDS根密钥

要创建一个用于运行AD健康检查脚本的gMSA帐户,首先添加一个KDS根密钥(如果您尚未拥有)。您可以在域控制器上运行PowerShell命令Get-KDSRootKey来检查是否已经有KDS根密钥。

如果您沒有KDS根密鑰,您可以在2012R2或更新版本的域控制器上的一個Domain Admins AD群組的用戶帳戶下運行Add-KDSRootKey -EffectiveImmediately來創建一個。

該密鑰需要在其他域控制器上複製以完全生效。有關此過程的更多信息可以在Microsoft文檔中找到。

創建gMSA

一旦創建了KDS根密鑰,您就可以使用PowerShell創建gMSA帳戶。下面是一個示例腳本,用於創建僅允許從Domain Admins群組中的域控制器進行身份驗證的gMSA帳戶。

# 更改為您的域
$Domain = "contoso.com"

$AccountName = "svcadhealthcheck"

# 創建一個名為svcadhealthcheck(實際上是svcadhealthcheck$)的GMSA,僅允許域控制器獲取密碼
New-ADServiceAccount $AccountName -DNSHostName "$AccountName.$Domain" –PrincipalsAllowedToRetrieveManagedPassword "Domain Controllers"

# 添加GMSA到Domain Admins
# 注意,我們通過其真實的SamAccountName 'svcadhealthcheck$'添加了該帳戶
Add-ADGroupMember -Identity "Domain Admins" -Members "$AccountName`$"

安裝和測試gMSA

現在已經創建了gMSA,最後一步是在所有域控制器上安裝和測試它。一種方法是使用Invoke-Command PowerShell命令。下面是一個PowerShell腳本,將在所有DC上安裝gMSA並確保其正常運作。

# 這將在所有域控制器上運行
Invoke-Command -ComputerName (Get-ADDomainController -Filter *).Name -ScriptBlock {
    $Account = Get-ADServiceAccount -Filter { Name -eq 'svcadhealthcheck'}
    Install-ADServiceAccount $Account

    # 測試GMSA在計算機上的正常運作
    # 如果測試正常則返回$True
    $Test = Test-ADServiceAccount -Identity $Account.Name
    if($Test){
        Write-Output "GMSA test OK on $env:computername"
    }
    else {
        Write-Output "GMSA test FAILED on $env:computername"
    }

}

給予gMSA批量作業權限

安裝完gMSA後,現在需要給予它在DC上運行批次作業的權限。由於該帳戶將在計劃任務中自主背景運行,因此需要此權限。

您可以通過現有的GPO設置此權限,或者通過創建新的GPO並將其鏈接到域控制器 OU。如果您尚未擁有要使用的GPO,下面是一些創建GPO的步驟。

  1. 在DC上啟動群組策略編輯器
  2. 右鍵單擊域控制器 OU,選擇在此域中創建GPO並將其鏈接到此處
  3. 將其命名為DC – 批量登錄或您喜歡的其他名稱
  4. 右鍵單擊GPO,然後點擊編輯
  5. 轉到計算機配置 -> Windows設置 -> 安全設置 -> 用戶權限分配
  6. 左鍵點擊 以批次工作登錄,然後點擊 內容
  7. 點擊 新增使用者或群組。
  8. 點擊 物件類型,僅選擇 服務帳戶,然後點擊 確定。
  9. 搜尋之前建立的 svcADHealthCheck 服務帳戶,選擇它,然後點擊 確定

現在您應該在AD物件列表中看到 gMSA,如下所示。

gMSA given rights to logon as a batch job

建立排程任務

現在,您已經建立了執行排程任務的帳戶,您可以在選擇的加入網域的伺服器上建立排程任務本身。

您可以透過GUI建立排程任務,但那樣要點擊太多次!相反地,我建議使用PowerShell來建立它。為什麼?因為您只需複製下面看到的程式碼就完成了。

下面您將找到兩個腳本;兩個腳本都是相似的,但一個假設有一個AD使用者帳戶,另一個假設有一個gMSA。請根據您使用的帳戶使用適當的腳本。

#替換為您腳本的路徑
$ScriptPath = "C:\Scripts\ADHealthCheck.ps1"
#替換為您創建的用於運行任務的用戶名
$UserName = "svdADHealthCheck"

#替換為上述帳戶設定的密碼
$Password = "JägareTvå!"
#創建啟動腳本的操作
$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy bypass -File '$ScriptPath'"
#創建啟動任務的觸發器
$Trigger = New-ScheduledTaskTrigger -Once -At "12:00" -RepetitionInterval (New-TimeSpan -Hours 12)
#為定期任務創建設置
$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd
#使用 splat 創建定期任務以提高可讀性
$Splat = @{
    User = "$env:USERDOMAIN\$UserName"
    Password = $Password
    TaskName = "ADHealthCheck"
    Action = $Action
    Trigger = $Trigger
    RunLevel = "Highest"
    Settings = $Settings
}
Register-ScheduledTask @Splat
#替換為您腳本的路徑
$ScriptPath = "C:\Scripts\ADHealthCheck.ps1"
#替換為您創建的用於運行任務的用戶名
$UserName = "svdADHealthCheck$"
#創建啟動腳本的操作
$Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy bypass -File '$ScriptPath'"
#創建啟動任務的觸發器
$Trigger = New-ScheduledTaskTrigger -Once -At "12:00" -RepetitionInterval (New-TimeSpan -Hours 12)
#為定期任務創建設置
$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd

#創建定義 GMSA 的原則
$Principal = New-ScheduledTaskPrincipal -UserID "$env:USERDOMAIN\$UserName" -LogonType Password -RunLevel Highest
#使用 splat 創建定期任務以提高可讀性
$Splat = @{
    Principal = $Principal
    TaskName = "ADHealthCheck"
    Action = $Action
    Trigger = $Trigger
    RunLevel = "Highest"
    Settings = $Settings
}
Register-ScheduledTask @Splat

完成!此時,定期任務將按照上述腳本中提供的間隔執行。

摘要

哇!如果你從第一部分一直跟到現在,你應該已經知道AD健康是一個很深奧的主題。這個主題涵蓋的內容非常多,即使兩篇長篇博客也無法完全涵蓋。

但是,現在你應該已經有足夠的知識和預先建立好的PowerShell框架,可以在需要時插入其他Active Directory健康檢查。

進一步閱讀

Source:
https://adamtheautomator.com/active-directory-health-check-2/