feat: add Azure Blob Storage channel support - #2654
Open
wolfv wants to merge 106 commits into
Open
Conversation
* feat(rattler_index): add Azure Blob backend * fix(rattler_index): disable preconditions on azure (opendal azblob lacks conditional writes) * fix(rattler_index): re-index packages whose blob size changed
* fix(rattler_index): re-index packages whose blob size changed * fix: move to md5 checks instead of size * feat(rattler_index): add Azure Blob backend * fix(rattler_index): disable preconditions on azure (opendal azblob lacks conditional writes) * fix(rattler_index): base64-decode backend md5 before comparing * test(rattler_index): probe azure content_md5 on list * chore: lint
…channel # Conflicts: # Cargo.lock
# Conflicts: # Cargo.lock # Cargo.toml # crates/rattler-bin/src/commands/client.rs # py-rattler/Cargo.lock
Contributor
|
Details |
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.
Note
This supersedes #2615 so the changes can be merged and released directly from a maintainer-owned branch. It includes the latest
mainand resolves the original PR's merge conflicts.Description
Adds Azure Blob Storage as a first-class conda channel backend across rattler,
addressed through
az://URLs — the Azure counterpart to the existing S3 (s3://)and GCS support. Channels hosted in a blob container can be fetched, solved,
indexed, and uploaded to with no separate endpoint/config block.
Closes #2285.
URL model
A channel is addressed by its full blob host:
The account, endpoint, container and root prefix are all derived from the URL, so
the channel is spelled the same way it appears on the wire. Sovereign clouds and
the Azurite emulator work automatically because the endpoint lives in the host —
no allow-list of accounts or endpoints is baked in.
What's included
rattler_azure(new crate):az://URL parsing into typedAzureCoordinates { account, container },AzureCredentials(account key / SAS token), and optional
az login→ short-liveduser-delegation SAS minting for write paths (behind the
clapfeature).rattler_networking:AzureMiddleware— rewritesaz://→https://(a plain scheme swap) and signs via reqsign's
DefaultCredentialProviderchain (env vars → workload/managed identity →
az login). Public/anonymouscontainers work with zero credentials; a configured-but-broken credential is
a hard error rather than a silent anonymous downgrade.
rattler_repodata_gateway: accepts theaz://channel scheme for(sharded) repodata fetch.
rattler_index:azblobindexing backend (opendal), CLI subcommand.rattler_upload:az://upload path with concurrent block upload.rattler-bin: registersAzureMiddlewarebehind anazurefeature.py-rattler:AzureMiddlewarebinding, included in the default client stack.Authentication
--account-key/AZURE_STORAGE_KEY--sas-token/AZURE_STORAGE_SAS_TOKENaz login--azure-climints a short-lived user-delegation SAS (write paths)az loginSecurity / trust model
The URL host is trusted verbatim and becomes the request target, so
az://userinfo is rejected. This is a pure safety gate that removes no
functionality: Azure Blob has no
user:pass@auth mode — credentials come fromShared Key headers, SAS query strings, or AAD bearer tokens, and the storage
account is the host's first label (
account.blob.core.windows.net), neveruserinfo. So userinfo in an
az://URL can do exactly one thing: hide the realhost —
az://trusted.blob.core.windows.net@attacker.example/…targetsattacker.example. Rejecting it closes that host-spoofing vector while leavingevery legitimate URL untouched. (Scoped to
az://;https://channels thatlegitimately use Basic-auth userinfo are unaffected.)
On Windows the Azure CLI is resolved via
whichand invoked directly rather thanthrough
cmd /C, avoiding a metacharacter-injection surface.Known limitations (documented in-code)
if_not_existsonly on the single-shotPut Blob path (≤ 10 MiB), not the multi-block path used for larger packages,
so the upload overwrite guard does an explicit pre-write
statto cover allsizes (with a small, documented stat→write TOCTOU window).
not prefix-scoped; a short TTL bounds the blast radius.
How Has This Been Tested?
rattler_azure,rattler_networking(URL rewrite, userinforejection, credential-source detection, unsigned fallback, SAS pass-through),
and
rattler_upload.az loginAAD fetch) against a real account.py-rattler: unit test assertingAzureMiddlewareis in the default client stack.cargo build,cargo clippy -D warnings,cargo fmt, andcargo nextestall green.serves conda packages from an Azure Blob-hosted channel.
AI Disclosure
Tools: Claude Code (Claude Opus 4.8)
Checklist:
Additional validation after updating to current
maincargo fmt --all -- --checkcargo checkwith CI featurescargo check --manifest-path py-rattler/Cargo.tomlcargo clippy --all-targets --workspace -- -D warnings -Dclippy::dbg_macroPrompt added for this replacement PR