Skip to content

Audit extension tenant selection for guest and cross-tenant scenarios #7563

Description

@weikanglim

Background

PR #7549 fixed core azd tenant selection by distinguishing:

  • the access tenant (UserAccessTenantId / proto UserTenantId) used to acquire credentials for a signed-in user
  • the subscription/resource tenant (Subscription.TenantId) that owns the subscription and its RBAC state

That PR intentionally stayed core-only. A follow-up extension audit found a separate cleanup worth tracking.

This is broader than #7077, which fixed one extension path with the same access-tenant issue.

The extension-facing APIs already expose both values on azdext.Subscription, so this should not require new gRPC surface area.

Follow-up work

  1. Fix generated extension templates

    The generated Go / JS / .NET prompt samples currently use PromptSubscription().Subscription.TenantId when creating AzureDeveloperCliCredential.

    These are access-tenant credential scenarios and should use UserTenantId instead.

    Files:

    • extensions/microsoft.azd.extensions/internal/resources/languages/go/internal/cmd/prompt.go.tmpl
    • extensions/microsoft.azd.extensions/internal/resources/languages/javascript/commands/prompt.js
    • extensions/microsoft.azd.extensions/internal/resources/languages/dotnet/commands/PromptCommand.cs
  2. Fix resource-tenant extension flows

    At least one extension path looks like the same class of bug that Fix principal tenant resolution and simplify subscription lookup #7549 fixed in core:

    • extensions/azure.ai.agents/internal/project/agent_identity_rbac.go

    This code currently uses Account().LookupTenant(...) and then performs Graph service principal discovery plus RBAC role assignment. Since LookupTenant() returns the access tenant, this path should be reviewed to confirm whether it must instead use the subscription/resource tenant.

  3. Audit remaining explicit-subscription fallback paths

    Several extensions call LookupTenant(...) or persist AZURE_TENANT_ID during explicit-subscription flows. Many of these may be correct access-tenant scenarios, but they should be audited and documented so we are consistent about when to use:

    • UserTenantId / LookupTenant() for user credential acquisition
    • Subscription.TenantId for resource-tenant principal / RBAC operations

    Candidate files:

    • extensions/azure.appservice/internal/cmd/swap.go
    • extensions/azure.ai.models/internal/cmd/init.go
    • extensions/azure.ai.models/internal/cmd/custom.go
    • extensions/azure.ai.agents/internal/cmd/init_foundry_resources_helpers.go
    • extensions/azure.ai.finetune/internal/cmd/init.go
    • extensions/azure.ai.agents/internal/project/service_target_agent.go

Acceptance criteria

  • Generated extension templates use UserTenantId for PromptSubscription-based credential creation
  • Resource-tenant principal / RBAC flows in extensions use the subscription tenant where required
  • We add regression coverage for at least one guest/cross-tenant case for each fixed pattern
  • We document any remaining intentional LookupTenant() usages as access-tenant cases

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/authAuthentication, credentials, identityarea/extensionsExtensions (general)area/uxUX, prompts, output formattingenhancementNew feature or improvement

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions