sqmSQLTool · Security & Compliance · 2026

Security & Compliance

Audit-ready in one hour.

Login audit, sysadmin accounts, SA hardening, TLS status, AD reconciliation — every security check in one module. Documented, reproducible, automatable.

Login auditTLS / certificatesSA hardeningAD reconciliationPolicy

Uwe Janke · Senior SQL Server DBA · dtcSoftware

🔒 Login Audit — SQL01\PROD — 2026-05-28
Critical findings
SA accountActive • default name • sysadmin
sql_backup_userSQL auth • sysadmin • last login: never
DOMAIN\jschmidtAD account disabled • SQL login still active
TLS status
TLS 1.0Enabled • disabling recommended
TLS 1.2Enabled • OK
SQL certificateSelf-signed • expires in: 90 days

Motivation

Security gaps nobody sees

💀

SA account: active & well-known

The SA account is always named "sa", always has sysadmin rights, and is still active on many systems. An attacker only has to guess the password — or it was never changed.

👻

Orphaned SQL logins

Employees leave the company, their AD account is disabled — but the SQL login stays active. Without regular reconciliation, ghost accounts pile up.

🔒

TLS 1.0 still active

TLS 1.0 and 1.1 are classified as insecure (RFC 8996). Still active on many systems because turning it off is complex and automation is missing.

📋

Auditing without a tool = hours of work

Sysadmin accounts, certificate expiry dates, TLS configuration, SQL-auth logins — every audit question means manual research, server by server.

✓ sqmSQLTool checks every security parameter automatically — structured reports, reproducible, documented for audits.

Overview

Four security categories. One module.

🔑

Access rights

Login audit, sysadmin accounts, SA hardening, AD reconciliation.

🔐

Network & TLS

TLS protocol versions, encryption status, certificate assignment.

📜

Certificate management

Create, import, and request certificates — the full lifecycle.

🛡

Hardening & policy

SQL Server policy management, password rotation, SA obfuscation.

10
security functions
Login, TLS, certs, policy, AD reconciliation
1h
to a full audit report
Set up once — automatic after that
n
instances in parallel
Pipeline — the whole estate at once

Access rights

Invoke-sqmLoginAudit

A full login audit: every login, roles, last login, SQL auth vs. Windows auth, status.

What gets checked

👤 Every loginName, type (SQL / Windows / group), status
🛡 Server rolesSysadmin, SecurityAdmin, ServerAdmin, etc.
📅 Last loginWhen did this login last connect?
⚠ SQL authEvery SQL login flagged — less secure than Windows auth
❌ DisabledLogins that are disabled but still exist
💻 Database accessWhich databases the login can access
⚠ SQL-auth logins with the sysadmin role and long inactivity are the most common audit finding.
# Full login audit
Invoke-sqmLoginAudit `
    -SqlInstance "SQL01"

# Only SQL-auth logins with sysadmin
Invoke-sqmLoginAudit `
    -SqlInstance "SQL01" `
    -Filter SqlAuthSysadmin

# Inactive for more than 90 days
Invoke-sqmLoginAudit `
    -SqlInstance "SQL01" `
    -InactiveDays 90

# Every instance, CSV for the audit
Get-Content "instances.txt" |
    Invoke-sqmLoginAudit |
    Export-Csv "login_audit.csv" `
        -NoTypeInformation

Sysadmin control

Get-sqmSysadminAccounts

Every account with the sysadmin role — Windows groups are expanded, so every indirect member becomes visible.

The problem with groups

A Windows group as sysadmin looks tidy — but who's actually a member of that group? Get-sqmSysadminAccounts expands every group and lists each individual user.

🛡 Sysadmin Accounts — SQL01
Direct sysadmin logins (3)
saSQL auth • ACTIVE
DOMAIN\sql_svcService account • OK
DOMAIN\DBA_TeamGroup • 8 members
Indirect members via DBA_Team
DOMAIN\u.jankeactive
DOMAIN\m.muellerAD account disabled!
# Every sysadmin account, groups included
Get-sqmSysadminAccounts `
    -SqlInstance "SQL01"

# With AD group expansion
Get-sqmSysadminAccounts `
    -SqlInstance "SQL01" `
    -ExpandGroups

# Only unexpected accounts
Get-sqmSysadminAccounts `
    -SqlInstance "SQL01" |
    Where-Object {
        $_.Name -notmatch "^sa$|svc_|sql_"
    }

