Windows Server 2025の新機能「OSConfig」は、PowerShellのMicrosoft.OSConfigモジュールが提供するセキュリティベースラインの展開と維持を簡素化する機能です。現在のセキュリティ設定をベースラインと比較して評価する(監査する)ことを目的に、モジュールのインストールから対応状況(コンプライアンス状態)の確認までをスクリプト化してみました。弊社製品「BOM for Windows」*1による監視(カスタム監視)での利用を想定したスクリプトです。
*1 BOM for WindowsのWindows Server2025対応は、2025年前半にリリースされるBOM for Windows ver 8.0 SR2で予定されています。
Microsoft.OSConfigモジュールのインストールと更新を自動化するスクリプト
Windows Admin Center(WAC)v2の「セキュリティ」ツールにある「セキュリティベースライン」タブを開くと、Microsoft.OSConfigモジュールがインストールおよび更新され、各ベースラインごとの「コンプライアンスの割合」「準拠している」「準拠していません」の概要と、その下に選択中のベースラインに含まれるセキュリティ設定(説明)とコンプライアンスのステータス、非準拠の理由、重大度の一覧が表示されます(画面1)。今回は、WAC v2のこの画面の情報、つまりMicrosoft.OSConfigモジュールのインストールと更新から、ベースラインを適用する前のコンプライアンスの状況を確認するスクリプトを作成します。

画面1 WAC v2でベースラインを適用する前に得られるコンプライアンス状況の情報をスクリプトで取得したい
以下のPowerShellスクリプト「install-osconfigmd.ps1」は、Microsoft.OSConfigモジュールがインストールされているかどうかを確認し、インストールされていなければインストールします。OSConfigは、Windows Server 2025およびAzure Local(旧称、Azure Stack HCI)バージョン23H2でサポートされています。このスクリプトは、対応OSの場合に限り、Microsoft.OSConfigモジュールをインストールします。また、既にインストールされている場合、最新のモジュールが利用可能でないかどうかを確認し、利用可能な場合は現在のモジュールをアンインストールして、最新のモジュールをインストールします。このスクリプトのコードの大部分は、WAC v2のスクリプト(Install/Update-WACSEMicrosoftOsConfigModuleファンクション)を流用させてもらいました。Windows Server 2025やAzure Local 23H2の識別方法やWrite-Verboseの使い方については、他のスクリプトにも応用できるので、是非流用してください。なお、Microsoft.OSConfigモジュールはPowerShellギャラリー(https://www.powershellgallery.com/packages/Microsoft.OSConfig/)からのインストールとなるため、インターネットアクセスが利用可能である必要があります。
[install-osconfigmd.ps1](プレーンテキストで表示)
[cmdletBinding()]
param()
function Check-WindowsServer2025 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
if ($osname.Contains("Windows Server 2025")) {
return $true
} else {
return $false
}
}
function Check-AzureLocal23H2 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
$osver = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion
if ($osname.Contains("Azure Stack HCI")) {
if ($osver -eq "23H2") {
return $true
} else {
return $false
}
} else {
return $false
}
}
function Install-MicrosoftOsConfigModule {
$osConfigModule = "Microsoft.OSConfig"
$moduleExists = Get-InstalledModule -Name $osConfigModule -AllVersions -ErrorAction silentlycontinue
if ($moduleExists) {
# No installation performed
return $false
} else {
# Install the package providers if not already installed
Get-PackageProvider -Name PowerShellGet -ForceBootstrap | Out-Null
Get-PackageProvider -Name NuGet -ForceBootstrap | Out-Null
Install-Module -Name $osConfigModule -Repository PSGallery -Scope AllUsers -Force
return $true
}
}
function Update-MicrosoftOsConfigModule {
$osConfigModule = "Microsoft.OSConfig"
$installedModule = Get-InstalledModule -Name $osConfigModule -ErrorAction silentlycontinue
$latestModule = Find-Module -Name $osConfigModule -Repository PSGallery -ErrorAction silentlycontinue
if ($installedModule -and $latestModule -and ($latestModule.Version -gt $installedModule.Version)) {
Uninstall-Module -Name $osConfigModule -AllVersions -Force
Install-Module -Name $osConfigModule -Scope AllUsers -Repository PSGallery -Force
return $true
} else {
# No update performed
return $false
}
}
if (Check-WindowsServer2025) {
Write-Verbose "Check-WindowsServer2025: Windows Server 2025"
} else {
if (Check-AzureLocal23H2) {
Write-Verbose "Check-WindowsServer2025: Azure Local 23H2"
} else {
Write-Verbose "Check-WindowsServer2025: Unsupported Operating System"
return -1
exit
}
}
if (!(Install-MicrosoftOsConfigModule)) {
Write-Verbose "Install-MicrosoftOsConfigModule: OsConfig Module Exist"
Write-Verbose "Update-MicrosoftOsConfigModule: OsConfig Module Try to update"
if (Update-MicrosoftOsConfigModule) {
Write-Verbose "Update-MicrosoftOsConfigModule: OsConfig Module updated"
} else {
Write-Verbose "Update-MicrosoftOsConfigModule: OsConfig Module latest"
}
} else {
Write-Verbose "Install-MicrosoftOsConfigModule: OsConfig Module Installed"
}
$installedmodule = (Get-Module -ListAvailable -Name Microsoft.OSConfig)
Write-Verbose $installedmodule
return 0
後で出てくる他のスクリプトと同様に、BOMでの利用を想定し、スクリプトはエラーの場合「-1」*1を返します。「install-osconfigmd.ps1」の場合は、対応OSでない場合にエラーを返します。「install-osconfigmd.ps1」は、インストールや更新が成功するか、インストールする必要がない場合は、「0」を返して終了します。また、他のスクリプトと同様に、「-Verbose」パラメーターを付けて実行すると、どのような処理を実行しているか、詳細な情報を出力します(画面2)。
*1 BOMのカスタム監視で利用する場合は、「-1」はエラーとして扱われないため(巨大な数値として扱われます)、すべてのスクリプトの「return -1」を「return $null」や「return "Error"」などに書き換えてく利用してください。

