microsoft / microsoft/aspire

Azure SQL: contained user for managed identity is created from the principal (object) id, but SQL matches on client id

Open
#19,390 2 comments 0 reactions 0 assignees View on GitHub
area-deployment area-integrations triage:bot-seen
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 15h
Merged PRs (30d)
196

Description

## Summary

The generated `api-roles-` module creates the contained SQL user from the managed identity's **principal (object) id**. Azure SQL matches managed identities on their **client (application) id**, so the resulting user does not match the token and the application fails to log in.

## Details

`api-identity.module.bicep` exposes both:

```bicep
output clientId string = api_identity.properties.clientId
output principalId string = api_identity.properties.principalId
```

and `main.bicep` passes the principal id to the roles module:

```bicep
module api_roles_control_sql 'api-roles-control-sql/api-roles-control-sql.module.bicep' = {
params: {
principalId: api_identity.outputs.principalId
principalName: api_identity.outputs.principalName
}
}
```

The script converts that GUID to a SID:

```sql
DECLARE @id UNIQUEIDENTIFIER = '$principalId';
DECLARE @castId NVARCHAR(MAX) = CONVERT(VARCHAR(MAX), CONVERT (VARBINARY(16), @id), 1);
DECLARE @cmd NVARCHAR(MAX) = N'CREATE USER [' + @name + '] WITH SID = ' + @castId + ', TYPE = E;'
```

## Observed behaviour

I hit #19389 first, so I created the contained user by hand using the same statement and the same `principalId`. The application then failed with:

```
Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user ''.
```

Recreating the user with `CREATE USER [] FROM EXTERNAL PROVIDER`, which lets SQL resolve the SID from Entra, produced a **different** SID — the little-endian encoding of the identity's **client id**, not its object id. With that user in place the application connects successfully.

Concretely, for a user-assigned identity with:
- `clientId` = `c5055d7d-d66d-468d-8984-077214496243`
- `principalId` = `ad966088-94ed-440e-87c7-ecd56daac796`

`FROM EXTERNAL PROVIDER` yields SID `0x7D5D05C56DD68D468984077214496243`, which is the client id. The script's `principalId`-derived SID does not match what the token presents.

## Impact

Once #19389 is fixed, the script will run to completion but still create a user that cannot authenticate, so this is likely masked by that bug today.

## Suggested fix

Pass `api_identity.outputs.clientId` to the roles module for the SID, or use `CREATE USER [name] FROM EXTERNAL PROVIDER` and let SQL resolve the identity by name.

## Environment

- Aspire 13.4.6 (same script emitted by 13.3.5), azd 1.25.0, .NET 10.0.300
- Azure SQL serverless `GP_S_Gen5`, Entra-only authentication, user-assigned managed identity on Azure App Service Linux

Contributor guide

Open the contributing guide

Research direction

Start by tracing the identity outputs in api-identity.module.bicep through the parameters in main.bicep into api-roles-control-sql/api-roles-control-sql.module.bicep and its generated SQL. Verify that the contained user SID corresponds to the managed identity client ID and that the deployed application can authenticate successfully with the resulting user.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, sql
Domain
cloud, databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.