fix(boto3): Fix botocore SigV4 failures caused by post-sign trace propagation - #7050
fix(boto3): Fix botocore SigV4 failures caused by post-sign trace propagation#7050pabloDeputter wants to merge 9 commits into
Conversation
- merge Sentry baggage with existing vendor (e.g. Datadog) baggage in botocore's`before-sign` hook; avoiding post-sign header tampering that invalidates the SigV4 signature. - Skip propagation for presigned requests Fixes: #7031 & PY-2667
Codecov Results 📊✅ 99283 passed | ⏭️ 6494 skipped | Total: 105777 | Pass Rate: 93.86% | Execution Time: 340m 44s 📊 Comparison with Base Branch
➖ Removed Tests (1)View removed tests
All tests are passing successfully. ✅ Patch coverage is 94.81%. Project has 2503 uncovered lines. Files with missing lines (2)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 89.99% 89.99% —%
==========================================
Files 193 193 —
Lines 24946 25016 +70
Branches 9000 9034 +34
==========================================
+ Hits 22451 22513 +62
- Misses 2495 2503 +8
- Partials 1435 1437 +2Generated by Codecov Action |
| return rv | ||
|
|
||
| def endheaders(self: "HTTPConnection", *args: "Any", **kwargs: "Any") -> "Any": | ||
| trace_headers = getattr(self, "_sentrysdk_trace_headers", ()) |
There was a problem hiding this comment.
Does calling sentry_sdk.get_current_scope().iter_trace_propagation_headers() here instead of in putrequest() work?
It would be best to avoid stashing stuff on the HTTPConnection instance if we can help it.
There was a problem hiding this comment.
Good suggestion :) header generation is moved into endheaders() instead of being stored on the connection.
… SigV4 headers Refs: #7031 & PY-2667
| _complete_span(span) | ||
|
|
||
| HTTPConnection.putrequest = putrequest # type: ignore[method-assign] | ||
| HTTPConnection.endheaders = endheaders # type: ignore[method-assign] |
There was a problem hiding this comment.
Eager .format() in endheaders crashes on URLs or header values with braces
The endheaders patch eagerly interpolates user-controlled real_url and header_value with .format(), raising KeyError and aborting the HTTP request when either contains curly braces.
Evidence
- In
sentry_sdk/integrations/stdlib.py, theendheadersfunction (defined at line 211) callslogger.debug("...{real_url}...".format(key=header_name, value=header_value, real_url=real_url))at line 236. real_urlis constructed from theurlargument toputrequest(line 192), which may contain literal braces such as/api/{id}.header_valuecomes fromiter_trace_propagation_headers(line 224) and may include baggage or trace values with braces.- Python evaluates the
.format()eagerly beforelogger.debugis invoked, so aKeyErrorpropagates out of thetryblock even when debug logging is disabled, aborting the HTTP request.
Identified by Warden · code-review · 4DB-4BC
Description
Summary of issue
baggagewas not included inSignedHeaders. Any later modifications to the value did not invalidate the request.before-signevent. It addsbaggage, ... andx-datadog-*before signing. Any later modifications to the value DO invalidate the request, thus later HTTP-client injection is suppressed to avoid duplicate headers.before-signhandler writes the baggage to the AWS requestbaggagein the SigV4 signaturebaggagevalue403 ForbiddenorSignatureDoesNotMatch.Changes
before-signhandler, so finalbaggageandsentry-tracevalues are created before SigV4 signing.http.clientpropagation is delayed untilendheaders(), when the complete request headers and SigV4SignedHeadersare available. Existingbaggageheader is never mutated after it already was signed.Issues
Resolves: #7031 & PY-2667
Reminders
uv run ruff.feat:,fix:,ref:,meta:)