mirror of
https://github.com/Yamato-Security/WELA.git
synced 2025-12-07 01:32:50 +01:00
Merge pull request #16 from Yamato-Security/15-output-horizontally
feat: Output horizontally
This commit is contained in:
2
.github/workflows/check-audit.yml
vendored
2
.github/workflows/check-audit.yml
vendored
@@ -2,7 +2,7 @@ name: Check audit setting
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
branches: [ "*" ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
12
.github/workflows/create-rule-meta.yml
vendored
12
.github/workflows/create-rule-meta.yml
vendored
@@ -19,15 +19,3 @@ jobs:
|
||||
|
||||
- name: Run
|
||||
run: cd wela-extractor && cargo run --release -- ../hayabusa-rules ../config/eid_subcategory_mapping.csv ../config/security_rules.json
|
||||
|
||||
- name: Push changes
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
git add *.json
|
||||
git commit -m "Automated update"
|
||||
if [ "$(git log -1 --pretty=%B)" = "Automated update" ]; then
|
||||
git push origin main
|
||||
fi
|
||||
|
||||
183
WELA.ps1
183
WELA.ps1
@@ -1,127 +1,4 @@
|
||||
function CheckRegistryValue {
|
||||
param (
|
||||
[string]$registryPath,
|
||||
[string]$valueName,
|
||||
[int]$expectedValue
|
||||
)
|
||||
|
||||
try {
|
||||
$value = Get-ItemProperty -Path $registryPath -Name $valueName -ErrorAction Stop
|
||||
if ($value.$valueName -eq $expectedValue) {
|
||||
return $true
|
||||
} else {
|
||||
return $false
|
||||
}
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Set-Applicable {
|
||||
param (
|
||||
[string]$autidpolTxt,
|
||||
[string]$jsonRulePath
|
||||
)
|
||||
|
||||
$extractedGuids = [System.Collections.Generic.HashSet[string]]::new()
|
||||
Get-Content -Path $autidpolTxt | Select-String -NotMatch "No Auditing" | ForEach-Object {
|
||||
if ($_ -match '{(.*?)}') {
|
||||
[void]$extractedGuids.Add($matches[1])
|
||||
}
|
||||
}
|
||||
|
||||
$pwshModuleLogging = CheckRegistryValue -registryPath "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging" -valueName "EnableModuleLogging" -expectedValue 1
|
||||
$pwshScriptLogging = CheckRegistryValue -registryPath "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -valueName "EnableScriptBlockLogging" -expectedValue 1
|
||||
|
||||
$jsonContent = Get-Content -Path $jsonRulePath -Raw | ConvertFrom-Json
|
||||
foreach ($rule in $jsonContent) {
|
||||
$rule | Add-Member -MemberType NoteProperty -Name "applicable" -Value $false
|
||||
if ($rule.channel -eq "pwsh") {
|
||||
if ($rule.event_ids -contains "400") {
|
||||
$rule.applicable = $true
|
||||
} elseif ($rule.event_ids -contains "4103") {
|
||||
$rule.applicable = $pwshModuleLogging
|
||||
} elseif ($rule.event_ids -contains "4104") {
|
||||
$rule.applicable = $pwshScriptLogging
|
||||
}
|
||||
continue
|
||||
}
|
||||
foreach ($guid in $rule.subcategory_guids) {
|
||||
if ($extractedGuids.Contains($guid)) {
|
||||
$rule.applicable = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return $jsonContent
|
||||
}
|
||||
|
||||
function Get-RuleCounts {
|
||||
param ($rules)
|
||||
$rules | Group-Object -Property level | ForEach-Object {
|
||||
[PSCustomObject]@{
|
||||
Level = $_.Name
|
||||
Count = $_.Count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function CalculateUsableRate {
|
||||
param ($counts, $totalCounts)
|
||||
$result = @()
|
||||
$totalCounts | ForEach-Object {
|
||||
$level = $_.Level
|
||||
$total = $_.Count
|
||||
$usableCount = ($counts | Where-Object Level -eq $level | Select-Object -ExpandProperty Count -First 1)
|
||||
if ($null -eq $usableCount) { $usableCount = 0 }
|
||||
$percentage = if ($total -ne 0) { "{0:N2}" -f ($usableCount / $total * 100) } else { "0.00" }
|
||||
$result += [PSCustomObject]@{
|
||||
Level = $level
|
||||
UsableCount = $usableCount
|
||||
TotalCount = $total
|
||||
Percentage = $percentage
|
||||
}
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
function ShowRulesCountsByLevel {
|
||||
param ($usableRate, $msg)
|
||||
Write-Output $msg
|
||||
$levelColorMap = [ordered]@{
|
||||
"critical" = "Red"
|
||||
"high" = "DarkYellow"
|
||||
"medium" = "Yellow"
|
||||
"low" = "Green"
|
||||
"informational" = "White" # Assuming a default color for informational
|
||||
}
|
||||
|
||||
$usableRate | Sort-Object { $levelColorMap.Keys.IndexOf($_.Level) } | ForEach-Object {
|
||||
$color = $levelColorMap[$_.Level]
|
||||
Write-Host "$($_.Level) rules: $($_.UsableCount) / $($_.TotalCount) ($($_.Percentage)%)" -ForegroundColor $color
|
||||
}
|
||||
Write-Output ""
|
||||
Write-Output ""
|
||||
}
|
||||
|
||||
function Test-IsAdministrator {
|
||||
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator
|
||||
return (New-Object Security.Principal.WindowsPrincipal($currentUser)).IsInRole($adminRole)
|
||||
}
|
||||
|
||||
if (-not (Test-IsAdministrator)) {
|
||||
Write-Output "This script must be run as an Administrator."
|
||||
exit
|
||||
}
|
||||
|
||||
# Set the console encoding to UTF-8
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# Step 1: Run the auditpol command using cmd.exe and redirect its output to a file
|
||||
$autidpolTxt = "auditpol_output.txt"
|
||||
Start-Process -FilePath "cmd.exe" -ArgumentList "/c chcp 437 & auditpol /get /category:* /r" -NoNewWindow -Wait -RedirectStandardOutput $autidpolTxt
|
||||
|
||||
Import-Module -Name ./WELAFunctions.psm1
|
||||
$logo = @"
|
||||
┏┓┏┓┏┳━━━┳┓ ┏━━━┓
|
||||
┃┃┃┃┃┃┏━━┫┃ ┃┏━┓┃
|
||||
@@ -132,51 +9,68 @@ $logo = @"
|
||||
by Yamato Security
|
||||
|
||||
"@
|
||||
|
||||
# Set the console encoding to UTF-8
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# Step 1: Run the auditpol command using cmd.exe and redirect its output to a file
|
||||
$autidpolTxt = "auditpol_output.txt"
|
||||
Start-Process -FilePath "cmd.exe" -ArgumentList "/c chcp 437 & auditpol /get /category:* /r" -NoNewWindow -Wait -RedirectStandardOutput $autidpolTxt
|
||||
|
||||
Write-Host $logo -ForegroundColor Green
|
||||
|
||||
# Step 3: Set the applicable flag for each rule
|
||||
$rules = Set-Applicable -autidpolTxt $autidpolTxt -jsonRulePath "./config/security_rules.json"
|
||||
|
||||
|
||||
$allSecRules = $rules | Where-Object { $_.channel -eq "sec" }
|
||||
$allPwsClaRules = $rules | Where-Object { $_.channel -eq "pwsh" -and $_.event_ids -contains "400" }
|
||||
$allSecRules = $rules | Where-Object { $_.channel -eq "sec" }
|
||||
$allPwsRules = $rules | Where-Object { $_.channel -eq "pwsh" }
|
||||
$allPwsClaRules = $rules | Where-Object { $_.channel -eq "pwsh" -and ($_.event_ids -contains "400" -or $_.event_ids -contains "600" -or $_.event_ids.Count -eq 0) }
|
||||
$allPwsModRules = $rules | Where-Object { $_.channel -eq "pwsh" -and $_.event_ids -contains "4103" }
|
||||
$allPwsScrRules = $rules | Where-Object { $_.channel -eq "pwsh" -and $_.event_ids -contains "4104" }
|
||||
|
||||
$usableSecRules = $rules | Where-Object { $_.applicable -eq $true -and $_.channel -eq "sec" }
|
||||
$usablePwsRules = $rules | Where-Object { $_.applicable -eq $true -and $_.channel -eq "pwsh" }
|
||||
$usablePwsClaRules = $rules | Where-Object { $_.applicable -eq $true -and $_.channel -eq "pwsh" -and $_.event_ids -contains "400" }
|
||||
$usableSecRules = $rules | Where-Object { $_.applicable -eq $true -and $_.channel -eq "sec" }
|
||||
$usablePwsRules = $rules | Where-Object { $_.applicable -eq $true -and $_.channel -eq "pwsh" }
|
||||
$usablePwsClaRules = $rules | Where-Object { $_.applicable -eq $true -and $_.channel -eq "pwsh" -and ($_.event_ids -contains "400" -or $_.event_ids -contains "600" -or $_.event_ids.Count -eq 0) }
|
||||
$usablePwsModRules = $rules | Where-Object { $_.applicable -eq $true -and $_.channel -eq "pwsh" -and $_.event_ids -contains "4103" }
|
||||
$usablePwsScrRules = $rules | Where-Object { $_.applicable -eq $true -and $_.channel -eq "pwsh" -and $_.event_ids -contains "4104" }
|
||||
|
||||
$unusableRules = $rules | Where-Object { $_.applicable -eq $false }
|
||||
|
||||
# Step 4: Count the number of usable and unusable rules for each level
|
||||
$totalCounts = Get-RuleCounts -rules $rules
|
||||
$totalSecCounts = Get-RuleCounts -rules $allSecRules
|
||||
$totalPwsCounts = Get-RuleCounts -rules $allPwsClaRules
|
||||
$totalCounts = Get-RuleCounts -rules $rules
|
||||
$totalSecCounts = Get-RuleCounts -rules $allSecRules
|
||||
$totalPwsCounts = Get-RuleCounts -rules $allPwsRules
|
||||
$totalPwsClaCounts = Get-RuleCounts -rules $allPwsClaRules
|
||||
$totalPwsModCounts = Get-RuleCounts -rules $allPwsModRules
|
||||
$totalPwsScrCounts = Get-RuleCounts -rules $allPwsScrRules
|
||||
|
||||
$usableSecCounts = Get-RuleCounts -rules $usableSecRules
|
||||
$usablePwsCounts = Get-RuleCounts -rules $usablePwsRules
|
||||
$usableSecCounts = Get-RuleCounts -rules $usableSecRules
|
||||
$usablePwsCounts = Get-RuleCounts -rules $usablePwsRules
|
||||
$usablePwsClaCounts = Get-RuleCounts -rules $usablePwsClaRules
|
||||
$usablePwsModCounts = Get-RuleCounts -rules $usablePwsModRules
|
||||
$usablePwsScrCounts = Get-RuleCounts -rules $usablePwsScrRules
|
||||
|
||||
# Step 5: Calculate the usable rate for each level
|
||||
$usableSecRate = CalculateUsableRate -counts $usableSecCounts -totalCounts $totalSecCounts
|
||||
$usablePwsRate = CalculateUsableRate -counts $usablePwsCounts -totalCounts $totalPwsCounts
|
||||
$usableSecRate = CalculateUsableRate -counts $usableSecCounts -totalCounts $totalSecCounts
|
||||
$usablePwsRate = CalculateUsableRate -counts $usablePwsCounts -totalCounts $totalPwsCounts
|
||||
$usablePwsClaRate = CalculateUsableRate -counts $usablePwsClaCounts -totalCounts $totalPwsClaCounts
|
||||
$usablePwsModRate = CalculateUsableRate -counts $usablePwsModCounts -totalCounts $totalPwsModCounts
|
||||
$usablePwsScrRate = CalculateUsableRate -counts $usablePwsScrCounts -totalCounts $totalPwsScrCounts
|
||||
|
||||
# Step 6: Show the number of usable and unusable rules for each level
|
||||
ShowRulesCountsByLevel -usableRate $usableSecRate -msg "Security event log detection rules:"
|
||||
ShowRulesCountsByLevel -usableRate $usablePwsClaRate -msg "PowerShell classic logging detection rules:"
|
||||
ShowRulesCountsByLevel -usableRate $usablePwsModRate -msg "PowerShell module logging detection rules:"
|
||||
ShowRulesCountsByLevel -usableRate $usablePwsScrRate -msg "PowerShell script block logging detection rules:"
|
||||
$pwsModEnabled = CheckRegistryValue -registryPath "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging" -valueName "EnableModuleLogging" -expectedValue 1
|
||||
$pwsScrEnabled = CheckRegistryValue -registryPath "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -valueName "EnableScriptBlockLogging" -expectedValue 1
|
||||
$pwsModStatus = if ($pwsModEnabled) { "Enabled" } else { "Disabled" }
|
||||
$pwsSrcStatus = if ($pwsScrEnabled) { "Enabled" } else { "Disabled" }
|
||||
|
||||
# Step 7: Calculate the total usable rate
|
||||
$totalUsableSecRate = CalculateTotalUsableRate -usableRate $usableSecRate
|
||||
$totalUsablePwsClaRate = CalculateTotalUsableRate -usableRate $usablePwsClaRate
|
||||
$totalUsablePwsModRate = CalculateTotalUsableRate -usableRate $usablePwsModRate
|
||||
$totalUsablePwsScrRate = CalculateTotalUsableRate -usableRate $usablePwsScrRate
|
||||
|
||||
ShowRulesCountsByLevel -usableRate $usableSecRate -msg "Security event log detection rules: " -colorMsg "$totalUsableSecRate (Partially Enabled)"
|
||||
ShowRulesCountsByLevel -usableRate $usablePwsClaRate -msg "PowerShell classic logging detection rules: " -colorMsg "$totalUsablePwsClaRate (Enabled)"
|
||||
ShowRulesCountsByLevel -usableRate $usablePwsModRate -msg "PowerShell module logging detection rules: " -colorMsg "$totalUsablePwsModRate ($pwsModStatus)"
|
||||
ShowRulesCountsByLevel -usableRate $usablePwsScrRate -msg "PowerShell script block logging detection rules: " -colorMsg "$totalUsablePwsScrRate ($pwsSrcStatus)"
|
||||
|
||||
Write-Output "Usable detection rules list saved to: UsableRules.csv"
|
||||
Write-Output "Unusable detection rules list saved to: UnusableRules.csv"
|
||||
@@ -186,6 +80,7 @@ $totalRulesCount = ($totalCounts | Measure-Object -Property Count -Sum).Sum
|
||||
$utilizationPercentage = "{0:N2}" -f (($totalUsable / $totalRulesCount) * 100)
|
||||
Write-Output "You can utilize $utilizationPercentage% of your detection rules."
|
||||
|
||||
# Step 7: Save the lists of usable and unusable rules to CSV files
|
||||
# Step 8: Save the lists of usable and unusable rules to CSV files
|
||||
$unusableRules = $rules | Where-Object { $_.applicable -eq $false }
|
||||
$usableSecRules | Select-Object title, level, id | Export-Csv -Path "UsableRules.csv" -NoTypeInformation
|
||||
$unusableRules | Select-Object title, level, id | Export-Csv -Path "UnusableRules.csv" -NoTypeInformation
|
||||
|
||||
227
WELAFunctions.psm1
Normal file
227
WELAFunctions.psm1
Normal file
@@ -0,0 +1,227 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Checks if a registry value matches the expected value.
|
||||
.DESCRIPTION
|
||||
This function retrieves a registry value and compares it to the expected value.
|
||||
.PARAMETER registryPath
|
||||
The path to the registry key.
|
||||
.PARAMETER valueName
|
||||
The name of the registry value.
|
||||
.PARAMETER expectedValue
|
||||
The expected value to compare against.
|
||||
.RETURNS
|
||||
[bool] $true if the registry value matches the expected value, otherwise $false.
|
||||
#>
|
||||
function CheckRegistryValue {
|
||||
param (
|
||||
[string]$registryPath,
|
||||
[string]$valueName,
|
||||
[int]$expectedValue
|
||||
)
|
||||
|
||||
try {
|
||||
$value = Get-ItemProperty -Path $registryPath -Name $valueName -ErrorAction Stop
|
||||
if ($value.$valueName -eq $expectedValue) {
|
||||
return $true
|
||||
} else {
|
||||
return $false
|
||||
}
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sets the applicable rules based on the provided audit policy text and JSON rule path.
|
||||
|
||||
.DESCRIPTION
|
||||
This function reads the audit policy text file and extracts GUIDs. It then checks the registry values for PowerShell logging settings and updates the applicability of rules in the JSON file based on these settings and the extracted GUIDs.
|
||||
|
||||
.PARAMETER autidpolTxt
|
||||
The path to the audit policy text file.
|
||||
|
||||
.PARAMETER jsonRulePath
|
||||
The path to the JSON rule file.
|
||||
|
||||
.RETURNS
|
||||
The updated JSON content with the applicability of rules set.
|
||||
|
||||
.EXAMPLE
|
||||
Set-Applicable -autidpolTxt "C:\path\to\auditpol.txt" -jsonRulePath "C:\path\to\rules.json"
|
||||
#>
|
||||
function Set-Applicable {
|
||||
param (
|
||||
[string]$autidpolTxt,
|
||||
[string]$jsonRulePath
|
||||
)
|
||||
|
||||
$extractedGuids = [System.Collections.Generic.HashSet[string]]::new()
|
||||
Get-Content -Path $autidpolTxt | Select-String -NotMatch "No Auditing" | ForEach-Object {
|
||||
if ($_ -match '{(.*?)}') {
|
||||
[void]$extractedGuids.Add($matches[1])
|
||||
}
|
||||
}
|
||||
|
||||
$pwshModuleLogging = CheckRegistryValue -registryPath "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging" -valueName "EnableModuleLogging" -expectedValue 1
|
||||
$pwshScriptLogging = CheckRegistryValue -registryPath "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -valueName "EnableScriptBlockLogging" -expectedValue 1
|
||||
|
||||
$jsonContent = Get-Content -Path $jsonRulePath -Raw | ConvertFrom-Json
|
||||
foreach ($rule in $jsonContent) {
|
||||
$rule | Add-Member -MemberType NoteProperty -Name "applicable" -Value $false
|
||||
if ($rule.channel -eq "pwsh") {
|
||||
if ($rule.event_ids -contains "400" -or $rule.event_ids -contains "600" -or $rule.event_ids.Count -eq 0) {
|
||||
$rule.applicable = $true
|
||||
} elseif ($rule.event_ids -contains "4103") {
|
||||
$rule.applicable = $pwshModuleLogging
|
||||
} elseif ($rule.event_ids -contains "4104") {
|
||||
$rule.applicable = $pwshScriptLogging
|
||||
}
|
||||
continue
|
||||
}
|
||||
foreach ($guid in $rule.subcategory_guids) {
|
||||
if ($extractedGuids.Contains($guid)) {
|
||||
$rule.applicable = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return $jsonContent
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Groups the rules by their level and counts the number of rules in each level.
|
||||
.PARAMETER rules
|
||||
The collection of rules to be grouped and counted.
|
||||
.RETURNS
|
||||
A hashtable with the count of rules for each level.
|
||||
#>
|
||||
function Get-RuleCounts {
|
||||
param ($rules)
|
||||
$levels = @("critical", "high", "medium", "low", "informational")
|
||||
$counts = @{}
|
||||
|
||||
$rules | Group-Object -Property level | ForEach-Object {
|
||||
$counts[$_.Name] = $_.Count
|
||||
}
|
||||
|
||||
foreach ($level in $levels) {
|
||||
if (-not $counts.ContainsKey($level)) {
|
||||
$counts[$level] = 0
|
||||
}
|
||||
}
|
||||
|
||||
return $counts.GetEnumerator() | ForEach-Object {
|
||||
[PSCustomObject]@{
|
||||
Level = $_.Key
|
||||
Count = $_.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Calculates the usable rate of rules based on their counts and total counts.
|
||||
.PARAMETER counts
|
||||
The counts of usable rules for each level.
|
||||
.PARAMETER totalCounts
|
||||
The total counts of rules for each level.
|
||||
.RETURNS
|
||||
A collection of objects representing the usable rate for each level.
|
||||
#>
|
||||
function CalculateUsableRate {
|
||||
param ($counts, $totalCounts)
|
||||
$result = @()
|
||||
$totalCounts | ForEach-Object {
|
||||
$level = $_.Level
|
||||
$total = $_.Count
|
||||
$usableCount = ($counts | Where-Object Level -eq $level | Select-Object -ExpandProperty Count -First 1)
|
||||
if ($null -eq $usableCount) { $usableCount = 0 }
|
||||
$percentage = if ($total -ne 0) { "{0:N2}" -f ($usableCount / $total * 100) } else { "0.00" }
|
||||
$result += [PSCustomObject]@{
|
||||
Level = $level
|
||||
UsableCount = $usableCount
|
||||
TotalCount = $total
|
||||
Percentage = $percentage
|
||||
}
|
||||
}
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Calculates the total usable rate of rules.
|
||||
.PARAMETER usableRate
|
||||
The collection of objects representing the usable rate for each level.
|
||||
.RETURNS
|
||||
A string representing the total usable rate as a percentage.
|
||||
#>
|
||||
function CalculateTotalUsableRate {
|
||||
param ($usableRate)
|
||||
$totalUsable = ($usableRate | Measure-Object -Property UsableCount -Sum).Sum
|
||||
$totalRulesCount = ($usableRate | Measure-Object -Property TotalCount -Sum).Sum
|
||||
return "{0:N2}%" -f ($totalUsable / $totalRulesCount * 100)
|
||||
}
|
||||
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Displays the counts of rules by their level with color-coded output.
|
||||
.PARAMETER usableRate
|
||||
The collection of objects representing the usable rate for each level.
|
||||
.PARAMETER msg
|
||||
The message to display before the counts.
|
||||
.PARAMETER colorMsg
|
||||
The message to display with color coding.
|
||||
#>
|
||||
function ShowRulesCountsByLevel {
|
||||
param ($usableRate, $msg, $colorMsg)
|
||||
Write-Host -NoNewline $msg
|
||||
$color = if ($colorMsg -match "Disabled") { "Red" } elseif ($colorMsg -match "Partially") { "Yellow" } else { "Green" }
|
||||
Write-Host "$colorMsg" -ForegroundColor $color
|
||||
$levelColorMap = [ordered]@{
|
||||
"critical" = "Red"
|
||||
"high" = "DarkYellow"
|
||||
"medium" = "Yellow"
|
||||
"low" = "Green"
|
||||
"informational" = "White" # Assuming a default color for informational
|
||||
}
|
||||
$i = 0
|
||||
Write-Host -NoNewline " - "
|
||||
$usableRate | Sort-Object { $levelColorMap.Keys.IndexOf($_.Level) } | ForEach-Object {
|
||||
$color = $levelColorMap[$_.Level]
|
||||
$level = if ($_.Level -match "informational") { "info" } else { $_.Level }
|
||||
Write-Host -NoNewline "$($level): $($_.UsableCount)/$($_.TotalCount) ($($_.Percentage)%)" -ForegroundColor $color
|
||||
if ($i -lt $usableRate.Count - 1)
|
||||
{
|
||||
Write-Host -NoNewline ", "
|
||||
}
|
||||
$i++
|
||||
}
|
||||
Write-Output ""
|
||||
Write-Output ""
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Checks if the current user is an administrator.
|
||||
.DESCRIPTION
|
||||
This function determines if the current user has administrative privileges.
|
||||
.RETURNS
|
||||
[bool] $true if the current user is an administrator, otherwise $false.
|
||||
#>
|
||||
function Test-IsAdministrator {
|
||||
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator
|
||||
return (New-Object Security.Principal.WindowsPrincipal($currentUser)).IsInRole($adminRole)
|
||||
}
|
||||
|
||||
if (-not (Test-IsAdministrator)) {
|
||||
Write-Output "This script must be run as an Administrator."
|
||||
exit
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user