Repository navigation
[Az.Accounts] Fix access denied on config init mutex when importing under different users - #30340
Open
Leon Zandman (lzandman) wants to merge 4 commits into
Open
Leon Zandman (lzandman) wants to merge 4 commits into
Leon Zandman (lzandman) wants to merge 4 commits into
Conversation
…nder different users Fixes Azure#25701. Config initialization was guarded by a single machine-wide mutex, Global\AzurePowerShellConfigInit. Once a process running as one user created it, processes running as other users could not open it, and importing the module failed with "Access to the path 'Global\AzurePowerShellConfigInit' is denied". The config file lives in the user's profile, so the lock only has to be shared by processes of the same user. Derive the mutex name from a hash of the config file path so users no longer collide. If the mutex still cannot be opened, warn and fall back to safe-mode initialization instead of failing the import. An abandoned mutex is now treated as acquired, since ownership passes to the waiting thread.
Contributor
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
|
Thank you for your contribution Leon Zandman (@lzandman)! We will review the pull request and get back to you soon. |
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
Source review identified no blocking issues in the focused mutex changes; tests were not executed during this review.
No open issues 🎉
What changed in this PR
Fixes #25701 by isolating Az.Accounts configuration initialization locks by config path, preventing cross-user mutex access conflicts during concurrent imports.
Changes:
- Replaces the machine-wide shared lock name with a config-path-derived name.
- Falls back to safe mode when the lock cannot be opened and handles abandoned mutexes as acquired.
- Adds focused unit tests and user-facing release notes.
| File | Description |
|---|---|
| src/Accounts/Authentication/AzureSessionInitializer.cs | Scopes mutex names and handles lock failures and abandonment. |
| src/Accounts/Authentication.Test/SessionInitializationTests.cs | Tests path-scoped names and abandoned-mutex acquisition. |
| src/Accounts/Accounts/ChangeLog.md | Documents the import fix and safe-mode fallback. |
Review effort: Balanced
Contributor
|
/azp run |
Contributor
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 PR Validation —⚠️ Review suggested
️✔️Az.Aks
️✔️Az.Compute
️✔️Az.Functions
️✔️Az.KubernetesConfiguration
️✔️Az.ManagedServiceIdentity
️✔️Az.Monitor
️✔️Az.Network
️✔️Az.OperationalInsights
️✔️Az.PrivateDns
️✔️Az.Resources
️✔️Az.Sql
️✔️Az.Websites
Description
Fixes #25701:
Import-Module Az.Accountsfails withAccess to the path 'Global\AzurePowerShellConfigInit' is deniedwhen processes run by different users (e.g. multiple DevOps agents or scheduled tasks on one machine) import the module concurrently.Root cause
AzureSessionInitializer.InitializeConfigscreates a machine-wide named mutex without explicit security. Windows gives it the default DACL of the creating process, so while it exists, a process running as another principal cannot open it and theMutexconstructor throws. The constructor sits outside anytry, so the whole module import fails.The lock protects
PSConfig.jsonin the current user's profile, so different users never need to share it.Changes
Global\AzurePowerShellConfigInit_<hash>, where the hash is the first 16 bytes of the SHA-256 of the upper-cased path, as 32 hex characters). Processes of the same user still share the lock, but different users no longer collide. 128 bits is far more than needed to tell apart the few user profiles on one machine, and keeps the name readable in tools such as Process Explorer.AbandonedMutexExceptionfromWaitOneis treated as a successful acquire, so the next process can still initialize configs if a previous one crashed while holding the lock.Compatibility
For a single user, behaviour is unchanged: processes share one lock with the same 1 s timeout and the same safe-mode fallback. Because the lock name changed, an older and a newer Az.Accounts version running side by side for the same user no longer share a lock. The worst case is that both initialize configs at once, which is what already happens today when the timeout expires. When an abandoned lock is acquired, a config file left half-written by the crashed owner is handled by the existing
try/catcharound initialization, which falls back to safe mode.Explicit mutex ACLs (
MutexAcl) were considered but not used. They are Windows-only, do not help against mutexes created by older versions, and .NET Framework'sMutexconstructor would require granting Everyone full control.Tests
Added unit tests to
SessionInitializationTestscovering the mutex name scoping and acquiring an abandoned mutex.Also tested manually on Windows 11 (PowerShell 7.6 and Windows PowerShell 5.1), comparing Az.Accounts 5.5.3 from the Gallery with a build of this branch. Each user ran in a separate logon session (SSH), like separate DevOps agents:
Global\AzurePowerShellConfigInit, 5.5.3 fails with the access-denied error. The fixed build imports normally.On macOS (PowerShell 7.6) the unit tests, timeout and abandoned-mutex scenarios pass as well. macOS can't show the cross-user fix, because .NET emulates named mutexes with files there.
Mandatory Checklist
Please choose the target release of Azure PowerShell. (⚠️ Target release is a different concept from API readiness. Please click below links for details.)
Check this box to confirm: I have read the Submitting Changes section of
CONTRIBUTING.mdand reviewed the following information:ChangeLog.mdfile(s) appropriatelysrc/{{SERVICE}}/{{SERVICE}}/ChangeLog.md.## Upcoming Releaseheader in the past tense.ChangeLog.mdif no new release is required, such as fixing test case only.