画面2 対応OSかどうかを識別して、対応OSの場合はMicrosoft.OSConfigモジュールをインストールまたは更新するスクリプト。-Verboseパラメーターを付加すると、詳細な情報を出力する
セキュリティベースラインのコンプライアンスを確認するスクリプト
OSConfigで利用可能なシナリオとしては、以下の5つを確認しています(App Control for Business用のシナリオは省略しています)。利用可能なシナリオは、Get-OSConfigMetadataコマンドレットで確認することができます。
- SecurityBaseline/WS2025/WorkgroupMember ・・・ ワークグループ構成のWindows Server 2025のセキュリティベースライン
- SecurityBaseline/WS2025/DomainMember ・・・ Active DirectoryドメインのメンバーサーバーのWindows Server 2025のセキュリティベースライン
- SecurityBaseline/WS2025/DomainController ・・・ Active DirectoryドメインのドメインコントローラーのWindows Server 2025のセキュリティベースライン
- Defender/AntiVirus ・・・ Microsoft Defenderウイルス対策のセキュリティベースライン
- SecuredCore ・・・ セキュアコアサーバーのセキュリティベースライン(構成と維持)
- SecuredCoreState ・・・ セキュアコアサーバーのセキュリティベースライン(情報提供) (3/25追加)
- SecurityBaseline/AzureStackHCI ・・・ Azure Local 23H2のセキュリティベースライン。(後で知りましたが、Azure Localでは、Azure向けのAzureWindowsBaselineシナリオも利用可能です。)
PowerShellスクリプト「audit-windowsbaseline.ps1」は、Windows Server 2025でのみ実行することができ(Azure Localの場合は-1で終了)、ワークグループ構成であるか、ドメインのメンバーサーバーであるか、ドメインコントローラーであるかをスクリプト内で判定して、適切なWindows Server 2025用のシナリオを決定し、コンプライアンス状況を確認し、コンプライアンスの割合を0~100(四捨五入した整数値)で返します。また、パラメーターとしてログの出力先パスを指定することができ、指定されなかった場合はTEMP環境変数にログファイルを出力します。ログファイル名は、シナリオに応じて以下のいずれかになります(画面3)。ワークグループ構成、メンバーサーバー、ドメインコントローラーの識別方法、日時を含むログファイル名の生成と出力については、他のスクリプトにも応用できるので、是非流用してください。
- WindowsBaseLine_WorkgroupServer_yyyyMMdd_HHmmss.log
- WindowsBaseLine_MemberServer_yyyyMMdd_HHmmss.log
- WindowsBaseLine_DomainController_yyyyMMdd_HHmmss.log
ログの各行は、左からセキュリティ設定の名前(Name)、コンプライアンスのステータス(Status)、重大度(Severity)、非準拠の理由(Reason)を示しています。WAC v2の説明と一致させたい場合は、スクリプトの「| ft Name,」を「| ft Description,」に変更してください。ただし、Descriptionが大きな幅を取ってしまい、可読性が悪くなる可能性があります。

