[ 
https://issues.apache.org/jira/browse/HDDS-17480?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Chung-En Lee updated HDDS-17480:
--------------------------------
    Description: 
In FSO buckets, a PutObject to a key ending with "/" that has no Content-Length 
header is treated as directory creation, even when x-amz-decoded-content-length 
is non-zero. S3 Gateway returns 200, creates a directory and silently discards 
the payload.

aws-cli sends exactly this request when it talks to S3 Gateway over HTTPS. It 
uses STREAMING-UNSIGNED-PAYLOAD-TRAILER with Transfer-Encoding: chunked and 
removes the Content-Length header.

h3. Environment
* S3 Gateway serving HTTPS: ozone.http.policy=HTTPS\_ONLY, with the keystore 
configured in ssl-server.xml (ssl.server.keystore.location, 
ssl.server.keystore.password, ssl.server.keystore.keypassword, 
ssl.server.keystore.type).
* ozone.s3g.fso.directory.creation=true (default).

h3. Steps to reproduce
# Create an FSO bucket:
{code}ozone sh bucket create /s3v/fsobucket --layout FILE_SYSTEM_OPTIMIZED
{code}
# Upload 5 bytes to a key ending with "/" over HTTPS:
{code}printf 'hello' > 5bytes.txt
aws --endpoint-url https://<s3g-host>:9879 --no-verify-ssl s3api put-object 
--bucket fsobucket --key dir1/ --body 5bytes.txt
{code}
# Read the object back and list the bucket:
{code}aws --endpoint-url https://<s3g-host>:9879 --no-verify-ssl s3api 
get-object --bucket fsobucket --key dir1/ out.txt
ozone fs -ls ofs://om/s3v/fsobucket/
{code}

Request headers sent by aws-cli in step 2 (from --debug). There is no 
Content-Length header:
{code}Transfer-Encoding: chunked
Content-Encoding: aws-chunked
X-Amz-Content-SHA256: STREAMING-UNSIGNED-PAYLOAD-TRAILER
X-Amz-Decoded-Content-Length: 5
X-Amz-Trailer: x-amz-checksum-crc64nvme
{code}

h3. Expected
The payload is not silently lost: either it is stored, or the request fails 
with an error.

h3. Actual
* put-object returns 200.
* get-object returns ContentLength 0.
* dir1 is a directory and the 5 bytes are gone:
{code}drwxrwxrwx   - testuser hadoop          0 2026-10-26 10:03 
ofs://om/s3v/fsobucket/dir1
{code}


  was:
In FSO buckets, a PutObject to a key ending with "/" that has no Content-Length 
header is treated as directory creation, even when x-amz-decoded-content-length 
is non-zero. S3 Gateway returns 200, creates a directory and silently discards 
the payload.

aws-cli sends exactly this request when it talks to S3 Gateway over HTTPS. It 
uses STREAMING-UNSIGNED-PAYLOAD-TRAILER with Transfer-Encoding: chunked and 
removes the Content-Length header.

h3. Environment
* Ozone 2.2.1 (apache/ozone:2.2.1 docker image), non-secure cluster. master has 
the same code.
* S3 Gateway serving HTTPS: ozone.http.policy=HTTPS\_ONLY, with the keystore 
configured in ssl-server.xml (ssl.server.keystore.location, 
ssl.server.keystore.password, ssl.server.keystore.keypassword, 
ssl.server.keystore.type).
* ozone.s3g.fso.directory.creation=true (default).
* aws-cli 2.38.1.

h3. Steps to reproduce
# Create an FSO bucket:
{code}ozone sh bucket create /s3v/fsobucket --layout FILE_SYSTEM_OPTIMIZED
{code}
# Upload 5 bytes to a key ending with "/" over HTTPS:
{code}printf 'hello' > 5bytes.txt
aws --endpoint-url https://<s3g-host>:9879 --no-verify-ssl s3api put-object 
--bucket fsobucket --key dir1/ --body 5bytes.txt
{code}
# Read the object back and list the bucket:
{code}aws --endpoint-url https://<s3g-host>:9879 --no-verify-ssl s3api 
get-object --bucket fsobucket --key dir1/ out.txt
ozone fs -ls ofs://om/s3v/fsobucket/
{code}

Request headers sent by aws-cli in step 2 (from --debug). There is no 
Content-Length header:
{code}Transfer-Encoding: chunked
Content-Encoding: aws-chunked
X-Amz-Content-SHA256: STREAMING-UNSIGNED-PAYLOAD-TRAILER
X-Amz-Decoded-Content-Length: 5
X-Amz-Trailer: x-amz-checksum-crc64nvme
{code}

h3. Expected
The payload is not silently lost: either it is stored, or the request fails 
with an error.

h3. Actual
* put-object returns 200.
* get-object returns ContentLength 0.
* dir1 is a directory and the 5 bytes are gone:
{code}drwxrwxrwx   - testuser hadoop          0 2026-10-26 10:03 
ofs://om/s3v/fsobucket/dir1
{code}

h3. Control
The same upload with a precomputed checksum makes aws-cli send Content-Length: 
5 without a trailer. In that case the data is stored, as a 5-byte file named 
dir2:
{code}aws --endpoint-url https://<s3g-host>:9879 --no-verify-ssl s3api 
put-object --bucket fsobucket --key dir2/ --body 5bytes.txt --checksum-crc32 
NhCmhg==
{code}
{code}-rw-rw-rw-   1 testuser hadoop          5 2026-10-26 10:03 
ofs://om/s3v/fsobucket/dir2
{code}



> PutObject to a trailing-slash key without Content-Length creates a directory 
> and discards the payload
> -----------------------------------------------------------------------------------------------------
>
>                 Key: HDDS-17480
>                 URL: https://issues.apache.org/jira/browse/HDDS-17480
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Chung-En Lee
>            Priority: Major
>
> In FSO buckets, a PutObject to a key ending with "/" that has no 
> Content-Length header is treated as directory creation, even when 
> x-amz-decoded-content-length is non-zero. S3 Gateway returns 200, creates a 
> directory and silently discards the payload.
> aws-cli sends exactly this request when it talks to S3 Gateway over HTTPS. It 
> uses STREAMING-UNSIGNED-PAYLOAD-TRAILER with Transfer-Encoding: chunked and 
> removes the Content-Length header.
> h3. Environment
> * S3 Gateway serving HTTPS: ozone.http.policy=HTTPS\_ONLY, with the keystore 
> configured in ssl-server.xml (ssl.server.keystore.location, 
> ssl.server.keystore.password, ssl.server.keystore.keypassword, 
> ssl.server.keystore.type).
> * ozone.s3g.fso.directory.creation=true (default).
> h3. Steps to reproduce
> # Create an FSO bucket:
> {code}ozone sh bucket create /s3v/fsobucket --layout FILE_SYSTEM_OPTIMIZED
> {code}
> # Upload 5 bytes to a key ending with "/" over HTTPS:
> {code}printf 'hello' > 5bytes.txt
> aws --endpoint-url https://<s3g-host>:9879 --no-verify-ssl s3api put-object 
> --bucket fsobucket --key dir1/ --body 5bytes.txt
> {code}
> # Read the object back and list the bucket:
> {code}aws --endpoint-url https://<s3g-host>:9879 --no-verify-ssl s3api 
> get-object --bucket fsobucket --key dir1/ out.txt
> ozone fs -ls ofs://om/s3v/fsobucket/
> {code}
> Request headers sent by aws-cli in step 2 (from --debug). There is no 
> Content-Length header:
> {code}Transfer-Encoding: chunked
> Content-Encoding: aws-chunked
> X-Amz-Content-SHA256: STREAMING-UNSIGNED-PAYLOAD-TRAILER
> X-Amz-Decoded-Content-Length: 5
> X-Amz-Trailer: x-amz-checksum-crc64nvme
> {code}
> h3. Expected
> The payload is not silently lost: either it is stored, or the request fails 
> with an error.
> h3. Actual
> * put-object returns 200.
> * get-object returns ContentLength 0.
> * dir1 is a directory and the 5 bytes are gone:
> {code}drwxrwxrwx   - testuser hadoop          0 2026-10-26 10:03 
> ofs://om/s3v/fsobucket/dir1
> {code}



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to