Skip to content

fix(storage): Azure presigned_url requires account_key even under managed identity - #23

Merged
abhi-bhat-lyzr merged 1 commit into
LYZR-OSS:mainfrom
parshva-lyzr:fix/azure-presigned-url-managed-identity
Aug 4, 2026
Merged

fix(storage): Azure presigned_url requires account_key even under managed identity#23
abhi-bhat-lyzr merged 1 commit into
LYZR-OSS:mainfrom
parshva-lyzr:fix/azure-presigned-url-managed-identity

Conversation

@parshva-lyzr

Copy link
Copy Markdown
Contributor

Problem

AzureBlobBackend.presigned_url() unconditionally requires self._account_key
and raises otherwise:

presigned_url requires account_key authentication. Use from_connection_string
or from_account_key.

Any backend built via from_managed_identity() or from_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-service on Azure,
configured with AZURE_STORAGE_ACCOUNT_URL only (managed identity, per
feat/azure-managed-identity). Every file upload: blob PUT succeeds
(201), then the immediate post-upload presigned_url() call raises this
error, so the whole upload is reported as success: false to the caller.

Fix

presigned_url() now falls back to a user delegation SAS
(BlobServiceClient.get_user_delegation_key()) when an AAD credential is
present 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 the
documented 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's
test 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 check clean.

Downstream

lyzr-agent and rag both pin lyzr-cloudrift by exact version and hit
this 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.z commit).

…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
parshva-lyzr force-pushed the fix/azure-presigned-url-managed-identity branch from 2e62c57 to 4c80402 Compare August 4, 2026 07:25
@sonarqubecloud

sonarqubecloud Bot commented Aug 4, 2026

Copy link
Copy Markdown

@abhi-bhat-lyzr
abhi-bhat-lyzr merged commit 5363044 into LYZR-OSS:main Aug 4, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants