Skip to content

Lite: non-interactive Azure auth (service principal + managed identity) — #1038#1042

Merged
erikdarlingdata merged 2 commits into
devfrom
feature/1038-lite-azure-auth
Jun 1, 2026
Merged

Lite: non-interactive Azure auth (service principal + managed identity) — #1038#1042
erikdarlingdata merged 2 commits into
devfrom
feature/1038-lite-azure-auth

Conversation

@erikdarlingdata
Copy link
Copy Markdown
Owner

What shipped (Phase A of #1038)

Two non-interactive Azure SQL auth modes for Lite, so a fleet of Azure SQL instances can authenticate with no per-server interactive prompt:

  • Service PrincipalAuthentication=ActiveDirectoryServicePrincipal, client id + client secret.
  • Managed IdentityAuthentication=ActiveDirectoryManagedIdentity, system-assigned (no id) or user-assigned (client id).

Both ride the same AAD provider infrastructure that already powers EntraMFA, selected via the Authentication= keyword. Per-server (credential profiles are deferred Phase B).

Changes

  • AuthenticationTypes: ServicePrincipal / ManagedIdentity constants (additive, backward compatible).
  • ServerConnection: non-secret model fields AzureClientId / AzureTenantId (stored-but-unused; MDS resolves tenant from the server authority) / ManagedIdentityClientId; SP + MI connection-string arms; GetConnectionString fetches the SP secret (MI fetches nothing); HasStoredCredentials (MI = true, SP = Credential-Manager check); AuthenticationDisplay arms (was a silent _ => "Windows"). Auth-keyword logic extracted into a shared ApplyAuthentication helper.
  • ServerManager: save SP secret on Add/Update; explicit orphan-secret delete when switching SP→MI / SP→Windows; DeleteServer already clears it.
  • AddServerDialog (XAML + code-behind): SP + MI radios and panels (shared Grid.Row=7 visibility toggle); MI panel carries the workstation-vs-Azure note; edit-load pre-fills the SP client id + secret from Credential Manager (mirrors the SQL-password pre-fill); persists the new fields; Test-Connection builder routed through the shared helper.

Two-build-site handling

The dialog's BuildConnectionBuilder (Test Connection) and ServerConnection.BuildConnectionString (production) are the two auth-deciding build sites. Rather than maintain two parallel arm-sets, both now call the shared ServerConnection.ApplyAuthentication. A parity test asserts they emit identical Authentication/UserID/Password/IntegratedSecurity for every auth mode.

Security

  • The SP secret lives only in Windows Credential Manager (DPAPI) via the existing per-server-GUID CredentialService. It is never a serialized model property (not in servers.json) and never logged (no connection-string-on-error path).
  • MI stores nothing.

Dependency note

No new NuGet. SP/MI use the AAD providers in the already-referenced Microsoft.Data.SqlClient.Extensions.Azure 1.0.0 (transitively MSAL + Azure.Identity). That reference is load-bearing — if it is dropped/bumped, SP + MI + EntraMFA break together.

Build + test (real results)

dotnet build Lite/PerformanceMonitorLite.csproj -c Debug
Build succeeded. 0 Warning(s) 0 Error(s)

dotnet test Lite.Tests
Passed! - Failed: 0, Passed: 334, Skipped: 0, Total: 334  (22 new Azure-auth tests)

New tests: SP shape (ActiveDirectoryServicePrincipal, UserID=clientId, Password=secret, IntegratedSecurity=false, Encrypt honored); MI system- and user-assigned; GetConnectionString SP-secret fetch / MI no-fetch; HasStoredCredentials (MI true, SP cred-manager); AuthenticationDisplay; two-build-site parity; Windows/SqlServer/EntraMFA regression.

Maintainer Azure E2E checklist (plan §9 — cannot be unit-tested without a tenant)

  • Real Azure SQL DB + service principal granted access → add SP server in Lite → Test → connects non-interactively; collection runs.
  • (If available) Azure-VM-hosted Lite with a managed identity → MI server connects with no secret.
  • A fleet of several SP servers connects in parallel (proves the MFA serialization lock excludes SP/MI) — no serialization, no interactive prompt.
  • Secret rotation via Edit Server reconnects.

🤖 Generated with Claude Code

erikdarlingdata and others added 2 commits June 1, 2026 19:12
…y) — #1038

Adds two non-interactive Azure SQL auth modes to Lite so a fleet of Azure SQL
instances can authenticate without per-server interactive prompts:

- ServicePrincipal: ActiveDirectoryServicePrincipal (client id + secret)
- ManagedIdentity: ActiveDirectoryManagedIdentity (system- or user-assigned)

Changes:
- AuthenticationTypes: add ServicePrincipal / ManagedIdentity constants.
- ServerConnection: AzureClientId / AzureTenantId / ManagedIdentityClientId
  (non-secret) model fields; SP + MI connection-string arms; GetConnectionString
  fetches the SP secret (none for MI); HasStoredCredentials (MI=true, SP=cred
  manager); AuthenticationDisplay arms. Auth keyword logic extracted into a shared
  ApplyAuthentication helper so the two build sites can't diverge.
- ServerManager: save SP secret on Add/Update; explicit orphan-secret delete on
  switch to MI/Windows; DeleteServer already clears it.
- AddServerDialog: SP + MI radios/panels (shared Grid.Row=7 toggle), edit-load
  pre-fill of SP client id + secret from Credential Manager, persist new fields,
  Test-Connection builder routed through the shared helper.

Security: the SP secret lives ONLY in Windows Credential Manager (DPAPI) via the
existing per-server-GUID CredentialService. It is never a serialized model
property (not in servers.json) and never logged.

Dependency note: SP/MI ride the AAD providers in the already-referenced
Microsoft.Data.SqlClient.Extensions.Azure 1.0.0 (same infra as EntraMFA). No new
NuGet added; that reference is load-bearing for SP + MI + EntraMFA.

Tests: connection-string shape for SP/MI (incl. system- vs user-assigned),
GetConnectionString secret fetch, HasStoredCredentials, AuthenticationDisplay,
two-build-site auth parity, and regression for Windows/SqlServer/EntraMFA.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… with a blank username (LOW-1)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@erikdarlingdata erikdarlingdata merged commit cfe6ca1 into dev Jun 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant