Skip to content

feat!: issue access keys as admin via targetUser - #3

Merged
CoderYellow merged 2 commits into
masterfrom
feat/target-user-access-keys
Sep 4, 2026
Merged

feat!: issue access keys as admin via targetUser#3
CoderYellow merged 2 commits into
masterfrom
feat/target-user-access-keys

Conversation

@CoderYellow

Copy link
Copy Markdown
Member

Upstream rustfs/cli#340 — the one I filed about targetUser being unreachable from the client — was fixed by #352 and released in rc-core 0.1.32. This adopts it.

What changes

Access keys are now created, inspected and revoked with the operator's admin credential, naming the owner via targetUser. Previously the operator built a second client authenticated as the owning user.

That removes two long-standing warts:

  • AccessKey no longer needs the user's password (passwordRef / chart passwordFromUser)
  • the owning user no longer needs admin:CreateServiceAccount / ListServiceAccounts / RemoveServiceAccount over itself — a requirement that was easy to miss and surfaced only as a bare AccessDenied

Breaking

AccessKey.spec.passwordRef and the chart's accessKeys[].passwordFromUser / passwordRef are gone. The field stays in the CRD schema only so a stale manifest is rejected as a spec error rather than silently pruned by the API server; the chart fails at render time with the same guidance.

Migration: delete those fields, and drop the three admin:*ServiceAccount grants from the owning user's policy unless something else needs them.

New requirement: the connection must hold RustFS root

The server's guard is owner || target_user == req_user || target_user == req_parent_user, so only an owner credential may parent a key to another user. A scoped admin now gets service account parent is outside requester scope.

This is deliberate upstream (GHSA-5354): admin:CreateServiceAccount controls whether a caller can create keys, not for whom, and without the guard any holder of that action could mint a root-parented key and escalate. Documented in docs/iam-model.md.

Verification

Against a live RustFS 1.0.0-beta.12, using the admin credential:

create SA with targetUser=spark: 200
$ rc admin service-account list <alias> --user spark
  spark-key     (parent: spark) [on]
  tgt-probe-key (parent: spark) [on]     <- no spark password involved
delete probe SA as admin: 200

info-service-account for another user's key also returns 200 with the right parentUser, so all three paths the operator needs work admin-side.

24 unit tests pass (one new, covering the passwordRef rejection); chart-tests.sh passes; clippy/fmt/actionlint clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SxBhmDG53GRf1vdanvsZBS

CoderYellow and others added 2 commits September 4, 2026 09:02
RustFS has always accepted `targetUser` on add-service-account, but
rc-core did not expose the field, so the operator authenticated *as the
owning user* to mint that user's keys. That forced every AccessKey to
carry the user's password and every owning user's policy to grant
admin:CreateServiceAccount / ListServiceAccounts / RemoveServiceAccount
over itself — a requirement that is easy to miss and fails with a bare
AccessDenied when you do.

rustfs/cli#340 was fixed by rustfs/cli#352 and released in rc-core
0.1.32, which adds `target_user` to CreateServiceAccountRequest. Use it:
keys are now created, inspected and revoked with the admin credential.

BREAKING CHANGE: `AccessKey.spec.passwordRef` and the chart's
`accessKeys[].passwordFromUser` / `passwordRef` are removed. The field is
kept in the CRD schema purely so a stale manifest is rejected as a spec
error instead of being silently pruned; the chart fails at render time.
Drop those fields, and drop the three admin:*ServiceAccount grants from
the owning user's policy unless something else needs them.

The operator's connection must now hold RustFS root: the server's guard
is `owner || target_user == req_user || target_user == req_parent_user`,
so only an owner may parent a key to another user. This is deliberate
upstream (GHSA-5354) — admin:CreateServiceAccount controls whether a
caller can create keys, not for whom.

Verified against a live RustFS 1.0.0-beta.12: creating a service account
with targetUser as the admin credential parents it to the named user
with no password involved, and both info and delete work the same way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SxBhmDG53GRf1vdanvsZBS
The two container-backed suites are behind cargo features, so a plain
`cargo clippy --all-targets` missed them; CI caught it.

Both now drop the password arguments, and both drop the
admin:*ServiceAccount grants from the test user's policy — their absence
is part of what the suites assert. The RustFS integration test also
checks `parent_user == "it-user"` on the issued key, which is the actual
behaviour targetUser buys.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SxBhmDG53GRf1vdanvsZBS
@CoderYellow
CoderYellow merged commit 337dfe8 into master Sep 4, 2026
5 checks passed
@CoderYellow
CoderYellow deleted the feat/target-user-access-keys branch September 4, 2026 01:23
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.

1 participant