Skip to content

Fix SigV4 auth failure due to missing req.GetBody on ES/OS writes#8308

Merged
yurishkuro merged 7 commits into
jaegertracing:mainfrom
dd-tone:fix-sigv4-getbody-roundtripper
Apr 14, 2026
Merged

Fix SigV4 auth failure due to missing req.GetBody on ES/OS writes#8308
yurishkuro merged 7 commits into
jaegertracing:mainfrom
dd-tone:fix-sigv4-getbody-roundtripper

Conversation

@dd-tone
Copy link
Copy Markdown
Contributor

@dd-tone dd-tone commented Apr 7, 2026

Which problem is this PR solving?

Resolves #8307

When using the sigv4auth extension with an OpenSearch backend, all PUT/POST requests (bulk writes, template creation) fail with HTTP 403 Forbidden and the AWS error message:

The request signature we calculated does not match the signature you provided.

This affects any deployment using SigV4 authentication with Elasticsearch or OpenSearch.

Description of the changes

Root cause: The olivere/elastic v7 client creates HTTP requests with http.NewRequest(method, url, nil) and then sets req.Body directly via setBodyReader(), without ever setting req.GetBody. The OTel sigv4auth extension's hashPayload function calls req.GetBody to read the payload for SigV4 signing. When GetBody is nil, it falls back to hashing an empty body (e3b0c44...), causing a signature mismatch on every request that carries a body.

Fix: Introduce a getBodyFixRoundTripper middleware that wraps the base http.RoundTripper and ensures req.GetBody is populated whenever req.Body is set but GetBody is nil. The middleware is inserted in GetHTTPRoundTripper() immediately before the httpAuth.RoundTripper() call, so the authenticator always sees a properly populated GetBody.

The middleware:

  • Reads req.Body into a byte buffer
  • Replaces req.Body with a new reader over the buffer
  • Sets req.GetBody to return a fresh reader over the same buffer
  • Is a no-op when GetBody is already set or Body is nil

How was this change tested?

  • make fmt -- passed
  • make lint -- 0 issues
  • make test -- all package tests pass, including 3 new unit tests:
    • TestGetBodyFixRoundTripper_SetsGetBody -- Body set, GetBody nil: verifies GetBody is populated and returns correct bytes
    • TestGetBodyFixRoundTripper_PreservesExistingGetBody -- Body and GetBody both set: verifies existing GetBody is not overwritten
    • TestGetBodyFixRoundTripper_NilBody -- Body nil: verifies no-op passthrough
  • Validated against live AWS OpenSearch with SigV4 authentication on a production-like EKS cluster. The patched binary started cleanly with zero 403 errors and zero restarts, compared to 51+ restarts on the unpatched version.

Checklist

AI Usage in this PR (choose one)

See AI Usage Policy.

  • None: No AI tools were used in creating this PR
  • Light: AI provided minor assistance (formatting, simple suggestions)
  • Moderate: AI helped with code generation or debugging specific parts
  • Heavy: AI generated most or all of the code changes

Made with Cursor

@dd-tone dd-tone requested a review from a team as a code owner April 7, 2026 03:51
Copilot AI review requested due to automatic review settings April 7, 2026 03:51
Signed-off-by: Anthony Marchante <anthony.marchante@doordash.com>
Made-with: Cursor
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 pull request fixes a SigV4 authentication failure issue that affects all PUT/POST requests (bulk writes, template creation) when using the sigv4auth extension with Elasticsearch/OpenSearch backends. The root cause is that the olivere/elastic v7 client sets req.Body directly without setting req.GetBody, which breaks HTTP authenticators that rely on GetBody to hash the request payload for signing.

