# OpenStack Swift API for RustFS Swift-compatible object storage API implementation for RustFS. ## Features The lists below are bounded to what `router.rs` / `handler.rs` dispatch and what the test suite exercises. A module existing under `src/swift/` does not by itself mean the feature is reachable over HTTP. ### Wired through the router and handler - ✅ Account listing (`GET /v1/AUTH_{project}`, JSON) and additive account metadata updates (`POST`, `X-Account-Meta-*` / `X-Remove-Account-Meta-*`) - ✅ Container CRUD (create, list, head, update metadata, delete) - ✅ Object CRUD with streaming downloads, HTTP Range requests (206 / 416), and server-side copy via the `COPY` method - ✅ Keystone token authentication and multi-tenant isolation with SHA256-based bucket prefixing - ✅ Custom metadata (`X-Object-Meta-*`, `X-Container-Meta-*`); container and account POSTs are additive, object POSTs replace the set - ✅ Container ACLs (`X-Container-Read` / `X-Container-Write`, set and remove on container POST, reported on HEAD). Enforcement is account-level plus referrer checks; per-user grants are not evaluated because credentials carry no user id - ✅ CORS: `OPTIONS` preflight on container and object routes, and response header injection driven by `X-Container-Meta-Access-Control-*` - ✅ TempURL (`temp_url_sig` / `temp_url_expires` on object GET, HEAD, PUT; key stored as account metadata; optional client-IP restriction) - ✅ FormPost (container POST with `multipart/form-data`, signed with the account TempURL key) - ✅ Large objects: Static Large Objects (`?multipart-manifest=put|get|delete`) and Dynamic Large Objects (`X-Object-Manifest`) - ✅ Bulk operations: `DELETE /v1/AUTH_{project}?bulk-delete` and `PUT /v1/AUTH_{project}/{container}?extract-archive=tar|tar.gz|tar.bz2` - ✅ Object versioning in the Swift `X-Versions-Location` style: the previous copy is archived on PUT / DELETE and restored on DELETE - ✅ Symlinks (`X-Symlink-Target` on PUT, resolved on GET / HEAD with loop and depth checks) - ✅ Container quotas (`X-Container-Meta-Quota-Bytes` / `-Quota-Count`), enforced on object PUT - ✅ Static website serving on object GET when `web-index` / `web-listings` container metadata is set - ✅ Object expiration headers: `X-Delete-At` / `X-Delete-After` are validated, stored, and returned on GET / HEAD ### Not yet wired, or partially wired - ⏳ Account `HEAD` returns `501 Not Implemented`; no account-level usage statistics are exposed - ⏳ Automatic deletion of expired objects: `expiration_worker.rs` exists but the server never starts it, so objects past `X-Delete-At` are not removed - ⏳ Container sync (`sync.rs`): no `X-Container-Sync-*` header handling and no background worker; the module is unit-tested only - ⏳ `X-Copy-From` on object PUT (only the `COPY` method is supported) - ⏳ `X-History-Location` versioning mode - ⏳ Static website index / listing pages at the container root (only the object GET route consults static-web settings) - ⏳ XML / plain-text listing formats; the `format=` query parameter is ignored and listings are always JSON ### Test coverage - Unit tests live next to each module (`acl.rs`, `bulk.rs`, `cors.rs`, `dlo.rs`, `slo.rs`, `tempurl.rs`, `formpost.rs`, `staticweb.rs`, `symlink.rs`, `quota.rs`, `expiration.rs`, `versioning.rs`, `router.rs`, `handler.rs`, and others) and run in the CI `swift` feature lane - `crates/protocols/tests/swift_metadata_persistence.rs` runs account, container, ACL, TempURL-key, and versioning metadata writes against a real ECStore and reloads them from disk - `crates/protocols/tests/swift_versioning_integration.rs`, `swift_listing_symlink_tests.rs`, `swift_simple_integration.rs`, and `swift_phase4_integration.rs` cover version naming, listing parameters, symlink parsing, and module-level helpers without a server - `rustfs/tests/swift_container_integration_test.rs` and `swift_object_integration_test.rs` exercise the HTTP surface end to end but are `#[ignore]` and need a running server (`TEST_RUSTFS_SERVER`); they are not part of CI ## Enable Feature **Swift API is opt-in and must be explicitly enabled.** Build with Swift support: ```bash cargo build --features swift ``` Or enable all protocol features: ```bash cargo build --features full ``` **Note:** Swift is NOT enabled by default to avoid unexpected API surface changes in existing deployments. ## Configuration Swift API uses Keystone for authentication. The variables below are read by `crates/keystone/src/config.rs`; that file is the authoritative list. | Variable | Description | |----------|-------------| | `RUSTFS_KEYSTONE_ENABLE` | Set to `true` to enable Keystone authentication (default `false`; nothing else is read while disabled) | | `RUSTFS_KEYSTONE_AUTH_URL` | Keystone authentication endpoint URL (required once enabled) | | `RUSTFS_KEYSTONE_VERSION` | Keystone API version, `v3` or `v2.0` (default `v3`) | | `RUSTFS_KEYSTONE_ADMIN_USER` | Admin username (optional) | | `RUSTFS_KEYSTONE_ADMIN_PASSWORD` | Admin password (optional) | | `RUSTFS_KEYSTONE_ADMIN_PROJECT` | Admin project name (optional) | | `RUSTFS_KEYSTONE_ADMIN_DOMAIN` | Admin domain name (optional) | | `RUSTFS_KEYSTONE_VERIFY_SSL` | Verify the Keystone TLS certificate (default `true`) | | `RUSTFS_KEYSTONE_ENABLE_CACHE` / `RUSTFS_KEYSTONE_CACHE_SIZE` / `RUSTFS_KEYSTONE_CACHE_TTL` | Token cache toggle, entry count, and TTL in seconds (defaults `true`, `10000`, `300`) | | `RUSTFS_KEYSTONE_TENANT_PREFIX` | Prefix bucket names with the tenant hash (default `true`) | | `RUSTFS_KEYSTONE_IMPLICIT_TENANTS` | Allow implicit tenant creation (default `true`) | | `RUSTFS_KEYSTONE_TIMEOUT` | Keystone request timeout in seconds (default `30`) | ## API Endpoints Swift API endpoints follow the pattern: `/v1/AUTH_{project_id}/...` ### Account Operations - `GET /v1/AUTH_{project}` - List containers (JSON) - `HEAD /v1/AUTH_{project}` - Get account metadata (returns 501, not yet implemented) - `POST /v1/AUTH_{project}` - Update account metadata and TempURL key - `DELETE /v1/AUTH_{project}?bulk-delete` - Bulk delete ### Container Operations - `PUT /v1/AUTH_{project}/{container}` - Create container (`?extract-archive=` for bulk upload) - `GET /v1/AUTH_{project}/{container}` - List objects (JSON; `limit`, `marker`, `end_marker`, `prefix`, `delimiter`) - `HEAD /v1/AUTH_{project}/{container}` - Get container metadata - `POST /v1/AUTH_{project}/{container}` - Update container metadata, ACLs, versioning location; FormPost when `multipart/form-data` - `DELETE /v1/AUTH_{project}/{container}` - Delete container - `OPTIONS /v1/AUTH_{project}/{container}` - CORS preflight ### Object Operations - `PUT /v1/AUTH_{project}/{container}/{object}` - Upload object (SLO manifest with `?multipart-manifest=put`, DLO with `X-Object-Manifest`, symlink with `X-Symlink-Target`) - `GET /v1/AUTH_{project}/{container}/{object}` - Download object (Range, SLO/DLO assembly, symlink resolution, `?multipart-manifest=get`) - `HEAD /v1/AUTH_{project}/{container}/{object}` - Get object metadata - `POST /v1/AUTH_{project}/{container}/{object}` - Update object metadata - `DELETE /v1/AUTH_{project}/{container}/{object}` - Delete object (`?multipart-manifest=delete` removes SLO segments) - `COPY /v1/AUTH_{project}/{container}/{object}` - Server-side copy - `OPTIONS /v1/AUTH_{project}/{container}/{object}` - CORS preflight Object GET, HEAD, and PUT also accept TempURL query parameters without an auth token. ## Architecture The Swift API is implemented as a Tower service layer (`SwiftService`) that wraps the S3 service: ``` HTTP Request │ ▼ ┌───────────────┐ │ SwiftService │ ← Routes /v1/AUTH_* requests └───────┬───────┘ │ ┌────┴────┐ │ │ ▼ ▼ Swift S3 Service Handler (fallback) ``` ### Key Components - **handler.rs** - Main service implementing Tower's Service trait and method dispatch - **router.rs** - URL routing and parsing for Swift paths - **container.rs** - Container operations with tenant isolation - **object.rs** - Object operations including copy and range requests - **account.rs** - Account validation, tenant access control, account metadata and TempURL key - **acl.rs**, **cors.rs** - Container ACL evaluation and CORS config - **slo.rs**, **dlo.rs** - Static and dynamic large objects - **tempurl.rs**, **formpost.rs** - Signed URL and form upload validation - **bulk.rs** - Bulk delete and archive extraction - **versioning.rs**, **symlink.rs**, **quota.rs**, **staticweb.rs**, **expiration.rs** - Per-feature helpers called from the handler - **expiration_worker.rs**, **sync.rs** - Background workers that are not started by the server (see above) - **metadata_update.rs** - Additive account/container metadata merge - **errors.rs** - Swift-specific error types - **types.rs** - Data structures for Swift API responses ### Tenant Isolation Swift containers are mapped to S3 buckets with a secure hash prefix: ``` Swift: /v1/AUTH_abc123/mycontainer ↓ S3 Bucket: {sha256(abc123)[0:16]}-mycontainer ``` This ensures: - Complete tenant isolation at the storage layer - No collision between tenants with similar container names - S3-compatible bucket naming (lowercase alphanumeric + hyphen) ## Documentation There is no separate Swift reference document in the repository. Use these sources instead: - Module-level `//!` comments in each `crates/protocols/src/swift/*.rs` file describe the headers and metadata keys that feature reads - `crates/protocols/tests/swift_*.rs` and `rustfs/tests/swift_*_integration_test.rs` show the expected request and response shapes - `docs/testing/ci-gates.md` describes the CI lane that builds and tests with `--features swift` ## License Apache License 2.0