-
Notifications
You must be signed in to change notification settings - Fork 80
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
FIx Request Handling on Requests with Trailing Headers (Mainly in ChunkedContentDecoder
)
#8753
Conversation
Attached printing from the logs as an example: In the headers of the request we can see
We added some printings in the function
The client is using PutObject with body "body for example", it is 16 characters (decimal) in hexadecimal base it is 10.
|
057ec16
to
d7251c3
Compare
a12235c
to
385f83c
Compare
ChunkedContentDecoder
)
141aa75
to
0cae790
Compare
squash? |
…nkedContentDecoder) 1. In http_utils.js accept more types of content sha256 headers (STREAMING-UNSIGNED-PAYLOAD-TRAILER, STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER), as without those headers on clients that add the checksum headers with trailing we would fail. 2. Change the state of the machine and add more states to support the trailing headers: STATE_READ_TRAILER (like we have STATE_READ_CHUNK_HEADER), STATE_WAIT_NL_TRAILER (like we have STATE_WAIT_NL_DATA) and STATE_WAIT_NL_END. 3. Set the following constants to limit the request (avoid the client from abuse): - MAX_CHUNK_SIZE - we want to have a lower number than Number.MAX_SAFE_INTEGER (reference), we expect lower number. - MAX_CHUNK_HEADER_SIZE - we don't expect that long (as it is saved in memory during the parsing). - MAX_TRAILER_SIZE - same, in the example we saw it was about ~30 (x-amz-checksum-crc32:uOMGCw==). - MAX_TRAILERS - currently we saw the trailer of checksum (x-amz-checksum-crc32:uOMGCw==), we expect to have a few trailers in a request. 4. Refactor and organize - add comments with explanations about the state machine, add helper functions, add separation between the parts, rename chunk_header_str to chunk_header, add members related to trailers, add the member this.stream_pos which we use for validation. 5. Improve building the string (either this.chunk_header, and this.trailer) so we won't build it byte by byte, but only after we find the CR ('\r`). 6. Replace buffer slice function with subarray as the function slice was deprecated (see reference). Co-authored-by: Guy Margalit <[email protected]> Signed-off-by: shirady <[email protected]>
3e21106
to
9b5cc89
Compare
---
config:
theme: dark
look: classic
layout: elk
---
flowchart TD
A -- not CR, append string --> A["STATE_READ_CHUNK_HEADER <br> read the chunk header until CR and parse it"]
A -. CR, header parse problem .-> J["STATE_ERROR <br> an error occurred"]
A -- "CR, chunk_size!=0" --> B["STATE_WAIT_NL_HEADER <br> wait for NL after the chunk header"]
A -- "CR, chunk_size==0" --> F["STATE_READ_TRAILER <br> read optional trailer until CR and save it"]
C -- data --> C["STATE_SEND_DATA <br> send chunk data to the stream until chunk size bytes sent"]
C -- done size bytes --> D["STATE_WAIT_CR_DATA <br> wait for CR after the chunk data"]
F -- not CR, append string --> F
F -- CR, keep trailer --> G["STATE_WAIT_NL_TRAILER <br> wait for NL after non empty trailer"]
F -- CR, empty trailer --> H["STATE_WAIT_NL_END <br> wait for NL after the last empty trailer"]
D -- CR --> E["STATE_WAIT_NL_DATA <br> wait for NL after the chunk data"]
H -- NL --> I["STATE_CONTENT_END <br> the stream is done"]
B -- NL --> C
E -- NL --> A
G -- NL --> F
B -. not NL .-> J
E -. not NL .-> J
G -. not NL .-> J
H -. not NL .-> J
D -. not CR .-> J
I -. any .-> J
|
Explain the changes
Background
The
ChunkedContentDecoder
pipes only the actual content from the body (no size, headers, CR NL, trailers, etc.). Although we added the handling for the extension and trailers in the class - we don't use them.http_utils.js
accept more types of content sha256 headers (STREAMING-UNSIGNED-PAYLOAD-TRAILER
,STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER
), as without those headers on clients that add the checksum headers with trailing we would fail.STATE_READ_TRAILER
(like we haveSTATE_READ_CHUNK_HEADER
),STATE_WAIT_NL_TRAILER
(like we haveSTATE_WAIT_NL_DATA
) andSTATE_WAIT_NL_END
.MAX_CHUNK_SIZE
- we want to have a lower number thanNumber.MAX_SAFE_INTEGER
(reference), we expect lower number.MAX_CHUNK_HEADER_SIZE
- we don't expect that long (as it is saved in memory during the parsing).MAX_TRAILER_SIZE
- same, in the example we saw it was about ~30 (x-amz-checksum-crc32:uOMGCw==
).MAX_TRAILERS
- currently we saw the trailer of checksum (x-amz-checksum-crc32:uOMGCw==
), we expect to have a few trailers in a request.chunk_header_str
tochunk_header
, add members related to trailers, add the memberthis.stream_pos
which we use for validation.this.chunk_header
, andthis.trailer
) so we won't build it byte by byte, but only after we find the CR ('\r`).slice
function withsubarray
as the functionslice
was deprecated (see reference).Issues:
List of GAPs:
Testing Instructions:
Unit Tests (automatic)
This tests the behavior of the
ChunkedContentDecoder
to various of inputs and the checks are cut differently.Please notice that it runs in a loop so the random cut of the chunks will be well-covered.
Please run:
npx jest test_chunked_content_decoder.test.js
.End-to-end Test (manual)
Use a client whose version was updated and adds the checksum trailers.
From what I experienced with this test the bucks were the same on every run, but it is not something that is guaranteed (therefore, the unit tests are covering this).
As mentioned in PR noobaa/noobaa-operator#1521, for example:
go run script/client_script.go -bucket fourteen.bucket -key test-key -mpu test-mpu-key -endpoint "https://localhost:12443" -disable-deletion
and expect to see all tests passing: