-
Notifications
You must be signed in to change notification settings - Fork 321
cosmos: Fix URL encoding for authentication signatures #3461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cosmos: Fix URL encoding for authentication signatures #3461
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes URL encoding issues in Cosmos DB authentication signatures. The core problem was that paths were URL-encoded before signing requests, but the Cosmos DB API expects unencoded paths in signatures. This caused authentication failures when resource IDs contained URL-unsafe characters like +, @, or /.
Key changes:
- Introduced
LinkSegmentto store both encoded and unencoded forms of path segments - Added
item_by_rid()method for RID-based links that should not be encoded - Renamed
resource_link()tolink_for_signing()to clarify its purpose - Added comprehensive tests for URL encoding edge cases
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| sdk/cosmos/azure_data_cosmos/src/resource_context.rs | Core fix: Added LinkSegment struct to store both encoded/unencoded path forms; separated path() (encoded) from link_for_signing() (unencoded); added item_by_rid() for RIDs that shouldn't be encoded |
| sdk/cosmos/azure_data_cosmos/src/pipeline/signature_target.rs | Updated to use link_for_signing() instead of resource_link(); added test for RID-based links |
| sdk/cosmos/azure_data_cosmos/src/pipeline/mod.rs | Changed offers API to use item_by_rid() instead of item() since offer IDs are RIDs |
| sdk/cosmos/azure_data_cosmos/src/models/throughput_properties.rs | Made offer_id field public to support RID-based link construction |
| sdk/cosmos/azure_data_cosmos/tests/cosmos_offers.rs | New test file for throughput CRUD operations on databases and containers; moved from cosmos_containers.rs |
| sdk/cosmos/azure_data_cosmos/tests/cosmos_items.rs | Added test coverage for IDs with @ character to verify URL-unsafe characters work correctly |
| sdk/cosmos/azure_data_cosmos/tests/cosmos_containers.rs | Removed autoscale throughput test (moved to cosmos_offers.rs) |
| Cargo.lock | Unrelated changes to azure_storage_blob_test dependencies |
API Change CheckAPIView identified API level changes in this PR and created the following API reviews |
tvaron3
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
Addresses #2994 |
This PR fixes two bugs, with the same root cause: We URL encode paths before signing the request, but we should not be doing that.
+, because we encode itread_item,delete_itemreturnsUnauthorizedfor item IDs containing special characters such as@#3394 - Whenever an ID has a URL-unsafe character in it, we produce an invalid resource link for signing and the user gets a 401This PR fixes both by storing both the unencoded and encoded form of path segments in the
ResourceLink, which get preserved as links are combined (to create sub-clients). In some SDKs, we "unencode" the string before generating the signature payload, but that's challenging because the current URL encoding library we're using (form_urlencoded) doesn't actually support decoding. We can improve this later, for now I just want to get something that fixes the immediate issue.We don't have direct APIs for managing offers, so the easiest way to end-to-end test this was to produce a test that kept trying to create a database until it got one with an offer RID containing
+. I did that, saw it fail, fixed this issue, and it passed. Since that test is inherently inconsistent, I haven't actually included it.Closes #3394