fix: remote state -- fall back to defaults.subscription - #7072
Conversation
…llback When no SubscriptionId is set in AccountConfig, NewBlobSdkClient now falls back to the default subscription from user config to resolve the correct tenant for authentication. Updated all callers and tests accordingly.
defaults.subscription
There was a problem hiding this comment.
Pull request overview
Updates the Azure Blob remote state client construction so that when state.remote.config.subscriptionId isn’t provided, tenant resolution uses the user’s configured default subscription (defaults.subscription) instead of implicitly using the home tenant—addressing guest-user issuer validation failures for remote state (#7067).
Changes:
- Extend
storage.NewBlobSdkClientto accept aconfig.UserConfigManagerand use it to fall back todefaults.subscriptionwhenAccountConfig.SubscriptionIdis empty. - Update IoC/test wiring to provide a
UserConfigManagerto the blob SDK client factory. - Add/adjust unit tests to cover default-subscription fallback and config-load error behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| cli/azd/pkg/azsdk/storage/storage_blob_client.go | Adds UserConfigManager dependency and default-subscription fallback logic for tenant resolution. |
| cli/azd/pkg/azsdk/storage/storage_blob_client_test.go | Updates tests for new constructor signature; adds tests for fallback and load-failure behavior. |
| cli/azd/test/functional/remote_state_test.go | Updates functional test blob client setup to pass a UserConfigManager. |
| cli/azd/pkg/environment/manager_test.go | Updates test IoC registration to provide UserConfigManager required by NewBlobSdkClient. |
Comments suppressed due to low confidence (2)
cli/azd/pkg/azsdk/storage/storage_blob_client_test.go:113
- This test sets an expectation on mockConfigMgr.Load(), but never asserts it. Without AssertExpectations/AssertCalled, the test would still pass if NewBlobSdkClient stops consulting user config when SubscriptionId is empty. Add an assertion on mockConfigMgr to ensure the intended behavior is verified.
This issue also appears on line 250 of the same file.
// User config has no default subscription either
mockConfigMgr.On("Load").Return(config.NewEmptyConfig(), nil)
// Expect credential provider to be called with empty tenant ID (home tenant)
mockCredProvider.On("GetTokenCredential", mock.Anything, "").Return(mockCred, nil)
client, err := NewBlobSdkClient(
mockCredProvider,
accountCfg,
mockConfigMgr,
coreClientOptions,
cloud.AzurePublic(),
mockTenantResolver,
)
require.NoError(t, err)
require.NotNil(t, client)
mockCredProvider.AssertExpectations(t)
// TenantResolver should NOT be called when no subscription ID is provided
mockTenantResolver.AssertNotCalled(t, "LookupTenant", mock.Anything, mock.Anything)
}
cli/azd/pkg/azsdk/storage/storage_blob_client_test.go:269
- This test configures mockConfigMgr.Load() to return an error, but doesn’t assert that Load was actually invoked. Add AssertExpectations/AssertCalled on mockConfigMgr so the “graceful fallback when Load fails” behavior is exercised and protected against regression.
// User config fails to load - should gracefully fall back to home tenant
mockConfigMgr.On("Load").Return(nil, errors.New("config not found"))
// Expect credential provider to be called with empty tenant ID (home tenant)
mockCredProvider.On("GetTokenCredential", mock.Anything, "").Return(mockCred, nil)
client, err := NewBlobSdkClient(
mockCredProvider,
accountCfg,
mockConfigMgr,
coreClientOptions,
cloud.AzurePublic(),
mockTenantResolver,
)
require.NoError(t, err)
require.NotNil(t, client)
mockCredProvider.AssertExpectations(t)
mockTenantResolver.AssertNotCalled(t, "LookupTenant", mock.Anything, mock.Anything)
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
vhvb1989
left a comment
There was a problem hiding this comment.
The fix looks good — falling back to defaults.subscription instead of the home tenant is the right call for the remote state scenario.
One observation worth noting: the BlobClient is unique in the codebase in that it binds subscription/tenant at construction time (via AccountConfig), whereas all other Azure service clients (KeyVault, ContainerApps, ContainerRegistry, etc.) follow a per-call subscriptionId pattern with a SubscriptionCredentialProvider. Even FileShareService in the same storage package follows the standard per-call pattern.
This works fine today since BlobClient is only used for remote state, but it would be good to consolidate this into a StorageBlobService following the standard pattern for consistency and future extensibility.
Filed #7073 to track this as a future improvement.
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
…llback (Azure#7072) When `state.remote.config.subscriptionId` isn't set, the blob client constructed for remote state now falls back to the default subscription from user config (`defaults.subscription`). Previously, it used the home tenant which is unexpected. Fixes Azure#7067
…llback (Azure#7072) When `state.remote.config.subscriptionId` isn't set, the blob client constructed for remote state now falls back to the default subscription from user config (`defaults.subscription`). Previously, it used the home tenant which is unexpected. Fixes Azure#7067
…llback (Azure#7072) When `state.remote.config.subscriptionId` isn't set, the blob client constructed for remote state now falls back to the default subscription from user config (`defaults.subscription`). Previously, it used the home tenant which is unexpected. Fixes Azure#7067
…llback (Azure#7072) When `state.remote.config.subscriptionId` isn't set, the blob client constructed for remote state now falls back to the default subscription from user config (`defaults.subscription`). Previously, it used the home tenant which is unexpected. Fixes Azure#7067
…llback (Azure#7072) When `state.remote.config.subscriptionId` isn't set, the blob client constructed for remote state now falls back to the default subscription from user config (`defaults.subscription`). Previously, it used the home tenant which is unexpected. Fixes Azure#7067
When
state.remote.config.subscriptionIdisn't set, the blob client constructed for remote state now falls back to the default subscription from user config (defaults.subscription). Previously, it used the home tenant which is unexpected.Changes
userConfigManager config.UserConfigManagerparameter toNewBlobSdkClientAccountConfig.SubscriptionIdis emptyremote_state_test.goandmanager_test.go(IoC registration)Fixes #7067