# Every instance, as CSV
Get-Content "instances.txt" |
    Get-sqmSysadminAccounts `
        -ExpandGroups |
    Export-Csv "sysadmins.csv" `
        -NoTypeInformation
⚠ Every unrecognized sysadmin account is a critical risk. Escalate any deviation from the expected list immediately.

SA hardening

Invoke-sqmSaObfuscation & New-sqmRandomSaPassword

Invoke-sqmSaObfuscation

Harden the SA account: rename it, disable it, or both — across every instance in one operation.

# Rename SA + disable it
Invoke-sqmSaObfuscation `
    -SqlInstance "SQL01" `
    -NewName "disabled_sa" `
    -Disable

# Every instance
Get-Content "instances.txt" |
    Invoke-sqmSaObfuscation `
        -NewName "sa_disabled" `
        -Disable
⚠ Prerequisite: at least one other active sysadmin login must already exist.

New-sqmRandomSaPassword

Sets a cryptographically random password for SA — worth doing as brute-force protection even when SA is disabled.

# Set a random password
New-sqmRandomSaPassword `
    -SqlInstance "SQL01"

# Store the password in a vault
New-sqmRandomSaPassword `
    -SqlInstance "SQL01" `
    -SaveToVault `
    -VaultPath "\\share\SecureVault"

# Every instance
Get-Content "instances.txt" |
    New-sqmRandomSaPassword `
        -SaveToVault
✓ Best practice: rename + disable + random password. All three measures together, in one maintenance window.

AD reconciliation

Get-sqmADAccountStatus

Checks the current AD status for every Windows login — disabled, locked, or expired accounts that are still active as a SQL login.

What gets checked

DisabledAD account disabled, SQL login still active
LockedAccount locked out in AD, but SQL access still possible
ExpiredPassword or account expired per AD
Not foundAccount no longer exists in AD
ActiveAD account is fine
⚠ Orphaned SQL logins (AD account deleted, SQL login still active) are a forgotten way in. Especially critical for former employees with elevated rights.
# AD status for every Windows login
Get-sqmADAccountStatus `
    -SqlInstance "SQL01"

# Only problem accounts
Get-sqmADAccountStatus `
    -SqlInstance "SQL01" `
    -ShowProblemsOnly

# Every instance, CSV export
Get-Content "instances.txt" |
    Get-sqmADAccountStatus `
        -ShowProblemsOnly |
    Export-Csv "orphaned_logins.csv" `
        -NoTypeInformation

# Remove disabled ones directly (WhatIf!)
Get-sqmADAccountStatus `
    -SqlInstance "SQL01" `
    -RemoveDisabled -WhatIf

Network security

Get-sqmTlsStatus

TLS protocol versions and encryption status across every SQL Server instance — which systems can still fall back to TLS 1.0 / 1.1?

What gets checked

TLS version1.0 (insecure), 1.1 (outdated), 1.2 (ok), 1.3 (optimal)
SQL encryptionIs ForceEncryption enabled?
CertificateSelf-signed vs. CA-signed, expiry date
Cipher suitesAny weak encryption algorithms enabled?
🔐 TLS Status — All Instances
SQL01\PRODTLS 1.2 • Force Enc. ON • CA cert
SQL02\PRODTLS 1.2 • Force Enc. ON • CA cert
SQL03\TESTTLS 1.0 active • Force Enc. OFF
SQL04\DEVTLS 1.2 • self-signed • 90d to expiry
# TLS status for one instance
Get-sqmTlsStatus `
    -ComputerName "SQL01"

# Every server, problems only
Get-Content "servers.txt" |
    Get-sqmTlsStatus `
        -ShowProblemsOnly

# CSV for the compliance report
Get-Content "servers.txt" |
    Get-sqmTlsStatus |
    Export-Csv "tls_compliance.csv" `
        -NoTypeInformation
⚠ TLS 1.0 and 1.1 are classified as deprecated (RFC 8996). In regulated environments (PCI-DSS, ISO 27001), TLS 1.0 is an audit finding.

Certificate management

Set-sqmSqlTlsCertificate & New-sqmSqlCertificate

Set-sqmSqlTlsCertificate

Assigns a certificate to a SQL Server service (registry entry + optional service restart).

