Domain: SQL Database Engine · Risk: Changes state · Runs on: Windows, PowerShell 5.1 or 7 (module or MCP tool)
Putting a valid TLS certificate on a SQL Server is a six-step chore, and every step has a way to fail quietly. This command does all six in the correct order and reports, at each step, whether it worked.
The payoff: encrypting a SQL Server stops being a half-day ticket a senior DBA has to babysit and becomes one reviewable command that runs the same way on one server or fifty. It removes the two mistakes that cause outages — binding a certificate the SQL service account can’t actually read, and turning on “force encryption” before confirming clients can still connect.
Three things to know before you approve its use:
- It can use your existing certificate authority, or none at all. If you run AD Certificate Services, it requests and installs the cert for you. If you buy certs elsewhere, hand it the
.pfxand it does the rest. No new certificate vendor to sign off. - Nothing about your certificates or servers leaves your network. The whole process runs inside your perimeter. There is no call home.
- “Force encryption” is off unless you ask for it. That switch makes the server reject unencrypted connections — powerful, and occasionally an outage. The command never flips it silently.
What success looks like — one server, end to end, using your own CA:
Install-SqlConnectionCertificate -CommonName sql01.corp.com `
-CaConfig 'CA01\Corp Issuing CA' -CertificateTemplate WebServer `
-SqlInstance MSSQLSERVER -ServiceAccount 'NT SERVICE\MSSQLSERVER'Outcome — a certificate requested, issued, installed, permissioned, bound, and verified serving over TLS. One command, one audit line per step.
The bottom line for a budget owner: read-only checks in this toolkit are free and unlicensed. This command is one of the paid actions. What you buy is the removal of a recurring, error-prone manual task and the outages it causes.
The end-to-end orchestrator. It sequences the six atomic functions — New-SqlCertRequest → Submit-SqlCertRequest → Import-SqlCert → Add-SqlCertPrivateKeyAccess → Set-SqlCertBinding → Test-SqlCertBinding — threading the issued thumbprint forward so Grant and Bind operate on the exact cert. Every stage returns a SqlCert.Result; a Failed or Pending stage stops the chain. It never throws.
What you actually need to remember:
-Stageruns any subset. Default is all six. Skip Request/Submit when you already have a.pfx.- Pending is not failure. A CA that queues the request returns Pending — resume later with the same command and it picks up where it stopped.
- Remote nodes need
-Credential. Import/Grant/Bind/Verify run over WinRM; Kerberos pass-through covers domain-joined, a credential covers workgroup/cross-domain. -ForceEncryptionis a separate, deliberate switch. It rejects every unencrypted connection. Verify first.
Recipe 01 — Bring your own PFX (no CA in the path)
Install-SqlConnectionCertificate -Stage Import,Grant,Bind,Verify `
-PfxPath C:\certs\sql01.pfx -PfxPassword $pw `
-SqlInstance MSSQLSERVER -ServiceAccount 'NT SERVICE\MSSQLSERVER'Imports the pfx, grants the service account read on the private key, binds, and confirms it serves. Four results, four green stages.
Recipe 02 — A remote server in a workgroup
$cred = Get-Credential
Install-SqlConnectionCertificate -Node sql02 -Credential $cred `
-PfxPath \\share\sql02.pfx -PfxPassword $pw -Stage Import,Grant,Bind,Verify `
-SqlInstance MSSQLSERVER -ServiceAccount 'CORP\svc_sql'Every stage runs on sql02 over WinRM under the supplied credential.
Recipe 03 — Confirm only (did last month’s bind survive?)
Install-SqlConnectionCertificate -Stage Verify -SqlInstance MSSQLSERVERReads the binding from the registry and reports the bound thumbprint and expiry. No change made.
Recipe 04 — Turn on Force Encryption, deliberately
Install-SqlConnectionCertificate -Stage Bind,Verify -SqlInstance MSSQLSERVER -ForceEncryptionSets ForceEncryption=1 and confirms the bind. Restart the SQL service to apply; the instance then rejects unencrypted clients.
Recipe 05 — Resume a CA that queues requests for approval
# First call returns Pending on Submit; after the CA operator approves, re-run:
Install-SqlConnectionCertificate -CommonName sql01.corp.com `
-CaConfig 'CA01\Corp Issuing CA' -CertificateTemplate WebServer `
-SqlInstance MSSQLSERVER -ServiceAccount 'NT SERVICE\MSSQLSERVER'Pending stops the chain without error; the same command resumes from where it stopped.
Watchpoint — the bind needs a restart. Writing the thumbprint to SuperSocketNetLib is instant; SQL loads it on the next service start. Verify confirms the registry value; the encrypted connection is live after the restart.
Start here if certificates are new to you. A TLS certificate is how a SQL Server proves it is really itself and encrypts the traffic to it. Getting one onto a server takes six small steps, and this command walks all six.
| Step | What happens |
|---|---|
| Request | Make a certificate signing request — a file that says “please issue a cert for this server name.” |
| Submit | Hand that request to your certificate authority and get the issued certificate back. |
| Import | Install the certificate into the server’s certificate store. |
| Grant | Give the SQL Server service account permission to read the certificate’s private key. Skip this and SQL silently can’t use the cert. |
| Bind | Tell SQL Server “use this certificate” by writing its fingerprint into the right registry key. |
| Verify | Check the binding really took. |
The whole thing, one line, with your own CA:
Install-SqlConnectionCertificate -CommonName sql01.corp.com `
-CaConfig 'CA01\Corp Issuing CA' -CertificateTemplate WebServer `
-SqlInstance MSSQLSERVER -ServiceAccount 'NT SERVICE\MSSQLSERVER'You get six results back, one per step. Green all the way down means the server is encrypted.
The one that bites everyone is the Grant step. If the SQL service account can’t read the private key, SQL starts, ignores the cert, and connections stay unencrypted with no obvious error. This command never skips Grant.
| Question | Answer |
|---|---|
| Outbound network calls at run time? | None to the vendor. The command talks only to your own CA (if used) and the target SQL servers, inside your network. |
| What is installed? | A signed PowerShell module, or the same code as a .NET global tool: dotnet tool install --global DetentPoint.SqlCertForge.Mcp. |
| Runtime | Windows, with Windows PowerShell 5.1 or PowerShell 7 — either is sufficient. |
| Privileges needed | Local admin on the target SQL host (writes to the machine cert store and HKLM). For remote targets, WinRM access under a credential you supply. |
| Certificate authority | Optional. Uses AD Certificate Services if you have it; otherwise you supply a .pfx from any source. |
| Data handled | Certificates and their private keys, on your own servers. Nothing about them is transmitted anywhere. |
| Licence | Read-only audit commands are free. State-changing commands (this one) are licensed; the licence is verified offline against a signature — no activation call. |
The one line that matters for a security review: nothing leaves your network. The licence check is an offline signature verification, not a call home.
| Dependency | Why | Required? |
|---|---|---|
| Windows + PowerShell 5.1 or 7 | Reads the machine cert store, writes the SQL registry binding. | Yes |
| Local administrator on the SQL host | The cert store and SuperSocketNetLib live under HKLM. |
Yes |
| The SQL Server service account name | Passed to Grant so that account can read the private key. | Yes (for Grant/Bind) |
| AD Certificate Services CA | Only for the Request/Submit stages. Skip both with a supplied .pfx. |
No |
| WinRM to the target | Only when acting on a remote -Node. Local runs don’t need it. |
No (local) |
| A SQL service restart | The bound cert loads on the next start. Yours to schedule. | To go live |
No hidden dependencies: no agent, no service, no database of its own, no internet. If the six things above are in place, it runs.
Controls built in:
- Least privilege on the private key. Grant gives the SQL service account Read only — not full control — on the key file.
- Broad principals are refused. Granting key access to Everyone, Authenticated Users, BUILTIN, BUILTIN, or Anonymous is blocked unless
-AllowBroadPrincipalis explicitly passed. The refusal is the default. - Force Encryption is opt-in. The switch that rejects unencrypted connections is never set implicitly.
- Every stage is evidence. Each step returns a structured
SqlCert.Result— stage, status, detail, thumbprint, resolved SID — suitable for an audit log.
A real result an auditor can keep (from a live run):
Grant Success Granted Read to SQLSPNLAB\svc_sql_ao on: CLVLAB-NODE1
Bind Success Bound BD7B1179…9582C to: AOAG on CLVLAB-NODE1
The certificate [Cert Hash(sha1) "BD7B1179…9582C"] was
successfully loaded for encryption.
The thumbprint, the account, and the target are on the record. The SID the account resolved to is captured for the grant.
What to check in an audit:
- The private-key ACL grants Read to the SQL service account SID and nothing broader.
- The bound thumbprint matches an in-policy, unexpired certificate.
- Where required, Force Encryption is on and clients still connect (no silent downgrade).