Howard's personal MSP client documentation folder imported into shared
ClaudeTools repo via /import command. Scope:
Clients (structured MSP docs under clients/<name>/docs/):
- anaise (NEW) - 13 files
- cascades-tucson - 47 files merged (existing had only reports/)
- dataforth - 18 files merged (alongside incident reports)
- instrumental-music-center - 14 files merged
- khalsa (NEW) - 22 files, multi-site (camden, river)
- kittle (NEW) - 16 files incl. fix-pdf-preview, gpo-intranet-zone
- lens-auto-brokerage (NEW) - 3 files (name matches SOPS vault)
- _client_template - 13-file scaffold for new clients
MSP tooling (projects/msp-tools/):
- msp-audit-scripts/ - server_audit.ps1, workstation_audit.ps1, README
- utilities/ - clean_printer_ports, win11_upgrade,
screenconnect-toolbox-commands
Credential handling:
- Extracted 1 inline password (Anaise DESKTOP-O8GF4SD / david)
to SOPS vault: clients/anaise/desktop-o8gf4sd.sops.yaml
- Redacted overview.md with vault reference pattern
- Scanned all 160 files for keys/tokens/connection strings -
no other credentials found
Skipped:
- Cascades/.claude/settings.local.json (per-machine config)
- Source-root CLAUDE.md (personal, claudetools has its own)
- scripts/server_audit.ps1 and workstation_audit.ps1 at source root
(identical duplicates of msp-audit-scripts versions)
Memory updates:
- reference_client_docs_structure.md (layout, conventions, active list)
- reference_msp_audit_scripts.md (locations, ScreenConnect 80-char rule)
Session log: session-logs/2026-04-16-howard-client-docs-import.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
136 lines
5.6 KiB
PowerShell
136 lines
5.6 KiB
PowerShell
#Requires -RunAsAdministrator
|
|
<#
|
|
.SYNOPSIS
|
|
Phase 0: Quick remote health checks on CS-SERVER.
|
|
.DESCRIPTION
|
|
Checks disk health (Dell OpenManage), identifies unknown listening ports,
|
|
audits IIS websites, and reports general server health.
|
|
Run on CS-SERVER via ScreenConnect.
|
|
.NOTES
|
|
Run during Phase 0 / Session 3 (2026-03-07) while backup is in progress.
|
|
#>
|
|
|
|
Write-Host "=== CS-SERVER Remote Health Checks ===" -ForegroundColor Cyan
|
|
Write-Host "Timestamp: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
|
Write-Host ""
|
|
|
|
# --- Disk Health (Dell OpenManage) ---
|
|
Write-Host "--- Disk Health ---" -ForegroundColor Yellow
|
|
|
|
$omreport = "C:\Program Files\Dell\SysMgt\oma\bin\omreport.exe"
|
|
if (Test-Path $omreport) {
|
|
Write-Host "[Physical Disks]" -ForegroundColor Cyan
|
|
& $omreport storage pdisk controller=0
|
|
|
|
Write-Host "`n[Virtual Disks]" -ForegroundColor Cyan
|
|
& $omreport storage vdisk controller=0
|
|
|
|
Write-Host "`n[Controller Battery]" -ForegroundColor Cyan
|
|
& $omreport storage battery controller=0
|
|
} else {
|
|
Write-Host "[WARN] Dell OpenManage CLI not found at: $omreport" -ForegroundColor Yellow
|
|
Write-Host "Try these alternatives:" -ForegroundColor Yellow
|
|
Write-Host " - OpenManage web UI: https://192.168.2.254:1311"
|
|
|
|
# Try alternate paths
|
|
$altPaths = @(
|
|
"C:\Program Files (x86)\Dell\SysMgt\oma\bin\omreport.exe",
|
|
"C:\Program Files\Dell\OpenManage\oma\bin\omreport.exe"
|
|
)
|
|
foreach ($p in $altPaths) {
|
|
if (Test-Path $p) {
|
|
Write-Host " - Found at: $p" -ForegroundColor Green
|
|
}
|
|
}
|
|
|
|
# Fallback: Windows disk health
|
|
Write-Host "`n[Windows Disk Health - Fallback]" -ForegroundColor Cyan
|
|
Get-PhysicalDisk | Select-Object DeviceId, FriendlyName, MediaType, Size, HealthStatus, OperationalStatus | Format-Table -AutoSize
|
|
Get-Volume | Where-Object { $_.DriveLetter } | Select-Object DriveLetter, FileSystemLabel, FileSystem, @{N='SizeGB';E={[math]::Round($_.Size/1GB,1)}}, @{N='FreeGB';E={[math]::Round($_.SizeRemaining/1GB,1)}}, HealthStatus | Format-Table -AutoSize
|
|
}
|
|
|
|
# --- Unknown Listening Ports ---
|
|
Write-Host "`n--- Unknown Port Identification ---" -ForegroundColor Yellow
|
|
|
|
$unknownPorts = @(5504, 6783, 8019)
|
|
foreach ($port in $unknownPorts) {
|
|
$conns = Get-NetTCPConnection -LocalPort $port -ErrorAction SilentlyContinue
|
|
if ($conns) {
|
|
foreach ($conn in $conns) {
|
|
$proc = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue
|
|
$svc = Get-CimInstance Win32_Service | Where-Object { $_.ProcessId -eq $conn.OwningProcess } | Select-Object -First 1
|
|
Write-Host "Port $port`:" -ForegroundColor Green -NoNewline
|
|
Write-Host " PID=$($conn.OwningProcess), Process=$($proc.ProcessName), Service=$($svc.Name)"
|
|
if ($proc.Path) { Write-Host " Path: $($proc.Path)" }
|
|
Write-Host " Local: $($conn.LocalAddress):$($conn.LocalPort) State: $($conn.State)"
|
|
}
|
|
} else {
|
|
Write-Host "Port $port`: No active listener" -ForegroundColor Yellow
|
|
}
|
|
}
|
|
|
|
# --- IIS Websites ---
|
|
Write-Host "`n--- IIS Websites ---" -ForegroundColor Yellow
|
|
|
|
try {
|
|
Import-Module WebAdministration -ErrorAction Stop
|
|
$sites = Get-Website
|
|
if ($sites) {
|
|
foreach ($site in $sites) {
|
|
Write-Host "Site: $($site.Name)" -ForegroundColor Green
|
|
Write-Host " State: $($site.State)"
|
|
Write-Host " Path: $($site.PhysicalPath)"
|
|
Write-Host " Bindings: $(($site.bindings.Collection | ForEach-Object { $_.bindingInformation }) -join ', ')"
|
|
Write-Host " App Pool: $($site.applicationPool)"
|
|
}
|
|
} else {
|
|
Write-Host "No websites configured in IIS" -ForegroundColor Yellow
|
|
}
|
|
} catch {
|
|
Write-Host "[WARN] WebAdministration module not available: $_" -ForegroundColor Yellow
|
|
}
|
|
|
|
# --- General Server Health ---
|
|
Write-Host "`n--- Server Health Summary ---" -ForegroundColor Yellow
|
|
|
|
$os = Get-CimInstance Win32_OperatingSystem
|
|
$uptime = (Get-Date) - $os.LastBootUpTime
|
|
Write-Host "Hostname: $env:COMPUTERNAME"
|
|
Write-Host "OS: $($os.Caption) $($os.Version)"
|
|
Write-Host "Last Boot: $($os.LastBootUpTime) (uptime: $($uptime.Days)d $($uptime.Hours)h $($uptime.Minutes)m)"
|
|
Write-Host "Timezone: $(Get-TimeZone | Select-Object -ExpandProperty DisplayName)"
|
|
|
|
# Memory
|
|
$totalMemGB = [math]::Round($os.TotalVisibleMemorySize / 1MB, 1)
|
|
$freeMemGB = [math]::Round($os.FreePhysicalMemory / 1MB, 1)
|
|
$usedMemGB = [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / 1MB, 1)
|
|
Write-Host "Memory: ${usedMemGB} GB used / ${totalMemGB} GB total (${freeMemGB} GB free)"
|
|
|
|
# Disk space
|
|
Write-Host "`nDisk Space:"
|
|
Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Used -gt 0 } | ForEach-Object {
|
|
$totalGB = [math]::Round(($_.Used + $_.Free) / 1GB, 1)
|
|
$usedGB = [math]::Round($_.Used / 1GB, 1)
|
|
$freeGB = [math]::Round($_.Free / 1GB, 1)
|
|
$pct = [math]::Round($_.Used / ($_.Used + $_.Free) * 100, 0)
|
|
Write-Host " $($_.Name): ${usedGB} GB / ${totalGB} GB (${freeGB} GB free, ${pct}% used)"
|
|
}
|
|
|
|
# --- DNS Forwarder Verification ---
|
|
Write-Host "`n--- DNS Forwarder Verification ---" -ForegroundColor Yellow
|
|
|
|
try {
|
|
$fwd = Get-DnsServerForwarder
|
|
Write-Host "DNS Forwarders:" -ForegroundColor Green
|
|
$fwd.IPAddress | ForEach-Object { Write-Host " $_" }
|
|
if ($fwd.IPAddress -contains "192.168.0.1") {
|
|
Write-Host " [OK] pfSense (192.168.0.1) is configured as forwarder" -ForegroundColor Green
|
|
} else {
|
|
Write-Host " [WARN] pfSense (192.168.0.1) is NOT a forwarder!" -ForegroundColor Red
|
|
}
|
|
} catch {
|
|
Write-Host "[WARN] Could not check DNS forwarders: $_" -ForegroundColor Yellow
|
|
}
|
|
|
|
Write-Host "`n=== Checks Complete ===" -ForegroundColor Cyan
|