microsoft / microsoft/aspire

AKS credential fetch: subscription-scoped and tenant-scoped clusters fall back to the app's resource group

Open
#19,262 1 comment 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

Follow-up from review feedback on #19219, deliberately deferred to keep that PR scoped to the original bug (the credential pipeline using the ambient Azure CLI subscription).

Both findings below are legitimate. They are pre-existing behavior, not regressions introduced by #19219 — before that PR there was no per-resource scope handling at all, so these paths already resolved to the app's deployment scope.

## 1. A pinned subscription with no resource group inherits the app's resource group

`AzureKubernetesEnvironmentResource.ResolveDeploymentScopeAsync` currently does:

```csharp
resourceGroup = pinnedSubscription && !string.Equals(subscriptionId, globalSubscriptionId, StringComparison.OrdinalIgnoreCase)
? null
: globalResourceGroup;
```

When a resource pins a subscription but no resource group (`AzureBicepResourceScope.CreateForSubscription`, so `HasResourceGroup == false`), and that subscription happens to equal the saved `Azure:SubscriptionId`, the saved `Azure:ResourceGroup` is inherited.

That inheritance is unfounded. `BicepProvisioner` deploys a subscription-scoped resource through the subscription deployment collection, so the resulting cluster can be in any resource group in that subscription. The saved resource group records where the *app* was deployed, which is not evidence of where the *cluster* landed. A non-empty resource group then short-circuits discovery in `GetResourceGroupAsync`, so `az aks get-credentials` can silently target a same-named cluster in the app's own group.

**Suggested fix:** force discovery whenever a subscription is pinned without a resource group, regardless of whether it matches the saved subscription:

```csharp
resourceGroup = pinnedSubscription ? null : globalResourceGroup;
```

Discovery is already scoped to the pinned subscription and, since #19219, fails loudly when the cluster name matches more than one resource group, so this is strictly safer than guessing.

## 2. Tenant-scoped clusters silently fall back to the app's scope

`GetExplicitScopeValues` returns `(null, null)` for a tenant-scoped `Scope` (and for a tenant-scoped `ExistingAzureResourceAnnotation`), which then falls all the way back to the saved subscription and resource group.

A tenant-scoped resource is deployed through the tenant deployment collection, so the app's subscription/resource group again says nothing about where the cluster lives. An AKS cluster cannot exist at tenant scope at all, so this configuration is arguably always a mistake — and the silent fallback can fetch credentials for an unrelated same-named cluster.

**Suggested fix:** throw a clear error pointing at `AsExistingInResourceGroup` instead of falling back. Tenant scope is only reachable via an explicit `AzureBicepResourceScope.CreateForTenant()` or an explicitly tenant-scoped annotation, never by default, so this cannot affect a normally configured cluster.

## Notes

Both fixes were prototyped on the #19219 branch (commit `d26472a714`, since reverted) and validated: 90/90 tests green, 0 warnings, and mutation-verified that reverting each fix fails exactly the expected tests. The prototype is a small change to `ResolveDeploymentScopeAsync` plus a throw helper in `GetExplicitScopeValues`, with three tests:

- `DeploymentScopeDropsDeploymentResourceGroupWhenResourcePinsOnlySubscription`
- `GetCredentialsStepDiscoversResourceGroupForSubscriptionScopedResources`
- `ExplicitScopeThrowsWhenResourceIsTenantScoped`

Note that testing the tenant-scoped *annotation* path from `Aspire.Hosting.Azure.Kubernetes.Tests` is not currently possible: the tenant-scope `ExistingAzureResourceAnnotation` constructor is `internal` and `Aspire.Hosting.Azure` only grants `InternalsVisibleTo` to `Aspire.Hosting.Azure.Tests`.

Contributor guide

Open the contributing guide

Research direction

Start with AzureKubernetesEnvironmentResource.ResolveDeploymentScopeAsync and GetExplicitScopeValues, then inspect the three named tests: DeploymentScopeDropsDeploymentResourceGroupWhenResourcePinsOnlySubscription, GetCredentialsStepDiscoversResourceGroupForSubscriptionScopedResources, and ExplicitScopeThrowsWhenResourceIsTenantScoped. Run the relevant Azure Kubernetes tests; done means both scope cases avoid an unsafe fallback and the tenant-scoped case reports the intended error.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.