googleapis / googleapis/mcp-toolbox
MSSQL source: support Microsoft Entra ID (managed identity) for the database connection
- Dominant language
- Go
- Stars
- 16.4k
- Forks
- 1.7k
- Avg merge
- 4d 9h
- Merged PRs (30d)
- 85
Description
### Prerequisites
- [x] Search the [current open issues](https://github.com/googleapis/mcp-toolbox/issues)
### What are you trying to do that currently feels hard or impossible?
I want to point the mssql source at an Azure SQL Database that has SQL authentication turned off and only accepts Microsoft Entra ID (formerly Azure AD) identities. This is a common hardening baseline in regulated Azure estates: the logical server is set to Entra-only auth, so there are no SQL logins or passwords to hand out. Today the mssql source can't connect in that setup. The config requires user and password.
The specific deployment I'm targeting: MCP Toolbox running as a pod on AKS, using Workload Identity federated to a user-assigned managed identity, connecting to Azure SQL over a private endpoint. Every other service in that cluster already reaches SQL this way with no secret in the connection string. I'd like Toolbox to do the same rather than being the one component that forces SQL auth back on (a non-starter for us).
### Suggested Solution(s)
I believe that the driver MCP Toolbox already depends on supports this (go-mssqldb). It ships an azuread subpackage that registers a separate driver name and handles Entra token acquisition through fedauth modes: ActiveDirectoryDefault, ActiveDirectoryManagedIdentity, ActiveDirectoryServicePrincipal, and others. ActiveDirectoryDefault resolves a workload-identity token via DefaultAzureCredential, which is exactly the AKS case above.
The gap is that Toolbox doesn't wire it up as an option. `internal/sources/mssql/mssql.go` imports only the base driver "github.com/microsoft/go-mssqldb" and never the /azuread subpackage, so the fedauth modes aren't reachable. The config struct also makes user and password mandatory.
One way to do it is by adding an optional auth mode to the source config, defaulting to the current password behavior so nothing breaks. For example:
```yaml
kind: source
name: my-azure-sql
type: mssql
host: my-server.database.windows.net
port: "1433"
database: my_db
# Connection encryption, independent of the auth mode below.
encrypt: "true" # one of: disable | false | true | strict
trustServerCertificate: true # skip cert chain validation; ignored when encrypt is 'strict'
# New: Entra ID connection auth. Omit the whole block to keep today's SQL auth.
azureAuth:
mode: workload-identity # or: default | managed-identity | service-principal
clientId: "" # optional for 'default'; used as DSN 'user id'
tenantId: "" # optional; needed in some isolated setups
disableInstanceDiscovery: true # for network-isolated segments with no route to the AAD authority discovery endpoint
```
- The modes map onto azidentity credentials in the azuread package:
- ActiveDirectoryDefault uses DefaultAzureCredential (reads the identity from the pod environment)
- ActiveDirectoryWorkloadIdentity uses WorkloadIdentityCredential directly
- ActiveDirectoryManagedIdentity uses ManagedIdentityCredential
- ActiveDirectoryServicePrincipal covers the client-secret or client-assertion case.
- A clientId field matters for user-assigned managed identity so DefaultAzureCredential doesn't have to guess when a pod maps to more than one identity. In DSN terms it becomes the user id parameter.
- disableInstanceDiscovery and additionallyAllowedTenants are already supported by the azuread package and are needed for network-isolated or sovereign-cloud deployments where the pod can't reach the public AAD authority discovery endpoint. Without a way to set them, those environments can't authenticate even when everything else is correct.
- encrypt and trustServerCertificate should both be plain toggles. The current source only exposes encrypt and never sets trustservercertificate, so there's no way today to encrypt the connection while skipping cert validation. That combination (encrypt: true with trustServerCertificate: true) is common for Azure SQL reached over a private endpoint. Note the driver forces validation on when encrypt is strict, so strict and trusting an unverified cert are mutually exclusive.
When an Entra mode is set, open the connection through the azuread driver with the matching fedauth value instead of the base driver, and stop requiring user/password.
There's precedent for passwordless database auth in the project already: the Cloud SQL sources support IAM auth (for example #2050 added it to the Cloud SQL MySQL source via auto_iam_authn). This request is the Azure equivalent for the mssql source.
### Alternatives Considered
- SQL authentication with the password stored in a secret. This works when the server allows SQL logins, but it's a non-starter when the server is Entra-only, and it reintroduces a credential to manage and rotate.
- A sidecar or proxy that terminates auth and forwards a local connection. That adds a moving part per source and still needs its own Entra token handling, so it mostly relocates the problem.
- Forking to add the azuread path locally. Doable, but I'd rather this live upstream so Azure users aren't each maintaining a patch.
### Additional Details
- Relevant file: internal/sources/mssql/mssql.go (base-driver import, the user/password required fields, and the DSN builder that only sets encrypt).
- Driver reference: the azuread package in github.com/microsoft/go-mssqldb. It registers the azuresql driver name and reads a fedauth DSN parameter to pick the credential. The same package parses disableinstancediscovery and additionallyallowedtenants.
- Encryption params live in msdsn: encrypt accepts disable/false/true/strict, and trustservercertificate is a bool that the driver ignores under strict.
- azidentity would need adding as a direct dependency; azcore is already pulled in indirectly.
- Related but distinct: #482 asks for Entra as an authService for OAuth on tool invocation (client to Toolbox). This request is about the database connection itself (Toolbox to Azure SQL). The two don't overlap, and my org would want both eventually.
I'm happy to work on a PR if the maintainers are open to this approach and can weigh in on where the auth-mode switch should live in the source config. I'm not a go developer and would use AI to help build and test it, though. Not sure this project's opinions on that but I want to honor whatever they are. Thanks for building this awesome tool, I hope I can use it!
Contributor guide
Assessment
This issue has not been assessed yet.