Status: Reviewed (deep-dive v1)
Stack: PowerShell (AD group membership) → SQL permission snapshots/procs → Blazor Server UI
Depends on: SQL-01 Inventory (instance population)
Goal: See who has powerful access, catch drift (new sysadmins, orphans, risky surface), and keep fixes change-controlled.
You can inventory, back up, maintain indexes, and watch Agent — and still get burned by sprawling sysadmin, orphaned users, or guest/xp_cmdshell leftovers. Hygiene is continuous, not a one-time audit.
sysadmin / Control Server / high DB roles are listed and justifiedxp_cmdshell, guest enabled in user DBs, unpatched/old TLS notes (high level), TRUSTWORTHY on user DBs| Finding | Severity | Notes |
|---|---|---|
New/unexpected sysadmin (Windows or SQL) |
Red | Diff vs last snapshot |
| Orphaned users in user DBs | Yellow/Red | Higher if dbo/owner |
xp_cmdshell enabled |
Red | Unless documented exception |
| Guest enabled in user DB | Yellow/Red | Especially prod |
| SQL logins with blank/weak policy flags | Red | is_policy_checked / expired |
Excessive db_owner on prod app logins |
Yellow | Prefer least privilege |
| TRUSTWORTHY ON (user DB) | Yellow | Review ownership chaining risk |
| Public/guest granted extras | Yellow | Unusual grants |
Scope = inventoried instances.
T-SQL (read-only security DMVs/catalog):
sysadmin and other server rolesdb_owner, db_securityadmin, …), orphaned users (sid mismatch)xp_cmdshell, show advanced options not required in report — just the risk flagsis_trustworthy_on, membership of guestPowerShell / AD:
Emit CollectedAt + instance key. Never collect password hashes for display.
| Table | Purpose |
|---|---|
dbo.SqlLogin |
Server principals snapshot (latest) |
dbo.SqlLoginHistory |
Prior snapshots for sysadmin drift |
dbo.SqlDbUser |
DB users + roles summary |
dbo.SqlSecurityFinding |
Computed findings (type, severity, object, first/last seen) |
dbo.SqlSecurityException |
Approved exceptions (who/when/why/expiry) |
dbo.AdGroupMember |
Expanded Windows group members |
Procs:
usp_SqlSecurity_ApplySnapshot — upsert principals/users; generate findings; clear fixed onesusp_SqlSecurity_GetExceptionsBoard — Blazor main grid (open findings minus approved)usp_SqlSecurity_GetLoginDetail — roles + AD expansionusp_SqlSecurity_GetSysadminDiff — added/removed since last collectsp_change_users_login / ALTER USER … WITH LOGIN) or drop if unused SqlSecurityException with expiry| Layer | Prefer |
|---|---|
| PowerShell collectors | Dedicated account; local admin only if required for service discovery; SQL login with least read + write to inventory DB only |
| SQL upsert procs | Writer login ≠ Blazor login |
| Blazor app pool | EXECUTE on read procs only; no sysadmin; no Agent start/stop |
| Humans | Windows groups → server roles; avoid personal SQL logins in prod |
| Symptom | Likely cause |
|---|---|
| Sysadmin churn every collect | Deploy scripts adding service accounts |
| Orphans after restore/migrate | SID mismatch across domains/instances |
| Findings flap open/closed | Exception not recorded; intermittent sync |
| AD expand empty | Group scope / trust / collector rights |
VIEW ANY DEFINITION / VIEW SERVER STATE / ability to read role membership — prefer custom role over sysadmin for the collector | # | Topic | Doc |
|---|---|---|
| 01 | Inventory & configuration baseline | SQL-01-Inventory-Baseline.md |
| 02 | Backup & restore readiness | SQL-02-Backup-Restore-Readiness.md |
| 03 | Index & statistics maintenance | SQL-03-Index-Statistics-Maintenance.md |
| 04 | SQL Agent jobs & schedules | SQL-04-SQL-Agent-Jobs-Schedules.md |
| 05 | Security & access hygiene | SQL-05-Security-Access-Hygiene.md |
Beyond the seed (when Rick directs): capacity/growth, performance health, patching, HA/DR, alerting/runbooks (see outline).
SQL Dude — SQL-05 Security & Access Hygiene v1