画面3 「audit-windowsbaseline.ps1」は、Windows Server 2025の適切なシナリオを選択して、コンプライアンスの割合を返すとともに、ログファイルに詳細情報を出力する
PowerShellスクリプト「audit-defenderantivirus.ps1」「audit-securedcore.ps1」「audit-securedcorestate.ps1(3/25追加)」は、Windows Server 2025およびAzure Local 23H2で利用可能なもので、それぞれDefender/AntiVirusとSecuredCoreシナリオ(audit-securedcorestate.ps1の使用を推奨)に対応します。最後のPowerShellスクリプト「audit-azurelocal.ps1」は、Azure Local 23H2でのみ利用することができるもので、SecurityBaseline/AzureStackHCIシナリオに対応します(画面4)。いずれも、ログの出力先の指定が可能で、ログファイル名はシナリオに応じて以下のいずれかになります。
- WindowsBaseLine_DefenderAntivirus_yyyyMMdd_HHmmss.log
- WindowsBaseLine_SecuredCore_yyyyMMdd_HHmmss.log
- WindowsBaseLine_SecuredCoreState_yyyyMMdd_HHmmss.log(3/25追加)
- WindowsBaseLine_AzureLocal_yyyyMMdd_HHmmss.log

画面4 「audit-windowsbaseline.ps1」はWindows Server 2025専用、「audit-azurelocal.ps1」はAzure Local 23H2専用。
[audit-windowsbaseline.ps1](プレーンテキストで表示)
[cmdletBinding()]
param($outDir)
function Check-WindowsServer2025 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
if ($osname.Contains("Windows Server 2025")) {
return $true
} else {
return $false
}
}
function Check-AzureLocal23H2 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
$osver = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion
if ($osname.Contains("Azure Stack HCI")) {
if ($osver -eq "23H2") {
return $true
} else {
return $false
}
} else {
return $false
}
}
function Check-MicrosoftOsConfigModule {
$osConfigModule = "Microsoft.OSConfig"
$moduleExists = Get-InstalledModule -Name $osConfigModule -AllVersions -ErrorAction silentlycontinue
if ($moduleExists) {
return $true
} else {
return $false
}
}
if (Check-WindowsServer2025) {
Write-Verbose "Check-WindowsServer2025: Windows Server 2025"
} else {
Write-Verbose "Check-WindowsServer2025: Unsupported Operating System"
return -1
exit
}
if (!(Check-MicrosoftOsConfigModule)) {
Write-Verbose "Check-MicrosoftOsConfigModule: OsConfig Module dows not exist"
return -1
exit
}
$auditScenario = ""
if($outDir -eq $null) {
$outDir = $env:TEMP
} else {
if(!(Test-Path -Path $outDir)) {
$outDir = $env:TEMP
}
}
if (!($outDir -like "*\")) {
$outDir = $outDir+"\"
}
$dateTime = Get-Date -Format "yyyyMMdd_HHmmss"
If ((Get-WMIObject Win32_ComputerSystem).PartOfDomain) {
#Domain Member or Domain Controller"
$domainRole = (get-wmiobject Win32_ComputerSystem).DomainRole
if ($domainRole -eq 3) {
$auditScenario = "SecurityBaseline/WS2025/MemberServer"
$logFileName = $outDir+"WindowsBaseLine_MemberServer_$datetime.log"
Write-Verbose "PartOfDomain: Domain Member"
} elseif ($domainRole -gt 4) {
$auditScenario = "SecurityBaseline/WS2025/DomainController"
$logFileName = $outDir+"WindowsBaseLine_DomainController_$datetime.log"
Write-Verbose "PartOfDomain: Domain Controller"
}
} else {
$auditScenario = "SecurityBaseline/WS2025/WorkgroupMember"
$logFileName = $outDir+"WindowsBaseLine_WorkgroupMember_$datetime.log"
Write-Verbose "PartOfDomain: Workgroup Member"
}
Write-Verbose $auditScenario
Write-Verbose "LogFile: $logFileName"
$results = (Get-OSConfigDesiredConfiguration -Scenario $auditScenario)
$results | ft Name, @{ Name = "Status"; Expression={$_.Compliance.Status} }, @{ Name = "Severity"; Expression={$_.Compliance.Severity} }, @{ Name = "Reason"; Expression={$_.Compliance.Reason} } -AutoSize -Wrap 2>&1| Out-File -Encoding default -FilePath $logFileName -width 160
$numOfCompliant = 0
$numOfTotal = 0
foreach ($result in $results) {
if($result.Compliance.Status -eq "Compliant") {
$numOfCompliant++
$numOfTotal++
} elseif ($result.Compliance.Status -eq "NotCompliant") {
$numOfTotal++
}
}
return [math]::Round(($numOfCompliant / $numOfTotal * 100),0)
[audit-defenderantivirus.ps1](プレーンテキストで表示)
[cmdletBinding()]
param($outDir)
function Check-WindowsServer2025 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
if ($osname.Contains("Windows Server 2025")) {
return $true
} else {
return $false
}
}
function Check-AzureLocal23H2 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
$osver = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion
if ($osname.Contains("Azure Stack HCI")) {
if ($osver -eq "23H2") {
return $true
} else {
return $false
}
} else {
return $false
}
}
function Check-MicrosoftOsConfigModule {
$osConfigModule = "Microsoft.OSConfig"
$moduleExists = Get-InstalledModule -Name $osConfigModule -AllVersions -ErrorAction silentlycontinue
if ($moduleExists) {
return $true
} else {
return $false
}
}
if (Check-WindowsServer2025) {
Write-Verbose "Check-WindowsServer2025: Windows Server 2025"
} else {
if (Check-AzureLocal23H2) {
Write-Verbose "Check-WindowsServer2025: Azure Local 23H2"
} else {
Write-Verbose "Check-WindowsServer2025: Unsupported Operating System"
return -1
exit
}
}
if (!(Check-MicrosoftOsConfigModule)) {
Write-Verbose "Check-MicrosoftOsConfigModule: OsConfig Module dows not exist"
return -1
exit
}
$auditScenario = ""
if($outDir -eq $null) {
$outDir = $env:TEMP
} else {
if(!(Test-Path -Path $outDir)) {
$outDir = $env:TEMP
}
}
if (!($outDir -like "*\")) {
$outDir = $outDir+"\"
}
$dateTime = Get-Date -Format "yyyyMMdd_HHmmss"
$auditScenario = "Defender/Antivirus"
$logFileName = $outDir+"WindowsBaseLine_AntiVirus_$datetime.log"
Write-Verbose $auditScenario
Write-Verbose "LogFile: $logFileName"
$results = (Get-OSConfigDesiredConfiguration -Scenario $auditScenario)
$results | ft Name, @{ Name = "Status"; Expression={$_.Compliance.Status} }, @{ Name = "Severity"; Expression={$_.Compliance.Severity} }, @{ Name = "Reason"; Expression={$_.Compliance.Reason} } -AutoSize -Wrap 2>&1| Out-File -Encoding default -FilePath $logFileName -width 160
$numOfCompliant = 0
$numOfTotal = 0
foreach ($result in $results) {
if($result.Compliance.Status -eq "Compliant") {
$numOfCompliant++
$numOfTotal++
} elseif ($result.Compliance.Status -eq "NotCompliant") {
$numOfTotal++
}
}
return [math]::Round(($numOfCompliant / $numOfTotal * 100),0)
[audit-securedcore.ps1](プレーンテキストで表示)
[cmdletBinding()]
param($outDir)
function Check-WindowsServer2025 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
if ($osname.Contains("Windows Server 2025")) {
return $true
} else {
return $false
}
}
function Check-AzureLocal23H2 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
$osver = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion
if ($osname.Contains("Azure Stack HCI")) {
if ($osver -eq "23H2") {
return $true
} else {
return $false
}
} else {
return $false
}
}
function Check-MicrosoftOsConfigModule {
$osConfigModule = "Microsoft.OSConfig"
$moduleExists = Get-InstalledModule -Name $osConfigModule -AllVersions -ErrorAction silentlycontinue
if ($moduleExists) {
return $true
} else {
return $false
}
}
if (Check-WindowsServer2025) {
Write-Verbose "Check-WindowsServer2025: Windows Server 2025"
} else {
if (Check-AzureLocal23H2) {
Write-Verbose "Check-WindowsServer2025: Azure Local 23H2"
} else {
Write-Verbose "Check-WindowsServer2025: Unsupported Operating System"
return -1
exit
}
}
if (!(Check-MicrosoftOsConfigModule)) {
Write-Verbose "Check-MicrosoftOsConfigModule: OsConfig Module dows not exist"
return -1
exit
}
$auditScenario = ""
if($outDir -eq $null) {
$outDir = $env:TEMP
} else {
if(!(Test-Path -Path $outDir)) {
$outDir = $env:TEMP
}
}
if (!($outDir -like "*\")) {
$outDir = $outDir+"\"
}
$dateTime = Get-Date -Format "yyyyMMdd_HHmmss"
$auditScenario = "SecuredCore"
$logFileName = $outDir+"WindowsBaseLine_SecuredCore_$datetime.log"
Write-Verbose $auditScenario
Write-Verbose "LogFile: $logFileName"
$results = (Get-OSConfigDesiredConfiguration -Scenario $auditScenario)
$results | ft Name, @{ Name = "Status"; Expression={$_.Compliance.Status} }, @{ Name = "Severity"; Expression={$_.Compliance.Severity} }, @{ Name = "Reason"; Expression={$_.Compliance.Reason} } -AutoSize -Wrap 2>&1| Out-File -Encoding default -FilePath $logFileName -width 160
$numOfCompliant = 0
$numOfTotal = 0
foreach ($result in $results) {
if($result.Compliance.Status -eq "Compliant") {
$numOfCompliant++
$numOfTotal++
} elseif ($result.Compliance.Status -eq "NotCompliant") {
$numOfTotal++
}
}
return [math]::Round(($numOfCompliant / $numOfTotal * 100),0)
[audit-securedcorestate.ps1](プレーンテキストで表示)(3/25追加)
[cmdletBinding()]
param($outDir)
function Check-WindowsServer2025 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
if ($osname.Contains("Windows Server 2025")) {
return $true
} else {
return $false
}
}
function Check-AzureLocal23H2 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
$osver = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion
if ($osname.Contains("Azure Stack HCI")) {
if ($osver -eq "23H2") {
return $true
} else {
return $false
}
} else {
return $false
}
}
function Check-MicrosoftOsConfigModule {
$osConfigModule = "Microsoft.OSConfig"
$moduleExists = Get-InstalledModule -Name $osConfigModule -AllVersions -ErrorAction silentlycontinue
if ($moduleExists) {
return $true
} else {
return $false
}
}
if (Check-WindowsServer2025) {
Write-Verbose "Check-WindowsServer2025: Windows Server 2025"
} else {
if (Check-AzureLocal23H2) {
Write-Verbose "Check-WindowsServer2025: Azure Local 23H2"
} else {
Write-Verbose "Check-WindowsServer2025: Unsupported Operating System"
return -1
exit
}
}
if (!(Check-MicrosoftOsConfigModule)) {
Write-Verbose "Check-MicrosoftOsConfigModule: OsConfig Module dows not exist"
return -1
exit
}
$auditScenario = ""
if($outDir -eq $null) {
$outDir = $env:TEMP
} else {
if(!(Test-Path -Path $outDir)) {
$outDir = $env:TEMP
}
}
if (!($outDir -like "*\")) {
$outDir = $outDir+"\"
}
$dateTime = Get-Date -Format "yyyyMMdd_HHmmss"
$auditScenario = "SecuredCoreState"
$logFileName = $outDir+"WindowsBaseLine_SecuredCoreState_$datetime.log"
Write-Verbose $auditScenario
Write-Verbose "LogFile: $logFileName"
$results = (Get-OSConfigDesiredConfiguration -Scenario $auditScenario)
$results | ft Name, @{ Name = "Status"; Expression={$_.Compliance.Status} }, @{ Name = "Severity"; Expression={$_.Compliance.Severity} }, @{ Name = "Reason"; Expression={$_.Compliance.Reason} } -AutoSize -Wrap 2>&1| Out-File -Encoding default -FilePath $logFileName -width 160
$numOfCompliant = 0
$numOfTotal = 0
foreach ($result in $results) {
if($result.Compliance.Status -eq "Compliant") {
$numOfCompliant++
$numOfTotal++
} elseif ($result.Compliance.Status -eq "NotCompliant") {
$numOfTotal++
}
}
return [math]::Round(($numOfCompliant / $numOfTotal * 100),0)
[audit-azurelocal.ps1](プレーンテキストで表示)
[cmdletBinding()]
param($outDir)
function Check-WindowsServer2025 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
if ($osname.Contains("Windows Server 2025")) {
return $true
} else {
return $false
}
}
function Check-AzureLocal23H2 {
$osname = (get-wmiobject Win32_OperatingSystem).Caption
$osver = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion
if ($osname.Contains("Azure Stack HCI")) {
if ($osver -eq "23H2") {
return $true
} else {
return $false
}
} else {
return $false
}
}
function Check-MicrosoftOsConfigModule {
$osConfigModule = "Microsoft.OSConfig"
$moduleExists = Get-InstalledModule -Name $osConfigModule -AllVersions -ErrorAction silentlycontinue
if ($moduleExists) {
return $true
} else {
return $false
}
}
if (Check-AzureLocal23H2) {
Write-Verbose "Check-WindowsServer2025: Azure Local 23H2"
} else {
Write-Verbose "Check-WindowsServer2025: Unsupported Operating System"
return -1
exit
}
if (!(Check-MicrosoftOsConfigModule)) {
Write-Verbose "Check-MicrosoftOsConfigModule: OsConfig Module dows not exist"
return -1
exit
}
$auditScenario = ""
if($outDir -eq $null) {
$outDir = $env:TEMP
} else {
if(!(Test-Path -Path $outDir)) {
$outDir = $env:TEMP
}
}
if (!($outDir -like "*\")) {
$outDir = $outDir+"\"
}
$dateTime = Get-Date -Format "yyyyMMdd_HHmmss"
$auditScenario = "SecurityBaseline/AzureStackHCI"
$logFileName = $outDir+"WindowsBaseLine_AzureLocal_$datetime.log"
Write-Verbose $auditScenario
Write-Verbose "LogFile: $logFileName"
$results = (Get-OSConfigDesiredConfiguration -Scenario $auditScenario)
$results | ft Name, @{ Name = "Status"; Expression={$_.Compliance.Status} }, @{ Name = "Severity"; Expression={$_.Compliance.Severity} }, @{ Name = "Reason"; Expression={$_.Compliance.Reason} } -AutoSize -Wrap 2>&1| Out-File -Encoding default -FilePath $logFileName -width 160
$numOfCompliant = 0
$numOfTotal = 0
foreach ($result in $results) {
if($result.Compliance.Status -eq "Compliant") {
$numOfCompliant++
$numOfTotal++
} elseif ($result.Compliance.Status -eq "NotCompliant") {
$numOfTotal++
}
}
return [math]::Round(($numOfCompliant / $numOfTotal * 100),0)
(2/4 11:50 母数にStatusを含まないエントリが含まれていたため、audit-*.ps1のスクリプトを修正しました。)
なお、これらのスクリプトに、セキュリティベースラインを適用、維持する機能は含まれていません。言ってみれば、OSConfigの監査モードでの利用です。ベースラインの展開については、以下の記事で確認してください。これらのスクリプトは、ベースラインの展開後の継続的なコンプライアンス状況の確認にも利用できます。
vol.80 CIS対応のセキュリティ態勢を簡単に導入、維持できる新機能「OSConfig」|Windows Server 2025大特集(17)
Windows Server 2025大特集(1)|...|(17)|メモ