Skip to content

rgw/admin: fold User.Tenant into the uid on get/modify/remove - #1324

Draft
jhoblitt wants to merge 1 commit into
ceph:masterfrom
jhoblitt:wip-rgw-admin-user-tenant-uid
Draft

rgw/admin: fold User.Tenant into the uid on get/modify/remove#1324
jhoblitt wants to merge 1 commit into
ceph:masterfrom
jhoblitt:wip-rgw-admin-user-tenant-uid

Conversation

@jhoblitt

@jhoblitt jhoblitt commented Aug 24, 2026

Copy link
Copy Markdown
Member

Problem

admin.User.Tenant appears only in CreateUser's URL-parameter whitelist. On GetUser, ModifyUser and RemoveUser a populated Tenant is silently dropped and the call addresses the bare uid — the same-named user in the empty tenant. RGW resolves tenancy through the combined uid on every operation, and the Admin Ops documentation declares the two spellings equivalent where the parameter exists: "A tenant may either be specified as a part of uid or as an additional request param" (doc/radosgw/adminops.rst, Create User).

Fixes #1323
Related: #1307 (empty values are never transmitted — a different gap in the same encoder; not addressed here)

Change

GetUser/ModifyUser/RemoveUser now fold a populated Tenant into the uid before encoding:

  • ID without $ → sends uid = Tenant + "$" + ID
  • ID already tenant$uid with the same tenant → unchanged
  • ID already tenanted with a different tenant → error
  • Tenant set with empty ID (GetUser lookup by access key) → error

CreateUser is untouched. No signatures change and no new exported symbols are added; the only affected calls are ones that today silently operate on the wrong user — behavior no correct program can rely on.

Testing

Local, no cluster (librados headers are not installed here; -tags nautilus excludes the one rgw/admin test file that imports rados):

  • go build ./rgw/... — ok
  • go vet -tags nautilus ./rgw/admin/ — ok
  • go test -tags nautilus ./rgw/admin/ -skip TestRadosGWTestSuite -v — PASS (all mock/unit tests, including the new TestUserWithTenantUID, TestGetUserTenantMockAPI, TestModifyUserTenantMockAPI, TestRemoveUserTenantMockAPI)
  • revive -config .revive.toml ./rgw/admin/... (v1.7.0) — clean
  • gofmt -l rgw/ — clean

The RadosGWTestSuite integration tests need a live cluster and were not run locally.

Server-side counterpart: https://tracker.ceph.com/issues/79816 proposes RGW itself accept the tenant parameter on user info/modify/remove (implementation in ceph/ceph#71301). That change and this one are independent — the combined-uid fold here works against all existing RGW releases.

AI assistance: this change was drafted by an AI agent under my direction and review.

The Tenant field is only in CreateUser's URL-parameter whitelist, so
GetUser, ModifyUser and RemoveUser silently drop a populated Tenant and
address the bare uid: the same-named user in the empty tenant. RGW
resolves tenancy through the combined "tenant$uid" form on every
operation, and the Admin Ops API documents the two spellings as
equivalent.

Fold a populated Tenant into the uid before encoding on those three
calls:

- a bare ID becomes "tenant$id"
- an ID already carrying the same tenant is unchanged
- an ID carrying a different tenant is an error
- a Tenant with no ID (GetUser lookup by access key) is an error

No signatures change, and the only affected calls are ones that today
silently operate on the wrong user, which no correct program can rely
on.

Fixes: ceph#1323
Signed-off-by: Joshua Hoblitt <josh@hoblitt.com>

@anoopcs9 anoopcs9 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm, thanks.

Some nits:

  • withTenantUID() only splits on the first $, so it doesn't handle the three-part tenant$ns$id namespace form - harmless here since struct admin.User has no namespace concept, but a comment noting ID is expected to be bare or "tenant$id" would make the scope explicit.
  • The Tenant field comment restates the fold rules that also live on the withTenantUID() doc. The in-struct comment itself is fine but you could trim the overlap - leaving the "what" on the field and the "how" on the method - to avoid documenting the behavior in two places.

Besides all these, is there any reason to not take this out of Draft status?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rgw/admin: User.Tenant is silently dropped by GetUser/ModifyUser/RemoveUser (operates on the wrong user)

2 participants