fix(storage): Azure presigned_url requires account_key even under managed identity - #23
Merged
abhi-bhat-lyzr merged 1 commit intoAug 4, 2026
Conversation
…aged identity; release v0.2.11 AzureBlobBackend.presigned_url() unconditionally required a raw account key to sign a SAS, so any backend authenticated via from_managed_identity()/from_service_principal() (AAD credential, no account key) always raised: presigned_url requires account_key authentication. Use from_connection_string or from_account_key. Blob reads/writes work fine over AAD, but local SAS signing needs either the account key or a short-lived user delegation key obtained via BlobServiceClient.get_user_delegation_key(). Fall back to the latter when an AAD credential is present and no account key was supplied. No new Azure RBAC required: Storage Blob Data Contributor (already the documented role for managed-identity blob access) includes Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey. Adds unit tests for all three presigned_url auth paths (account_key, AAD/managed-identity via delegation key, no-credential error). Also adds azure-storage-blob to the dev extra — CI (uv sync --extra dev) never installed it, so cloudrift.storage.azure_blob was never importable in the test job; the new test module surfaced this. Bumps version 0.2.10 -> 0.2.11: 0.2.10 is already published on PyPI, so this must sort above it for downstream >=0.2.x pins to pick up the fix by default.
parshva-lyzr
force-pushed
the
fix/azure-presigned-url-managed-identity
branch
from
August 4, 2026 07:25
2e62c57 to
4c80402
Compare
|
abhi-bhat-lyzr
approved these changes
Aug 4, 2026
abhi-bhat-lyzr
approved these changes
Aug 4, 2026
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.



Problem
AzureBlobBackend.presigned_url()unconditionally requiresself._account_keyand raises otherwise:
Any backend built via
from_managed_identity()orfrom_service_principal()(AAD credential, no raw account key) hits this on every call — blob
read/write works fine over AAD, but SAS signing does not fall back to it.
Reproduced end-to-end in production:
studio-lyzr-agent-serviceon Azure,configured with
AZURE_STORAGE_ACCOUNT_URLonly (managed identity, perfeat/azure-managed-identity). Every file upload: blobPUTsucceeds(
201), then the immediate post-uploadpresigned_url()call raises thiserror, so the whole upload is reported as
success: falseto the caller.Fix
presigned_url()now falls back to a user delegation SAS(
BlobServiceClient.get_user_delegation_key()) when an AAD credential ispresent and no account key was supplied — the standard way to mint a SAS
URL under Azure AD auth.
No new Azure RBAC needed:
Storage Blob Data Contributor— already thedocumented role for managed-identity blob access — includes
Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey.Tests
Added
tests/test_storage_azure_blob.py(mocked — no Azurite in this repo'stest setup) covering all three auth paths: account_key, AAD via delegation
key, and the no-credential error. Full suite:
277 passed, 1 skipped(pre-existing skip, unrelated).
ruff checkclean.Downstream
lyzr-agentandragboth pinlyzr-cloudriftby exact version and hitthis in production when configured for Azure managed identity. Follow-up
PRs there bump the pin once this is released (next version after 0.2.10 —
pyproject.toml version left unbumped here per this repo's convention of a
separate
chore(release): x.y.zcommit).