Changes:

  • Introduce a getBodyFixRoundTripper middleware that populates req.GetBody whenever req.Body is set but GetBody is nil, ensuring authenticators see properly populated GetBody fields
  • The middleware reads the body into a buffer and replaces both req.Body and sets req.GetBody to return fresh readers over that buffer
  • Insert the middleware in GetHTTPRoundTripper() immediately before the authenticator wrapping, so it sits between the base transport and the authenticator
  • Add three comprehensive unit tests covering all cases: body set with GetBody nil, preserving existing GetBody, and nil body (no-op)

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
internal/storage/elasticsearch/config/config.go Added getBodyFixRoundTripper middleware type with RoundTrip method and integrated it into the GetHTTPRoundTripper function
internal/storage/elasticsearch/config/config_test.go Added three new unit tests for the middleware and a helper recordingRoundTripper for testing

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings April 9, 2026 17:18
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.84%. Comparing base (6e7606e) to head (9a47f0f).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8308      +/-   ##
==========================================
+ Coverage   95.80%   95.84%   +0.03%     
==========================================
  Files         319      319              
  Lines       16819    16829      +10     
==========================================
+ Hits        16114    16130      +16     
+ Misses        549      545       -4     
+ Partials      156      154       -2     
Flag Coverage Δ
badger_direct 9.21% <0.00%> (-0.02%) ⬇️
badger_e2e 1.06% <0.00%> (-0.01%) ⬇️
cassandra-4.x-direct-manual 13.50% <0.00%> (-0.02%) ⬇️
cassandra-4.x-e2e-auto 1.05% <0.00%> (-0.01%) ⬇️
cassandra-4.x-e2e-manual 1.05% <0.00%> (-0.01%) ⬇️
cassandra-5.x-direct-manual 13.50% <0.00%> (-0.02%) ⬇️
cassandra-5.x-e2e-auto 1.05% <0.00%> (-0.01%) ⬇️
cassandra-5.x-e2e-manual 1.05% <0.00%> (-0.01%) ⬇️
clickhouse 1.19% <0.00%> (-0.01%) ⬇️
elasticsearch-6.x-direct 17.36% <0.00%> (+0.02%) ⬆️
elasticsearch-7.x-direct 17.40% <0.00%> (+0.02%) ⬆️
elasticsearch-8.x-direct 17.55% <0.00%> (+0.02%) ⬆️
elasticsearch-8.x-e2e 1.06% <0.00%> (-0.01%) ⬇️
elasticsearch-9.x-e2e 1.06% <0.00%> (-0.01%) ⬇️
grpc_direct 8.01% <0.00%> (-0.01%) ⬇️
grpc_e2e 1.06% <0.00%> (-0.01%) ⬇️
kafka-3.x-v2 1.06% <0.00%> (-0.01%) ⬇️
memory_v2 1.06% <0.00%> (-0.01%) ⬇️
opensearch-1.x-direct 17.44% <0.00%> (+0.02%) ⬆️
opensearch-2.x-direct 17.44% <0.00%> (+0.02%) ⬆️
opensearch-2.x-e2e 1.06% <0.00%> (-0.01%) ⬇️
opensearch-3.x-e2e 1.06% <0.00%> (-0.01%) ⬇️
query 1.06% <0.00%> (-0.01%) ⬇️
tailsampling-processor 0.53% <0.00%> (-0.01%) ⬇️
unittests 94.52% <100.00%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

func (t *getBodyFixRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
if req.Body != nil && req.GetBody == nil {
body, err := io.ReadAll(req.Body)
if err != nil {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a test for this branch?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yurishkuro Added a test for the io.ReadAll error branch, all of the middleware cases are covered now.

auto-merge was automatically disabled April 13, 2026 20:09

Head branch was pushed to by a user without write access

Signed-off-by: dd-tone <anthony.marchante@doordash.com>
Made-with: Cursor
@dd-tone dd-tone force-pushed the fix-sigv4-getbody-roundtripper branch from a868fe9 to e312793 Compare April 13, 2026 20:12
@yurishkuro yurishkuro enabled auto-merge April 13, 2026 23:36
@yurishkuro yurishkuro added this pull request to the merge queue Apr 14, 2026
Merged via the queue into jaegertracing:main with commit c55c9c5 Apr 14, 2026
69 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: SigV4 authentication fails with 403 on all requests with bodies (bulk writes, template creation) against AWS Managed OpenSearch

3 participants