# Assign a certificate (by thumbprint)
Set-sqmSqlTlsCertificate `
    -ComputerName "SQL01" `
    -Thumbprint "A1B2C3D4..." `
    -RestartService

# Remove the certificate
Set-sqmSqlTlsCertificate `
    -ComputerName "SQL01" `
    -RemoveCertificate
ℹ For production: a CA-signed certificate via New-sqmCertificateRequest — self-signed for dev/test only.

New-sqmSqlCertificate

Creates a self-signed certificate directly for SQL Server — correct EKU (Server Authentication), in the right store.

# Create a self-signed cert
New-sqmSqlCertificate `
    -ComputerName "SQL01" `
    -ValidYears 3

# Create + assign immediately
New-sqmSqlCertificate `
    -ComputerName "SQL01" `
    -ValidYears 3 `
    -AssignToSqlService `
    -RestartService

Certificate lifecycle

New-sqmCertificateRequest & Install-sqmCertificate

The full certificate lifecycle: create a CSR, get it signed, import it, assign it.

Lifecycle steps

1
Create the CSR

New-sqmCertificateRequest — generates a .req file with the correct SAN (FQDN, NetBIOS, cluster VNN).

2
Submit to the CA

Send the CSR to an internal or external CA — get a signed certificate back as .cer or .pfx.

3
Import it

Install-sqmCertificate — imports it into the correct store, sets permissions for the SQL Server service account.

4
Assign it

Set-sqmSqlTlsCertificate — assign the certificate to the SQL Server service + restart.

# Step 1: create the CSR
New-sqmCertificateRequest `
    -ComputerName "SQL01" `
    -OutputPath "\\share\Certs" `
    -AdditionalSAN "sql01-vnn","sql01.corp.local"

# Step 3: import the signed cert
Install-sqmCertificate `
    -ComputerName "SQL01" `
    -CertFile "\\share\Certs\SQL01.cer" `
    -SetPermissions

# Step 4: assign + restart
Set-sqmSqlTlsCertificate `
    -ComputerName "SQL01" `
    -CertFile "\\share\Certs\SQL01.cer" `
    -RestartService
✓ SANs are filled in automatically with the FQDN, short name, and cluster VNN — no manually assembling the CSR.

Reference

Quick reference

TaskFunctionOutput
Login auditInvoke-sqmLoginAuditConsole + CSV
Sysadmin accountsGet-sqmSysadminAccountsConsole + CSV
Rename/lock SAInvoke-sqmSaObfuscationConsole
SA random passwordNew-sqmRandomSaPasswordConsole
AD account reconciliationGet-sqmADAccountStatusConsole + CSV
TLS statusGet-sqmTlsStatusConsole + CSV
Assign TLS certificateSet-sqmSqlTlsCertificateConsole
Self-signed certNew-sqmSqlCertificateCertificate
Create a CSRNew-sqmCertificateRequest.req file
Import a certificateInstall-sqmCertificateConsole

Recommended audit routine (monthly)

1
Login audit

Every instance, export to CSV, compare against last month

2
Sysadmin accounts

Escalate any new sysadmin immediately

3
AD reconciliation

Remove disabled accounts that still have a SQL login

4
TLS + certificates

Renew expiring certificates (90-day warning) ahead of time

ℹ All four steps can be scheduled as a SQL Agent job — the report lands in CentralPath automatically.
sqmSQLTool - Inventory & DocumentationsqmSQLTool - Certificate Expiry ReportsqmSQLTool - SPN AuditAlwaysOnSetup - AG Certificates

Summary

What your team gains

📋 For the auditor

Evidence in minutes

Login audit CSV, sysadmin report, TLS status — every piece of audit evidence produced in one run.

Reproducible

Monthly runs always come back in the same format — compare against the prior period at the push of a button.

Complete

No instance gets forgotten — the pipeline processes every server from a list.

🛡 For the DBA

SA locked down for good

Rename + disable + random password, in one maintenance window, across every system.

TLS 1.0 is history

Status of every system at a glance — targeted shutdown without manual registry digging.

Certificate expiry stops being stressful

Automatic warning 90 days ahead — never an expired SQL certificate in production again.

10
security functions
Login, TLS, certs, SA, AD, policy
1h
for a full audit
Every piece of evidence in one run
n
instances in parallel
Pipeline — no server gets forgotten