@@ -2968,6 +2968,253 @@ function Invoke-CLIAction {
29682968
29692969 if ($failedCount -gt 0 ) { [Environment ]::Exit (1 ) }
29702970 }
2971+ ' DiskAudit' {
2972+ Write-OutputColor " Auditing disk health and utilization..." - color " Info"
2973+ Write-OutputColor " " - color " Info"
2974+
2975+ $diskIssues = 0
2976+ $volumes = @ ()
2977+ $physicalDisks = @ ()
2978+
2979+ # Physical disk health
2980+ try {
2981+ $pDisks = @ (Get-PhysicalDisk - ErrorAction Stop)
2982+ foreach ($d in $pDisks ) {
2983+ $health = ' OK'
2984+ if ($d.HealthStatus -ne ' Healthy' ) { $health = ' FAIL' ; $diskIssues ++ }
2985+ if ($d.OperationalStatus -ne ' OK' ) { $health = ' FAIL' ; if ($d.HealthStatus -eq ' Healthy' ) { $diskIssues ++ } }
2986+ $sizeGB = [math ]::Round($d.Size / 1 GB , 1 )
2987+ $physicalDisks += @ {
2988+ DeviceId = $d.DeviceId
2989+ FriendlyName = $d.FriendlyName
2990+ MediaType = " $ ( $d.MediaType ) "
2991+ BusType = " $ ( $d.BusType ) "
2992+ SizeGB = $sizeGB
2993+ HealthStatus = " $ ( $d.HealthStatus ) "
2994+ OperationalStatus = " $ ( $d.OperationalStatus ) "
2995+ Health = $health
2996+ }
2997+ }
2998+ } catch {
2999+ Write-OutputColor " WARNING: Could not query physical disks: $ ( $_.Exception.Message ) " - color " Warning"
3000+ }
3001+
3002+ # Volume utilization
3003+ try {
3004+ $vols = @ (Get-CimInstance - ClassName Win32_LogicalDisk - Filter " DriveType=3" - ErrorAction Stop)
3005+ foreach ($v in $vols ) {
3006+ $totalGB = [math ]::Round($v.Size / 1 GB , 1 )
3007+ $freeGB = [math ]::Round($v.FreeSpace / 1 GB , 1 )
3008+ $usedGB = [math ]::Round(($v.Size - $v.FreeSpace ) / 1 GB , 1 )
3009+ $pctFree = if ($v.Size -gt 0 ) { [math ]::Round(($v.FreeSpace / $v.Size ) * 100 , 1 ) } else { 0 }
3010+ $status = ' OK'
3011+ if ($pctFree -lt 10 ) { $status = ' WARN' ; $diskIssues ++ }
3012+ if ($pctFree -lt 5 ) { $status = ' CRITICAL' }
3013+ $volumes += @ {
3014+ Drive = $v.DeviceID
3015+ Label = $v.VolumeName
3016+ TotalGB = $totalGB
3017+ UsedGB = $usedGB
3018+ FreeGB = $freeGB
3019+ PctFree = $pctFree
3020+ Status = $status
3021+ }
3022+ }
3023+ } catch {
3024+ Write-OutputColor " ERROR: Failed to query volumes: $ ( $_.Exception.Message ) " - color " Error"
3025+ [Environment ]::Exit (1 )
3026+ }
3027+
3028+ # Console output
3029+ Write-OutputColor " ┌────────────────────────────────────────────────────────────────────────┐" - color " Info"
3030+ Write-OutputColor " │$ ( " DISK AUDIT - $env: COMPUTERNAME " .PadRight(72 )) │" - color " Info"
3031+ Write-OutputColor " ├────────────────────────────────────────────────────────────────────────┤" - color " Info"
3032+ if (@ ($physicalDisks ).Count -gt 0 ) {
3033+ Write-OutputColor " │$ ( " PHYSICAL DISKS" .PadRight(72 )) │" - color " Info"
3034+ foreach ($d in $physicalDisks ) {
3035+ $line = " $ ( $d.FriendlyName ) "
3036+ if ($line.Length -gt 35 ) { $line = $line.Substring (0 , 32 ) + " ..." }
3037+ $line = " $ ( $line.PadRight (36 )) $ ( $d.SizeGB ) GB $ ( $d.MediaType ) [$ ( $d.Health ) ]"
3038+ if ($line.Length -gt 72 ) { $line = $line.Substring (0 , 69 ) + " ..." }
3039+ $color = if ($d.Health -eq ' OK' ) { ' Success' } else { ' Error' }
3040+ Write-OutputColor " │$ ( $line.PadRight (72 )) │" - color $color
3041+ }
3042+ Write-OutputColor " ├────────────────────────────────────────────────────────────────────────┤" - color " Info"
3043+ }
3044+ Write-OutputColor " │$ ( " VOLUMES" .PadRight(72 )) │" - color " Info"
3045+ foreach ($v in $volumes ) {
3046+ $label = if ($v.Label ) { " ($ ( $v.Label ) )" } else { " " }
3047+ $line = " $ ( $v.Drive ) $label "
3048+ if ($line.Length -gt 20 ) { $line = $line.Substring (0 , 17 ) + " ..." }
3049+ $line = " $ ( $line.PadRight (22 )) $ ( $v.UsedGB ) /$ ( $v.TotalGB ) GB Free: $ ( $v.PctFree ) % [$ ( $v.Status ) ]"
3050+ if ($line.Length -gt 72 ) { $line = $line.Substring (0 , 69 ) + " ..." }
3051+ $color = switch ($v.Status ) { ' OK' { ' Success' } ' WARN' { ' Warning' } ' CRITICAL' { ' Error' } default { ' Info' } }
3052+ Write-OutputColor " │$ ( $line.PadRight (72 )) │" - color $color
3053+ }
3054+ Write-OutputColor " ├────────────────────────────────────────────────────────────────────────┤" - color " Info"
3055+ $summaryLine = " Disks: $ ( @ ($physicalDisks ).Count) Volumes: $ ( @ ($volumes ).Count) Issues: $diskIssues "
3056+ Write-OutputColor " │$ ( $summaryLine.PadRight (72 )) │" - color $ (if ($diskIssues -gt 0 ) { " Warning" } else { " Success" })
3057+ Write-OutputColor " └────────────────────────────────────────────────────────────────────────┘" - color " Info"
3058+
3059+ if ($script :CLIOutputFormat -eq ' JSON' ) {
3060+ $jsonResult = @ {
3061+ Tool = $script :ToolFullName
3062+ Version = $script :ScriptVersion
3063+ Action = ' DiskAudit'
3064+ Timestamp = (Get-Date - Format " yyyy-MM-ddTHH:mm:ss" )
3065+ Hostname = $env: COMPUTERNAME
3066+ Summary = @ {
3067+ PhysicalDisks = @ ($physicalDisks ).Count
3068+ Volumes = @ ($volumes ).Count
3069+ Issues = $diskIssues
3070+ }
3071+ PhysicalDisks = $physicalDisks
3072+ Volumes = $volumes
3073+ }
3074+ Write-Output ($jsonResult | ConvertTo-Json - Depth 10 )
3075+ }
3076+
3077+ if ($diskIssues -gt 0 ) { [Environment ]::Exit (1 ) }
3078+ }
3079+ ' TLSAudit' {
3080+ Write-OutputColor " Auditing TLS/SSL configuration..." - color " Info"
3081+ Write-OutputColor " " - color " Info"
3082+
3083+ $tlsIssues = 0
3084+ $protocols = @ ()
3085+ $regBase = ' HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols'
3086+
3087+ $protocolList = @ (
3088+ @ { Name = ' SSL 2.0' ; Secure = $false }
3089+ @ { Name = ' SSL 3.0' ; Secure = $false }
3090+ @ { Name = ' TLS 1.0' ; Secure = $false }
3091+ @ { Name = ' TLS 1.1' ; Secure = $false }
3092+ @ { Name = ' TLS 1.2' ; Secure = $true }
3093+ @ { Name = ' TLS 1.3' ; Secure = $true }
3094+ )
3095+
3096+ foreach ($proto in $protocolList ) {
3097+ $name = $proto.Name
3098+ $serverPath = " $regBase \$name \Server"
3099+ $clientPath = " $regBase \$name \Client"
3100+
3101+ $serverEnabled = $null
3102+ $clientEnabled = $null
3103+
3104+ # Check Server subkey
3105+ if (Test-Path $serverPath ) {
3106+ $serverReg = Get-ItemProperty - Path $serverPath - ErrorAction SilentlyContinue
3107+ if ($null -ne $serverReg -and $null -ne $serverReg.Enabled ) {
3108+ $serverEnabled = $serverReg.Enabled -ne 0
3109+ } elseif ($null -ne $serverReg -and $null -ne $serverReg.DisabledByDefault ) {
3110+ $serverEnabled = $serverReg.DisabledByDefault -eq 0
3111+ }
3112+ }
3113+
3114+ # Check Client subkey
3115+ if (Test-Path $clientPath ) {
3116+ $clientReg = Get-ItemProperty - Path $clientPath - ErrorAction SilentlyContinue
3117+ if ($null -ne $clientReg -and $null -ne $clientReg.Enabled ) {
3118+ $clientEnabled = $clientReg.Enabled -ne 0
3119+ } elseif ($null -ne $clientReg -and $null -ne $clientReg.DisabledByDefault ) {
3120+ $clientEnabled = $clientReg.DisabledByDefault -eq 0
3121+ }
3122+ }
3123+
3124+ # Determine effective status
3125+ # If registry keys don't exist, Windows uses defaults:
3126+ # SSL 2.0/3.0: disabled by default on modern Windows
3127+ # TLS 1.0/1.1: enabled by default (but deprecated)
3128+ # TLS 1.2/1.3: enabled by default
3129+ $effectiveServer = if ($null -ne $serverEnabled ) { $serverEnabled } else {
3130+ # Default behavior for unset protocols
3131+ switch ($name ) {
3132+ ' SSL 2.0' { $false }
3133+ ' SSL 3.0' { $false }
3134+ default { $true }
3135+ }
3136+ }
3137+ $effectiveClient = if ($null -ne $clientEnabled ) { $clientEnabled } else {
3138+ switch ($name ) {
3139+ ' SSL 2.0' { $false }
3140+ ' SSL 3.0' { $false }
3141+ default { $true }
3142+ }
3143+ }
3144+
3145+ $status = ' OK'
3146+ $configured = $null -ne $serverEnabled -or $null -ne $clientEnabled
3147+
3148+ if (-not $proto.Secure -and ($effectiveServer -or $effectiveClient )) {
3149+ $status = if ($name -match ' SSL' ) { ' CRITICAL' } else { ' WARN' }
3150+ $tlsIssues ++
3151+ }
3152+ if ($proto.Secure -and -not $effectiveServer -and -not $effectiveClient ) {
3153+ $status = ' CRITICAL' ; $tlsIssues ++
3154+ }
3155+
3156+ $protocols += @ {
3157+ Protocol = $name
3158+ ServerEnabled = $effectiveServer
3159+ ClientEnabled = $effectiveClient
3160+ Configured = $configured
3161+ Secure = $proto.Secure
3162+ Status = $status
3163+ }
3164+ }
3165+
3166+ # Check .NET strong crypto settings
3167+ $netFx64 = ' HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319'
3168+ $netFx32 = ' HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319'
3169+ $strongCrypto64 = $false
3170+ $strongCrypto32 = $false
3171+ try {
3172+ $reg64 = Get-ItemProperty - Path $netFx64 - ErrorAction SilentlyContinue
3173+ if ($null -ne $reg64 -and $null -ne $reg64.SchUseStrongCrypto ) { $strongCrypto64 = $reg64.SchUseStrongCrypto -eq 1 }
3174+ $reg32 = Get-ItemProperty - Path $netFx32 - ErrorAction SilentlyContinue
3175+ if ($null -ne $reg32 -and $null -ne $reg32.SchUseStrongCrypto ) { $strongCrypto32 = $reg32.SchUseStrongCrypto -eq 1 }
3176+ } catch { }
3177+
3178+ # Console output
3179+ Write-OutputColor " ┌────────────────────────────────────────────────────────────────────────┐" - color " Info"
3180+ Write-OutputColor " │$ ( " TLS AUDIT - $env: COMPUTERNAME " .PadRight(72 )) │" - color " Info"
3181+ Write-OutputColor " ├────────────────────────────────────────────────────────────────────────┤" - color " Info"
3182+ foreach ($p in $protocols ) {
3183+ $serverStr = if ($p.ServerEnabled ) { " On" } else { " Off" }
3184+ $clientStr = if ($p.ClientEnabled ) { " On" } else { " Off" }
3185+ $cfgStr = if ($p.Configured ) { " Explicit" } else { " Default" }
3186+ $line = " $ ( $p.Protocol.PadRight (10 )) Server: $ ( $serverStr.PadRight (5 )) Client: $ ( $clientStr.PadRight (5 )) ($cfgStr ) [$ ( $p.Status ) ]"
3187+ if ($line.Length -gt 72 ) { $line = $line.Substring (0 , 69 ) + " ..." }
3188+ $color = switch ($p.Status ) { ' OK' { ' Success' } ' WARN' { ' Warning' } ' CRITICAL' { ' Error' } default { ' Info' } }
3189+ Write-OutputColor " │$ ( $line.PadRight (72 )) │" - color $color
3190+ }
3191+ Write-OutputColor " ├────────────────────────────────────────────────────────────────────────┤" - color " Info"
3192+ $scLine = " .NET Strong Crypto: x64=$ ( if ($strongCrypto64 ) { ' Yes' } else { ' No' }) x86=$ ( if ($strongCrypto32 ) { ' Yes' } else { ' No' }) "
3193+ $scColor = if ($strongCrypto64 -and $strongCrypto32 ) { " Success" } else { " Warning" }
3194+ Write-OutputColor " │$ ( $scLine.PadRight (72 )) │" - color $scColor
3195+ $summaryLine = " Issues: $tlsIssues "
3196+ Write-OutputColor " │$ ( $summaryLine.PadRight (72 )) │" - color $ (if ($tlsIssues -gt 0 ) { " Warning" } else { " Success" })
3197+ Write-OutputColor " └────────────────────────────────────────────────────────────────────────┘" - color " Info"
3198+
3199+ if ($script :CLIOutputFormat -eq ' JSON' ) {
3200+ $jsonResult = @ {
3201+ Tool = $script :ToolFullName
3202+ Version = $script :ScriptVersion
3203+ Action = ' TLSAudit'
3204+ Timestamp = (Get-Date - Format " yyyy-MM-ddTHH:mm:ss" )
3205+ Hostname = $env: COMPUTERNAME
3206+ Summary = @ {
3207+ Issues = $tlsIssues
3208+ StrongCrypto64 = $strongCrypto64
3209+ StrongCrypto32 = $strongCrypto32
3210+ }
3211+ Protocols = $protocols
3212+ }
3213+ Write-Output ($jsonResult | ConvertTo-Json - Depth 10 )
3214+ }
3215+
3216+ if ($tlsIssues -gt 0 ) { [Environment ]::Exit (1 ) }
3217+ }
29713218 default {
29723219 Write-OutputColor " Unknown CLI action: $ ( $script :CLIAction ) " - color " Error"
29733220 [Environment ]::Exit (1 )
0 commit comments