Skip to content

feat: add KMS backend positioning badge, Vault TLS form, and rekey sweep UI - #209

Open
reatang wants to merge 3 commits into
mainfrom
reatang/rustfs-kms-fix-5f9d51
Open

feat: add KMS backend positioning badge, Vault TLS form, and rekey sweep UI#209
reatang wants to merge 3 commits into
mainfrom
reatang/rustfs-kms-fix-5f9d51

Conversation

@reatang

@reatang reatang commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Pull Request

Description

Console side of the SSE/KMS P1 batch (handoff: rustfs/backlog#2034), pairing with server-side changes already merged into rustfs/rustfs main — rustfs/rustfs#6633 (backend positioning), rustfs/rustfs#6638 (Vault TLS/mTLS), rustfs/rustfs#6644 / rustfs/rustfs#6654 (object-level rewrap + bulk rekey pipeline).

T1 — Backend positioning badge. The KMS status card shows a destructive badge when the running backend reports capabilities.production_supported === false (Local/Static). The capability matrix comes from GET /kms/status and is only fetched while KMS is running; older servers omit the field entirely and no badge is rendered (absence means "unknown", never "false"). The Local/Static options in the backend select are labeled "(dev/testing only)".

T2 — Vault TLS / mTLS form. New collapsible "Advanced TLS" group in the Vault connection section: ca_cert_path, client_cert_path, client_key_path (server-local PEM paths; helper text notes that in a multi-node cluster the same path must exist on every node). Client cert and key are validated as a pair on the client (mirroring the server rule), and validation errors auto-expand the group and focus the offending field. Blank values are omitted from the configure payload entirely — older servers use deny_unknown_fields, so a console upgrade changes nothing for users who don't touch these fields. Stored state is surfaced via the has_custom_ca / has_client_identity booleans; paths are never echoed back, and the UI states explicitly that saving with blank fields removes the stored TLS settings.

T3 — Bulk rekey sweep UI. New "Rekey Existing Objects" card: start a sweep (optional comma-separated bucket list + object-key prefix, with a confirmation dialog warning about scan cost), poll progress every 3s while running (stops on terminal states), cooperative cancel, and the five per-version counters. failed > 0 is highlighted with guidance that the sweep is idempotent — re-running retries only the failed versions. The whole card is gated on a served capability matrix, so old servers without the rekey routes never see it; on servers where rewrap !== true (Local/Static/AWS) the card explains the backend doesn't support rewrapping instead of offering a start button. The 404 "no sweep has run" empty state is distinguished from a 404 missing route by the JSON error body; 409 (already running) and 501 (unsupported) get distinct, non-error-modal presentations.

i18n: 46 new entries across all 14 locales; two now-unreferenced keys removed. The rekey badge/counter keys are sweep-specific because the existing Completed/Failed keys belong to the tasks panel and carry ({count}) placeholders.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code refactoring
  • Performance improvement
  • Test improvements
  • Security fix

Testing

  • Unit tests added/updated
  • Manual testing completed
pnpm test:run
  • 416 tests pass, including new suites: sse-rekey.test.ts (404/409/501 discrimination, start-request assembly), sse-kms-p1-safety.test.js (source assertions pinning the three compatibility rules), and extended sse-config.test.ts (TLS paths are never refilled from status).
  • pnpm type-check, pnpm lint, pnpm format:check clean for all touched files.
  • Contract-verified against a freshly built rustfs main (cargo build --bin rustfs): capabilities shape, 501 on non-rewrap backends, 404 empty-state body, and unknown-field rejection all match the implementation.
  • End-to-end against a local VaultTransit backend (Docker Vault): configure → start → create key → put 2 SSE-KMS objects → sweep (scanned=2, already_current=2) → rotate key → sweep (scanned=2, rewrapped=2) → idempotent re-run. In-browser: start/confirm/poll/terminal-state flow, pair-validation error focusing, and the empty-payload rule verified.

Checklist

  • Code follows the project's style guidelines
  • Self-review completed
  • TypeScript types are properly defined
  • All commit messages are in English (Conventional Commits)
  • All existing tests pass
  • No new dependencies added, or they are justified

Related Issues

Closes rustfs/backlog#2034

Screenshots (if applicable)

UI states were verified live against a local VaultTransit-backed server (status card without badge, Advanced TLS group, rekey card through running → completed); screenshots intentionally omitted per reviewer agreement.

Additional Notes

Compatibility rules followed throughout: new status fields are optional (absence renders nothing), blank TLS inputs never enter the payload, and the rekey UI is capability-gated so servers without the routes never show it. A pre-existing format:check failure in components/object/tiff-viewer.tsx exists on main and is not touched here.

Console side of the SSE/KMS P1 batch (rustfs/backlog#2034), pairing with
server PRs #6633 (backend positioning), #6638 (Vault TLS/mTLS) and
#6644/#6654 (object rewrap + bulk rekey pipeline):

- Show a destructive badge when the running backend reports
  capabilities.production_supported === false, and label the Local/Static
  select options as dev/testing only. The capability matrix is fetched
  from GET /kms/status only while KMS is running; older servers omit it
  and render nothing.
- Add an Advanced TLS group to the Vault connection form (custom CA,
  mTLS client cert/key, all server-local PEM paths). Blank values are
  omitted from the configure payload because older servers deny unknown
  fields; cert and key are validated as a pair; stored state is surfaced
  via the has_custom_ca / has_client_identity booleans and paths are
  never echoed back.
- Add a rekey sweep card (start with optional bucket list and prefix,
  3s progress polling with terminal-state stop, cooperative cancel,
  failed>0 highlighted with idempotent re-run guidance). The card is
  gated on a served capability matrix so old servers without the rekey
  routes never see it, and the 404 empty state is distinguished from a
  missing route by the response body.
- 43 new locale entries across all 14 locales; drop one unreferenced key.
- Verified against a freshly built rustfs main: capabilities shape, 501
  on non-rewrap backends, 404 empty-state body, and unknown-field
  rejection all match.
The rekey card reused the existing "Completed" and "Failed" keys, but
those belong to the tasks panel and carry a ({count}) placeholder in
every locale, so the badge rendered as "已完成({count})". "Scanned" was
also untranslated in ja-JP/fr-FR. Switch to sweep-specific keys
(Sweep completed / Sweep cancelled / Versions scanned / Versions failed)
and drop the now-unreferenced "Cancelled" key. Caught during in-browser
verification against a local VaultTransit backend.
@cxymds

cxymds commented Aug 28, 2026

Copy link
Copy Markdown
Member

@reatang

…x-5f9d51

# Conflicts:
#	i18n/locales/ar-MA.json
#	i18n/locales/de-DE.json
#	i18n/locales/en-US.json
#	i18n/locales/es-ES.json
#	i18n/locales/fr-FR.json
#	i18n/locales/id-ID.json
#	i18n/locales/it-IT.json
#	i18n/locales/ja-JP.json
#	i18n/locales/ko-KR.json
#	i18n/locales/pt-BR.json
#	i18n/locales/ru-RU.json
#	i18n/locales/tr-TR.json
#	i18n/locales/vi-VN.json
#	i18n/locales/zh-CN.json
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.

2 participants