Skip to content

Thread tenant ID through per-request credentials (#1770) - #3262

Draft
Vinay Gera (g2vinay) wants to merge 1 commit into
microsoft:mainfrom
g2vinay:g2vinay/issue-1770-tenant-credential
Draft

Thread tenant ID through per-request credentials (#1770)#3262
Vinay Gera (g2vinay) wants to merge 1 commit into
microsoft:mainfrom
g2vinay:g2vinay/issue-1770-tenant-credential

Conversation

@g2vinay

@g2vinay Vinay Gera (g2vinay) commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Addresses #1770: tools that authenticate with per-request TokenCredentials must honor the --tenant option so the credential is created for the tenant the request targets. When a tool ignored the tenant, requests could fail whenever the target tenant differed from the credential's default tenant.

This PR audits the tools in that class and threads the tenant through to credential creation:

  • Bug fix — applicationinsights recommendation list: the command already accepted --tenant, but the service layer dropped it when creating the credential used to read profiler data. The tenant now flows through to GetCredential(tenant).
  • Feature — added --tenant to the commands in the following areas and propagated it to credential creation: Deploy, MySQL, PostgreSQL, Quota, and Azure AI Search.

Each service now creates its per-request credential (and, where applicable, its ARM / data-plane clients) for the specified tenant, and tenant is included in credential cache keys where clients are cached.

Note on "one tool per PR": this issue is intentionally cross-cutting — it asks to review all tools in the per-request-credential class — so the change spans several tools by design. Each tool's change is small and mechanical: thread an optional tenant parameter through to credential creation.

Follow-ups (tracked separately, out of scope here)

  • SQL (Azure.Mcp.Tools.Sql) — same per-request-credential class; not yet threaded. Planned as a dedicated follow-up.
  • Confidential Ledger and Speech — endpoint-based commands that build a credential from an endpoint only (no subscription/tenant option today). Hardening these to accept/enforce a tenant is deferred API design.

Ensure tools that authenticate with per-request TokenCredentials honor the --tenant option so credentials are created for the tenant the request targets. Without this, requests can fail when the target tenant differs from the credential's default tenant.

- Fix 'applicationinsights recommendation list' dropping --tenant when creating the profiler-data credential (bug fix).

- Add a --tenant option to the Deploy, MySQL, PostgreSQL, Quota, and Azure AI Search commands and propagate it through to credential creation.

Follow-ups tracked separately: SQL (same per-request-credential class, not yet threaded); ConfidentialLedger and Speech (endpoint-based commands, API-hardening deferred).
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Threads the --tenant option through multiple toolsets that create per-request TokenCredentials so credentials (and cached clients) are created for the tenant a request targets, avoiding cross-tenant auth failures (addresses #1770).

Changes:

  • Propagates tenant through service/client creation paths (and cache keys where applicable) for Azure AI Search, Quota, Deploy, MySQL, PostgreSQL, and Application Insights profiler reads.
  • Adds Tenant options to affected command option types and forwards the value into corresponding service calls.
  • Updates unit tests to match the new method signatures.

Reviewed changes

Copilot reviewed 68 out of 68 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tools/Azure.Mcp.Tools.Search/tests/Azure.Mcp.Tools.Search.Tests/Knowledge/KnowledgeSourceGetCommandTests.cs Updates mocks for added tenant parameter in knowledge source list flow.
tools/Azure.Mcp.Tools.Search/tests/Azure.Mcp.Tools.Search.Tests/Knowledge/KnowledgeBaseRetrieveCommandTests.cs Updates mocks for added tenant parameter in knowledge base retrieval flow.
tools/Azure.Mcp.Tools.Search/tests/Azure.Mcp.Tools.Search.Tests/Knowledge/KnowledgeBaseGetCommandTests.cs Updates mocks for added tenant parameter in knowledge base list flow.
tools/Azure.Mcp.Tools.Search/tests/Azure.Mcp.Tools.Search.Tests/Index/IndexQueryCommandTests.cs Updates mocks for added tenant parameter in index query flow.
tools/Azure.Mcp.Tools.Search/tests/Azure.Mcp.Tools.Search.Tests/Index/IndexGetCommandTests.cs Updates mocks for added tenant parameter in index get/list flow.
tools/Azure.Mcp.Tools.Search/src/Services/SearchService.cs Threads tenant into client creation, credential acquisition, and SearchIndexClient cache keys.
tools/Azure.Mcp.Tools.Search/src/Services/ISearchService.cs Extends service contract to accept optional tenant across relevant methods.
tools/Azure.Mcp.Tools.Search/src/Options/Knowledge/KnowledgeSourceGetOptions.cs Adds Tenant CLI option for knowledge source get.
tools/Azure.Mcp.Tools.Search/src/Options/Knowledge/KnowledgeBaseRetrieveOptions.cs Adds Tenant CLI option for knowledge base retrieve.
tools/Azure.Mcp.Tools.Search/src/Options/Knowledge/KnowledgeBaseGetOptions.cs Adds Tenant CLI option for knowledge base get/list.
tools/Azure.Mcp.Tools.Search/src/Options/Index/IndexQueryOptions.cs Adds Tenant CLI option for index query.
tools/Azure.Mcp.Tools.Search/src/Options/Index/IndexGetOptions.cs Adds Tenant CLI option for index get/list.
tools/Azure.Mcp.Tools.Search/src/Commands/Knowledge/KnowledgeSourceGetCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.Search/src/Commands/Knowledge/KnowledgeBaseRetrieveCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.Search/src/Commands/Knowledge/KnowledgeBaseGetCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.Search/src/Commands/Index/IndexQueryCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.Search/src/Commands/Index/IndexGetCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.Quota/tests/Azure.Mcp.Tools.Quota.Tests/Commands/Usage/CheckCommandTests.cs Updates mocks for added tenant parameter on quota usage check.
tools/Azure.Mcp.Tools.Quota/tests/Azure.Mcp.Tools.Quota.Tests/Commands/Region/AvailabilityListCommandTests.cs Updates mocks for added tenant parameter on availability list.
tools/Azure.Mcp.Tools.Quota/src/Services/QuotaService.cs Uses tenant when creating credentials/ARM client for quota operations.
tools/Azure.Mcp.Tools.Quota/src/Services/IQuotaService.cs Extends service contract to accept tenant.
tools/Azure.Mcp.Tools.Quota/src/Options/Usage/CheckOptions.cs Adds Tenant CLI option for quota usage check.
tools/Azure.Mcp.Tools.Quota/src/Options/Region/AvailabilityListOptions.cs Adds Tenant CLI option for region availability list.
tools/Azure.Mcp.Tools.Quota/src/Commands/Usage/CheckCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.Quota/src/Commands/Region/AvailabilityListCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.Postgres/tests/Azure.Mcp.Tools.Postgres.Tests/Table/TableSchemaGetCommandTests.cs Updates mocks for added tenant parameter in table schema retrieval.
tools/Azure.Mcp.Tools.Postgres/tests/Azure.Mcp.Tools.Postgres.Tests/Services/PostgresServiceTests.cs Updates service tests for new tenant parameter positions.
tools/Azure.Mcp.Tools.Postgres/tests/Azure.Mcp.Tools.Postgres.Tests/Services/PostgresServiceServerNameValidationTests.cs Updates server-name validation tests for new tenant parameter positions.
tools/Azure.Mcp.Tools.Postgres/tests/Azure.Mcp.Tools.Postgres.Tests/Services/PostgresServiceRowLimitTests.cs Updates row-limit tests for new tenant parameter positions.
tools/Azure.Mcp.Tools.Postgres/tests/Azure.Mcp.Tools.Postgres.Tests/Services/PostgresServiceParameterizedQueryTests.cs Updates parameterization tests for new tenant parameter positions.
tools/Azure.Mcp.Tools.Postgres/tests/Azure.Mcp.Tools.Postgres.Tests/Services/PostgresServiceConnectionStringInjectionTests.cs Updates connection-string injection tests for new tenant parameter positions.
tools/Azure.Mcp.Tools.Postgres/tests/Azure.Mcp.Tools.Postgres.Tests/PostgresListCommandTests.cs Updates list command tests for new tenant parameter positions.
tools/Azure.Mcp.Tools.Postgres/tests/Azure.Mcp.Tools.Postgres.Tests/Database/DatabaseQueryCommandTests.cs Updates query command tests for new tenant parameter positions.
tools/Azure.Mcp.Tools.Postgres/src/Services/PostgresService.cs Threads tenant into Entra token acquisition and ARM scoping calls.
tools/Azure.Mcp.Tools.Postgres/src/Services/IPostgresService.cs Extends service contract to accept tenant.
tools/Azure.Mcp.Tools.Postgres/src/Options/Table/TableSchemaGetOptions.cs Adds Tenant CLI option for table schema get.
tools/Azure.Mcp.Tools.Postgres/src/Options/PostgresListOptions.cs Adds Tenant CLI option for list command.
tools/Azure.Mcp.Tools.Postgres/src/Options/Database/DatabaseQueryOptions.cs Adds Tenant CLI option for database query command.
tools/Azure.Mcp.Tools.Postgres/src/Commands/Table/TableSchemaGetCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.Postgres/src/Commands/PostgresListCommand.cs Forwards options.Tenant into service calls.
tools/Azure.Mcp.Tools.Postgres/src/Commands/Database/DatabaseQueryCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.MySql/tests/Azure.Mcp.Tools.MySql.Tests/Table/TableSchemaGetCommandTests.cs Updates mocks for added tenant parameter in schema retrieval.
tools/Azure.Mcp.Tools.MySql/tests/Azure.Mcp.Tools.MySql.Tests/Services/MySqlServiceTests.cs Updates service tests for new tenant parameter positions.
tools/Azure.Mcp.Tools.MySql/tests/Azure.Mcp.Tools.MySql.Tests/Services/MySqlServiceServerNameValidationTests.cs Updates server-name validation tests for new tenant parameter positions.
tools/Azure.Mcp.Tools.MySql/tests/Azure.Mcp.Tools.MySql.Tests/Server/ServerParamSetCommandTests.cs Updates mocks for added tenant parameter in server param set.
tools/Azure.Mcp.Tools.MySql/tests/Azure.Mcp.Tools.MySql.Tests/Server/ServerParamGetCommandTests.cs Updates mocks for added tenant parameter in server param get.
tools/Azure.Mcp.Tools.MySql/tests/Azure.Mcp.Tools.MySql.Tests/Server/ServerConfigGetCommandTests.cs Updates mocks for added tenant parameter in config get.
tools/Azure.Mcp.Tools.MySql/tests/Azure.Mcp.Tools.MySql.Tests/MySqlListCommandTests.cs Updates mocks for added tenant parameter in list flows.
tools/Azure.Mcp.Tools.MySql/tests/Azure.Mcp.Tools.MySql.Tests/Database/DatabaseQueryCommandTests.cs Updates mocks for added tenant parameter in query flow.
tools/Azure.Mcp.Tools.MySql/src/Services/MySqlService.cs Threads tenant into Entra token acquisition and ARM scoping calls.
tools/Azure.Mcp.Tools.MySql/src/Services/IMySqlService.cs Extends service contract to accept tenant.
tools/Azure.Mcp.Tools.MySql/src/Options/MySqlListOptions.cs Adds Tenant CLI option for list command.
tools/Azure.Mcp.Tools.MySql/src/Options/BaseMySqlOptions.cs Adds Tenant to shared MySQL server/database option base.
tools/Azure.Mcp.Tools.MySql/src/Commands/Table/TableSchemaGetCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.MySql/src/Commands/Server/ServerParamSetCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.MySql/src/Commands/Server/ServerParamGetCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.MySql/src/Commands/Server/ServerConfigGetCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.MySql/src/Commands/MySqlListCommand.cs Forwards options.Tenant into service calls.
tools/Azure.Mcp.Tools.MySql/src/Commands/Database/DatabaseQueryCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.Deploy/tests/Azure.Mcp.Tools.Deploy.Tests/Commands/App/LogsGetCommandTests.cs Updates mocks for added tenant parameter in log retrieval.
tools/Azure.Mcp.Tools.Deploy/src/Services/IDeployService.cs Extends Deploy service contract to accept optional tenant.
tools/Azure.Mcp.Tools.Deploy/src/Services/DeployService.cs Threads tenant into ARM + LogsQuery client creation and credential acquisition.
tools/Azure.Mcp.Tools.Deploy/src/Options/App/LogsGetOptions.cs Adds Tenant CLI option for logs get.
tools/Azure.Mcp.Tools.Deploy/src/Commands/App/LogsGetCommand.cs Forwards options.Tenant into service call.
tools/Azure.Mcp.Tools.ApplicationInsights/src/Services/ProfilerDataService.cs Threads tenant into request signing by acquiring tokens using tenant-aware credentials.
tools/Azure.Mcp.Tools.ApplicationInsights/src/Services/IProfilerDataService.cs Extends profiler data service contract to accept optional tenant.
tools/Azure.Mcp.Tools.ApplicationInsights/src/Services/ApplicationInsightsService.cs Passes tenant into profiler data service call chain.
servers/Azure.Mcp.Server/changelog-entries/g2vinay-tenant-credential-threading.yaml Adds changelog entry documenting the tenant threading fix/feature.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 29 to 33
Arg.Is("service123"),
Arg.Is((string?)null),
Arg.Any<string?>(),
Arg.Any<RetryPolicyOptions>(),
Arg.Any<CancellationToken>())
Comment on lines 21 to 27
Service.GetAzdResourceLogsAsync(
Arg.Any<string>(),
Arg.Any<string>(),
Arg.Any<string>(),
Arg.Any<int?>(),
Arg.Any<string?>(),
Arg.Any<CancellationToken>())
Comment on lines 19 to 23
var expectedServers = new List<string> { "mysql-server-1", "mysql-server-2", "mysql-server-3" };
Service.ListServersInSubscriptionAsync("sub123", Arg.Any<CancellationToken>()).Returns(expectedServers);
Service.ListServersInSubscriptionAsync("sub123", Arg.Any<string?>(), Arg.Any<CancellationToken>()).Returns(expectedServers);

var response = await ExecuteCommandAsync(
"--subscription", "sub123");
Comment on lines 28 to 32
var expectedServers = new List<string> { "postgres-server-1", "postgres-server-2", "postgres-server-3" };
Service.ListServersAsync("sub123", "rg1", Arg.Any<CancellationToken>()).Returns(expectedServers);
Service.ListServersAsync("sub123", "rg1", null, Arg.Any<CancellationToken>()).Returns(expectedServers);

var response = await ExecuteCommandAsync(
"--subscription", "sub123",
Comment on lines +53 to 55
Arg.Any<string?>(),
Arg.Any<CancellationToken>())
.Returns(expectedQuotaInfo);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants