Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Documentation corrections remain for token caching, resource-specific credentials, configuration validation, role assignment, and provider-specific deployment behavior.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Documents the generalized Csag.WorkloadIdentity library for Azure SQL, Blob Storage, managed identities, and Google federation.
Changes:
- Adds package quickstarts, options reference, and migration guidance.
- Restructures cloud identity setup documentation.
- Updates root and security documentation.
- Adds a patch changeset.
File summaries
| File | Description |
|---|---|
SECURITY.md |
Updates supported credential and resource descriptions. |
README.md |
Refreshes project overview and quick-start guidance. |
docs/cloud-identity-setup.md |
Adds identity, resource grant, configuration, and deployment instructions. |
Csag.WorkloadIdentity/README.md |
Adds quickstarts, API/options reference, and migration guidance. |
.changeset/workload-identity-docs.md |
Records the documentation patch release. |
Review details
Suppressed comments (2)
Csag.WorkloadIdentity/README.md:224
- The Azure SDK does not request a token from
TokenCredentialon every request; its bearer-token policy caches the returnedAccessTokenuntil it needs renewal. Please avoid implying a per-request credential call, since the adapter/provider refresh behavior and request latency are described incorrectly here.
Azure SQL works exactly as in quickstart A: `IAzureSqlTokenProvider` and `SqlConnection.AccessToken`, with plain ADO.NET or the EF Core factory. For Blob Storage inject the `BlobServiceClient`; the SDK asks the credential for a token on every request and the adapter answers from the held token:
docs/cloud-identity-setup.md:237
- This role-assignment procedure does not cover the user-assigned managed identity used as the federated-credential holder in section B.2.2. Such an identity must be selected under Managed identity (using its principal), not only via the app-registration/service-principal path described here; otherwise the documented Google-federation Blob setup cannot grant the required data role.
1. In the Azure portal open the storage account (or the container) and go to **Access control (IAM)** > **Add** > **Add role assignment**.
2. Select the role. On the **Members** tab choose **Managed identity** and pick the identity (a system-assigned identity is listed under its resource type, for example App Service), or choose **User, group, or service principal** and search for the app registration by name.
- Files reviewed: 5/5 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
6c2786d to
0f2a88d
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Address the critical SQL cleanup guidance and the two moderate documentation inaccuracies.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (2)
Csag.WorkloadIdentity/README.md:297
AddWorkloadIdentityis not harmless when called more than once:RegisterWorkloadIdentityServicesusesAddHostedService<TokenRefreshService>()(not aTryAdd), so each call registers another hosted refresh loop and can duplicate token requests. Please remove this claim or document the single-registration requirement until the registration code is made idempotent.
The options are validated when the host starts: no resource section at all, a missing value in a configured resource's provider section, or a non-positive `RefreshAheadWindow` throws an `OptionsValidationException` that names every offending value by its path, for example `AzureSql:Google:ServiceAccountEmail must be provided.` A `Provider` value other than `ManagedIdentity` or `Google` fails earlier, when the configuration is bound. Calling `AddWorkloadIdentity` more than once is harmless. Both token providers are always registered; resolving the provider of a resource whose section is absent throws an `InvalidOperationException` that names the missing section.
docs/cloud-identity-setup.md:290
- This migration instruction produces the wrong JSON shape if followed literally: the existing resource must still contain a
ManagedIdentityproperty, withClientIdinside it. As written, replacing the section with{ "ClientId": ... }leavesAzureSql.ManagedIdentityabsent and fails options validation. Clarify that the contents of theManagedIdentityobject are replaced, or show the full resource snippet.
For a user-assigned identity replace the `ManagedIdentity` section with `{ "ClientId": "<client-id>" }`. For the identity configuration B, with Azure SQL only:
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
0f2a88d to
e78053d
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
Remove or properly document the unsupported AKS Workload Identity guidance.
Review details
Suppressed comments (2)
Csag.WorkloadIdentity/README.md:154
- This quickstart also lists AKS as a supported host, but the implementation constructs only
ManagedIdentityCredential; AKS Workload Identity normally requiresWorkloadIdentityCredentialand projected-token configuration. Please remove AKS here unless the library is extended/configured for that credential flow.
An application on App Service (or Container Apps, Functions, a virtual machine, AKS) has a managed identity, so both tokens come from the `ManagedIdentity` provider. Blob Storage is reached through the Azure SDK, with `WorkloadIdentityTokenCredential` adapting the library's provider to the `TokenCredential` the SDK expects.
Csag.WorkloadIdentity/README.md:10
ManagedIdentityCredentialis the only credential this library creates, but standard AKS Workload Identity uses a projected Kubernetes service-account token withWorkloadIdentityCredential, not the managed-identity endpoint selected here. As written, this makes AKS look supported by this provider when the quickstart supplies no required AKS federation setup; please remove AKS from this list or document a supported AKS configuration separately.
- **`ManagedIdentity`.** The library requests the token from the managed identity endpoint of the Azure resource the application runs on (App Service, Container Apps, Functions, a virtual machine, AKS and so on), as the system-assigned identity of that resource or as a user-assigned identity selected by its client ID.
- Files reviewed: 5/5 changed files
- Comments generated: 0 new
- Review effort level: Lite
e78053d to
66b65e1
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The documentation changes have been reviewed and no blocking issues remain.
Review details
Suppressed comments (1)
docs/cloud-identity-setup.md:292
- The replacement example omits the
ManagedIdentityproperty name, so copying it into the preceding JSON would produce invalid configuration. Keep the resource property and replace only its value, e.g."ManagedIdentity": { "ClientId": "<client-id>" }.
For a user-assigned identity replace the `ManagedIdentity` section with `{ "ClientId": "<client-id>" }`. For the identity configuration B, with Azure SQL only:
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Lite
Package README: the resource-first model, two quickstarts (Azure SQL from Google Cloud Run over workload identity federation; Azure SQL and Blob Storage from Azure App Service with a system- or user-assigned managed identity, including a BlobServiceClient built on WorkloadIdentityTokenCredential), a reference of every option for both providers, and a migration section from Neolution.AzureSqlFederatedIdentity with the before/after configuration and the AddWorkloadIdentity rename. Every C# sample compiles against the library. Setup guide: restructured as a choice between an Azure managed identity and Google Cloud to Azure federation, with both holders of the federated credential (app registration or user-assigned managed identity), the Azure SQL and Blob Storage grants, the new configuration keys, App Service and Cloud Run deployment, and Microsoft Entra-only authentication. Vendor facts and every URL verified. Root README, SECURITY.md and a patch changeset follow the new name and model. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
An unrecognised Provider value is rejected by the configuration binder before options validation runs, and AKS pods do not use the resource Identity setting. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ll needs a resource section; runtime flow per provider Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ned password users automatically Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… AccessTokenCallback for a single pool Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
66b65e1 to
eddfae1
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
Fix the AKS support guidance and correct the AccessTokenCallback API example.
Review details
Suppressed comments (2)
Csag.WorkloadIdentity/README.md:154
- This quickstart lists AKS as a supported host for
ManagedIdentity, but the library constructsAzure.Identity.ManagedIdentityCredential, which requires an Azure managed-identity endpoint. Standard AKS workload identity exposes a projected token and is consumed withWorkloadIdentityCredential, not this credential, so users following this guide on AKS will fail to obtain a token. Remove AKS from this list (or document a separately supported AKS identity integration).
An application on App Service (or Container Apps, Functions, a virtual machine, AKS) has a managed identity, so both tokens come from the `ManagedIdentity` provider. Blob Storage is reached through the Azure SDK, with `WorkloadIdentityTokenCredential` adapting the library's provider to the `TokenCredential` the SDK expects.
Csag.WorkloadIdentity/README.md:347
- The
AccessTokenCallbackexample calls the wrong API shape:IAzureSqlTokenProviderexposesGetAzureSqlAccessTokenAsync, whileGetAccessTokenAsyncis inherited fromIAccessTokenProviderand returnsTask<Azure.Core.AccessToken>. Please reference the inherited method explicitly (and itsAzure.Core.AccessTokenresult) so readers do not try to compile a nonexistentIAzureSqlTokenProvider.GetAccessTokenAsyncoverload.
- **Token handling.** The provider holds the token; do not cache or persist it yourself. `AccessToken` is part of the `SqlClient` connection pool key, so a refreshed token starts a new pool, which is expected. If your connection string sets `Min Pool Size` above zero, call `SqlConnection.ClearPool` with a connection that carries the old token once it has expired; otherwise the pool keeps that token's physical connections open indefinitely (see the [`AccessToken` remarks](https://learn.microsoft.com/en-us/dotnet/api/microsoft.data.sqlclient.sqlconnection.accesstoken)). Alternatively, set `SqlConnection.AccessTokenCallback` (Microsoft.Data.SqlClient 5.2 or later) to a delegate that returns `new SqlAuthenticationToken(token.Token, token.ExpiresOn)` from `IAzureSqlTokenProvider.GetAccessTokenAsync`: the callback keeps a single pool across token refreshes.
- Files reviewed: 5/5 changed files
- Comments generated: 0 new
- Review effort level: Lite
Summary
Documentation for the generalised
Csag.WorkloadIdentitylibrary.Provider: Google) end to end,SqlConnection.AccessTokenand the EF Core factory; quickstart B — Azure SQL + Blob Storage from Azure App Service (Provider: ManagedIdentity, system- and user-assigned),BlobServiceClientonWorkloadIdentityTokenCredential; a full options reference for both providers plusRefreshAheadWindow/EnableBackgroundRefresh; a migration section fromCsag.AzureSqlFederatedIdentity/Neolution.AzureSqlFederatedIdentitywith before/after JSON and theAddWorkloadIdentityrename; notes on credential-free connection strings, ADC and the service-account identity, and what the background refresh actually does.docs/cloud-identity-setup.mdrestructured as "choose your identity configuration": (A) Azure Managed Identity (enable system/user-assigned,CREATE USER … FROM EXTERNAL PROVIDER, Blob RBAC roles) — from Generalize project and rename it to Neolution.WorkloadIdentity #2'sIDENTITY-SETUP.md; (B) Google Cloud → Azure federation, keeping the verified least-privilege content (roles/iam.serviceAccountOpenIdTokenCreatorbound on the service account,iamcredentials.googleapis.comenabled, audienceapi://AzureADTokenExchange) and covering both holders of the federated credential — an app registration or a user-assigned managed identity — sinceGoogleOptions.ClientIdaccepts either; resource grants; "Configure the application" with the new keys; Generalize project and rename it to Neolution.WorkloadIdentity #2's "disable SQL authentication" hardening section. Microsoft Entra ID naming throughout.Stacked on the Demo PR (it links the Demo README).
Validation
Every sample checked against the actual members, overloads and keys on the branch; every relative link resolves on the rebased head; absolute URLs return 200 except the nuget.org page of the not-yet-published package ID. Vendor facts re-checked. Adversarially verified.
🤖 Generated with Claude Code