feat(cosi): add RustFS COSI v1alpha1 driver with idempotent grants - #217
feat(cosi): add RustFS COSI v1alpha1 driver with idempotent grants#217BenjaminFuentesEviden wants to merge 4 commits into
Conversation
Extract shared rustfs-admin client, ship a tonic COSI driver with Helm toggle, and document BucketClass parameters for Tenant-backed S3. Co-authored-by: Cursor <cursoragent@cursor.com>
Align DriverGrantBucketAccess with Ceph-style isolation: deterministic secrets, never rotate existing users, and return AlreadyExists when preferredAccessKey is claimed by another BucketAccess. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Hi @GatewayJ, I know you are quite busy delivering the stable V1, but what do you think about my COSI PR here? |
|
Thanks for contributing COSI support to RustFS. The overall direction is valuable, but this PR is not ready to merge yet. Please address the following items. CLAI could not find The Operator repository also does not currently run an automated CLA check, so the absence of a CLA status on this PR does not indicate that it has been signed. Blocking correctness and security issues
Architecture concernsThe decision to run COSI as a separate driver process is reasonable, but the integration is not sufficiently unified with the existing Operator architecture:
A more maintainable structure would be: The Helm chart should then manage the COSI sidecar, driver, RBAC, socket, and supported protocol version together. Required validationPlease add tests covering:
Given the credential vulnerability and ownership/lifecycle issues, this PR should not be merged in its current form. I recommend addressing the shared client and ownership model first, then adding the COSI transport and deployment integration on top of that foundation. |
|
Ok
I did the first step with CLA v2 here : rustfs/cla#6
Now I am reviewing your answers
[cid:7b37d366-485c-4063-b5d8-41969cdb9ad1]
…________________________________
De : GatewayJ ***@***.***>
Envoyé : mardi 4 août 2026 18:18
À : rustfs/operator ***@***.***>
Cc : Benjamin Fuentes ***@***.***>; Author ***@***.***>
Objet : Re: [rustfs/operator] feat(cosi): add RustFS COSI v1alpha1 driver with idempotent grants (PR #217)
Caution: External email. Do not open attachments or click links, unless this email comes from a known sender and you know the content is safe.
[https://avatars.githubusercontent.com/u/18332154?s=20&v=4]GatewayJ left a comment (rustfs/operator#217)<#217 (comment)>
Thanks for contributing COSI support to RustFS. The overall direction is valuable, but this PR is not ready to merge yet. Please address the following items.
CLA
I could not find BenjaminFuentesEviden in the official [RustFS CLA signature records<https://github.com/rustfs/cla/tree/main/signatures/individual>](https://github.com/rustfs/cla/tree/main/signatures/individual). Please sign the current [RustFS CLA v2<https://github.com/rustfs/cla/blob/main/README.md>](https://github.com/rustfs/cla/blob/main/README.md) before we continue with the merge process.
The Operator repository also does not currently run an automated CLA check, so the absence of a CLA status on this PR does not indicate that it has been signed.
Blocking correctness and security issues
1. The generated S3 secret is predictable
crates/cosi-driver/src/parameters.rs:165-169 derives the secret as:
sha256("rustfs-cosi-v1:{account_id}")
An access key is an identifier, not a secret. Anyone who knows the access key can calculate the corresponding secret key. Credentials should be randomly generated and durably persisted before creating the RustFS user. An unkeyed deterministic hash is not suitable for credential generation.
2. Grant ownership is not crash-safe or fully idempotent
In crates/cosi-driver/src/driver.rs:246-281, the RustFS user is created before the owner marker is attached. If the process exits or a policy operation fails after add_user, the next retry sees an existing user without the marker and returns AlreadyExists.
This leaves a valid COSI request permanently stuck and also creates a race between concurrent grants. Ownership should be persisted through a Kubernetes CAS-backed PendingCreate checkpoint before external RustFS mutations, then promoted after provisioning succeeds.
3. A shared policy name can change permissions for existing users
driver.rs:229-267 uses the policy BucketAccessClass parameter as a global canned-policy name, while add_canned_policy replaces the existing document.
Since a BucketAccessClass is normally shared by multiple BucketAccess resources, a later grant can overwrite the policy used by earlier users and silently move or broaden their bucket permissions. Generated policies must be unique per grant. Externally managed policies should only be referenced and validated, never replaced.
4. Bucket ownership and deletion are unsafe
driver.rs:149-158 treats every backend AlreadyExists result as a successful idempotent retry without verifying ownership or compatible parameters. driver.rs:184-194 later deletes all buckets expanded from the shared class parameters.
This can cause different BucketClaims to share an existing bucket or allow one claim to delete a bucket it did not create. Dynamic provisioning should use the COSI-generated unique bucket name. Existing/static buckets need a separate adoption path and must never be deleted without ownership proof.
5. The implementation is not fully compliant with COSI semantics
The protobuf is wire-compatible with the latest stable [COSI v0.2.2<https://github.com/kubernetes-sigs/container-object-storage-interface/releases/tag/v0.2.2>](https://github.com/kubernetes-sigs/container-object-storage-interface/releases/tag/v0.2.2), but the behavior is not fully compliant:
* Same bucket name with incompatible parameters must return AlreadyExists; the current code returns success for every collision.
* UnknownAuthenticationType is accepted as KEY even though authentication type is required.
* Grant retry and partial-failure semantics are not reliably idempotent.
Please explicitly pin the supported sidecar/controller version to v0.2.2. The current upstream main branch uses v1alpha2 and is not wire-compatible with this v1alpha1 service.
Architecture concerns
The decision to run COSI as a separate driver process is reasonable, but the integration is not sufficiently unified with the existing Operator architecture:
* rustfs-cosi-driver depends on the entire operator crate only to reuse RustfsAdminClient. The admin client should be extracted into a small shared crate used by both components.
* Existing Tenant provisioning stores ownership using Tenant status and CAS checkpoints, while this driver uses IAM policy names as ownership markers. This creates two independent ownership models for the same RustFS users, policies, and buckets.
* driver.rs currently combines gRPC transport, parameter validation, credential generation, policy construction, ownership decisions, lifecycle orchestration, and backend I/O. The gRPC layer should delegate to a testable provisioning/grant state machine.
* The binary is added to the Operator image, but no Helm Deployment, sidecar version, socket configuration, RBAC, or lifecycle ownership is provided. Users cannot enable the feature through the existing Operator installation.
A more maintainable structure would be:
Operator provisioning ─┐
├─ shared ownership/lifecycle service ─ rustfs-admin-client
COSI gRPC adapter ─────┘ │
Kubernetes CAS state
The Helm chart should then manage the COSI sidecar, driver, RBAC, socket, and supported protocol version together.
Required validation
Please add tests covering:
* partial failure after user creation;
* concurrent grants using the same preferred access key;
* shared BucketAccessClass policy behavior;
* existing bucket collisions and delete ownership;
* retry/restart idempotency;
* an end-to-end flow using the pinned COSI controller/sidecar version.
Given the credential vulnerability and ownership/lifecycle issues, this PR should not be merged in its current form. I recommend addressing the shared client and ownership model first, then adding the COSI transport and deployment integration on top of that foundation.
—
Reply to this email directly, view it on GitHub<#217?email_source=notifications&email_token=BTTXFZ5IK3EBMUQETFJWBTT5IIEGLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJYGE3TIMBYGQ22M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L#issuecomment-5181740845>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/BTTXFZYGBUTTXU35OEUT5VD5IIEGLAVCNFSNUABGKJSXA33TNF2G64TZHMYTAMJXGMYTCMJUGE5US43TOVSTWNJQGYYDIMRXGA2TRILWAI>.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS<https://github.com/notifications/mobile/ios/BTTXFZ6QTDS6TMNPGIRUZ2T5IIEGLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJYGE3TIMBYGQ22M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KUZTPN52GK4S7NFXXG> and Android<https://github.com/notifications/mobile/android/BTTXFZ23TEBWNIQQBLZP6B35IIEGLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJYGE3TIMBYGQ22M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2K4ZTPN52GK4S7MFXGI4TPNFSA>. Download it today!
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
|
Thanks @GatewayJ for the thorough review — I agree with the assessment and the recommended sequencing. CLA: signed via rustfs/cla#6 (pending merge/record). On the five blockers: I accept all of them.
Plan going forward (split as you suggested):
I will keep this PR (#217) as the discussion / tracking surface and open follow-up PRs against Thanks again for the clear guidance. |
PR A openedFoundation work (shared Helm Deployment / sidecar pin v0.2.2 / full COSI semantic compliance remain for PR B. Keeping this PR open as tracking until B lands. |
Type of Change
Related Issues
N/A
Summary of Changes
Adds a RustFS COSI v1alpha1 driver (
rustfs.objectstorage.k8s.io) and hardensDriverGrantBucketAccessso sharedpreferredAccessKeycannot rotate secrets out from under anotherBucketAccess(Ceph-like isolation).What this PR adds
New binary
rustfs-cosi-driver(crates/cosi-driver)objectstorage-sidecarUNIX socket pattern).Dockerfilebuilds-p operator -p rustfs-cosi-driver).rustfs.objectstorage.k8s.io.BucketClass / BucketAccessClass parameters (Rook-style admin secret + endpoint)
endpoint,objectStoreUserSecretName,objectStoreUserSecretNamespaceregion,policy, TLS CA ConfigMap refsbucketName/buckets(multi-bucket,*for broad policy),preferredAccessKey/accessKeyAdmin client support
get_user_infoonRustfsAdminClient(parse attached policy names from/rustfs/admin/v3/user-info)Docs
preferredAccessKeymust be unique perBucketAccess; default (omit it) is safestDesign choices (important for reviewers)
RustfsAdminClientrelease-0.2style)CephCOSIDriver-style CR in MVPname(ba-<UID>)BucketAccesspreferredAccessKeysha256("rustfs-cosi-v1:{account_id}")add_userwhen user already existssecretKeyvia PUT and breaking live workloads (SignatureDoesNotMatch)cosi-grant-{grant_name}preferredAccessKeypreferredAccessKeyby another claim →AlreadyExistsbuckets/bucketName*in IAM policyOut of scope / follow-ups
BucketAccess/ unique preferred keys).Checklist
make pre-commit(fmt-check + clippy + test + console-lint + console-fmt-check)[Unreleased](if user-visible change)Notes on checklist:
cargo fmt --check,cargo clippy -p rustfs-cosi-driver --all-targets -- -D warnings, and unit tests for cosi-driver +get_user_infoparsing were run locally.make pre-commit(including console lint/fmt) was not fully green in this contributor environment; please rely on CI.Impact
rustfs-cosi-driverin the operator image; deploy with official COSI sidecarVerification
Manual expectation for grant semantics:
BucketAccesswith the samepreferredAccessKey→ second grant returns gRPCAlreadyExists.BucketAccess→ OK with identical secret (no rotation).preferredAccessKey→ unique account per COSI grant name (ba-<UID>).Additional Notes
This work was validated against a demo cluster using RustFS + COSI
BucketClaim/BucketAccess, where sharedpreferredAccessKey+ non-idempotentadd_userpreviously causedSignatureDoesNotMatchon PutObject. The grant path above is specifically designed to prevent that class of failure while remaining Ceph-COSI-compatible by default.Driver name for BucketClass / BucketAccessClass:
Thank you for your contribution! Please ensure your PR follows the community standards (CODE_OF_CONDUCT.md) and sign the CLA if this is your first contribution.