Skip to content

HDDS-17361. S3 Gateway can set another user as the owner of a new key - #11707

Merged
ivandika3 merged 2 commits into
apache:masterfrom
peterxcli:HDDS-17361
Oct 25, 2026
Merged

ivandika3 merged 2 commits into
apache:masterfrom
peterxcli:HDDS-17361

Conversation

@peterxcli

@peterxcli peterxcli commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

What changes were proposed in this pull request?

Background

The S3 Gateway serves all users with one RpcClient. Each request thread sets its own S3Auth as a thread-local, and RpcClient uses that S3 user as the owner of new keys, files, directories and multipart uploads.

Problem

RpcClient#setThreadLocalS3Auth also stores the user in the field s3gUgi, which HDDS-7791 added. All request threads share this field, and getRealUserInfo() returns it whenever the calling thread has an S3Auth. OM stores the owner that the client sends.

Take two users, Alice and Bob, on the same S3 Gateway. Alice uploads an object. While the gateway handles the upload, Bob sends any request, for example ListObjects. Bob's request overwrites s3gUgi, so Alice's new key is stored with Bob as its owner. ListObjects, ozone sh key info and ofs then show Bob as the owner of Alice's key.

In a stress run on current master with one S3 Gateway, two users write from 8 threads each and a third user only lists objects. 330 of the 960 new keys get the wrong owner, and 236 of them get the user who only lists.

Access checks don't use the key owner, so this doesn't change who can read or write a key.

Changes

  • Remove the shared field s3gUgi.
  • getRealUserInfo() creates the UserGroupInformation from the S3Auth of the calling thread. createBucket() and getDEK() already do the same.
  • setThreadLocalS3Auth() no longer creates a UserGroupInformation. It used to do that once or twice for every S3 request. Now one is created only when a write needs the owner.

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/HDDS-17361

How was this patch tested?

New unit test TestRpcClient#testKeyOwnerComesFromS3AuthOfCallingThread. One thread sets the S3Auth of alice, a second thread then sets the S3Auth of bob, and the first thread creates a key. The test checks that the CreateKey request carries alice as the owner. Without the fix, it fails with expected: <[alice]> but was: <[bob]>.

S3 Gateway shares one RpcClient between all request threads. RpcClient
kept the S3 user of the latest request in the shared field s3gUgi, and
getRealUserInfo() returned it as the owner for new keys, files,
directories and multipart uploads. A concurrent request from another
user could therefore change the owner of a key.

Create the UserGroupInformation from the thread-local S3Auth when it is
needed instead, as createBucket() and getDEK() already do.
Copilot AI balanced review requested due to automatic review settings October 23, 2026 01:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@smengcl smengcl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @peterxcli

@ivandika3 ivandika3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@peterxcli Thanks for the fix. Is it possible to make s3gUgi to be ThreadLocal instead? The argument of the review #4188 (comment) is that UGI creation is wasteful.

public void setThreadLocalS3Auth(
S3Auth ozoneSharedSecretAuth) {
ozoneManagerClient.setThreadLocalS3Auth(ozoneSharedSecretAuth);
this.s3gUgi = UserGroupInformation.createRemoteUser(getThreadLocalS3Auth().getUserPrincipal());

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

this removal actually help to reduce ugi creation, as GET, HEAD, list and delete request dont call getRealUserInfo()

@peterxcli
peterxcli requested a review from ivandika3 October 24, 2026 18:48
@peterxcli
peterxcli marked this pull request as ready for review October 24, 2026 18:48

@ivandika3 ivandika3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @peterxcli , LGTM +1.

@ivandika3
ivandika3 merged commit 3139098 into apache:master Oct 25, 2026
73 checks passed
@peterxcli
peterxcli deleted the HDDS-17361 branch October 25, 2026 04:11
@peterxcli

Copy link
Copy Markdown
Member Author

Thanks @ivandika3 @smengcl!

errose28 added a commit to errose28/ozone that referenced this pull request Oct 27, 2026
* master: (114 commits)
  HDDS-17411. Show one initialization notice on the Namespace Usage page (apache#11737)
  HDDS-17375. Create new submodule ozone-integration-test-tools (apache#11754)
  HDDS-17452. Introduce ClientProtocol delegation for S3 Gateway (apache#11757)
  HDDS-16661. Validate unsigned S3 checksum trailer completion and framing (apache#11586)
  HDDS-17450. Speed up TestDirectoryDeletingService (apache#11765)
  HDDS-17308. ListObjectsV2 Incorrectly Filters CommonPrefixes When StartAfter Is Before the Matching Prefixes (apache#11715).
  Clamp Echo sleep time and response payload size. (apache#44)
  HDDS-17433. Add a freon command for positioned reads on shared input streams (apache#11741)
  HDDS-17239. Initialize usage counters on bucket create (apache#11742)
  HDDS-17357. Initialize Netty in background when Ozone client is created (apache#11726)
  HDDS-17426. Disable ozone.tracing.client.application-aware in acceptance tests (apache#11758)
  HDDS-16737. Share OM follower read logic between the Hadoop RPC and gRPC clients (apache#11418)
  HDDS-17446. Copy datanode container set in NodeStateMap.updateNode only once (apache#11746)
  HDDS-17454. Bump asm to 9.11.1 (apache#11750)
  HDDS-17453. Bump jackson to 2.21.8 (apache#11749)
  HDDS-17376. Scale repeated-defrag footprint tolerance with the number of OM tables (apache#11708)
  HDDS-17380. Fix deadlock when BackgroundContainerDataScanner shutdown during volume failure (apache#11729)
  HDDS-17251. List open multipart uploads in ListOpenFiles (apache#11739)
  HDDS-17361. S3 Gateway can set another user as the owner of a new key (apache#11707)
  HDDS-17238. Initialize refCount and usedNamespace on volume create (apache#11720)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants