feat(console): mask access/secret keys in application config forms#5
Conversation
Adds vitest with jsdom and React Testing Library to apps/console so that schema-form widgets and helpers can be unit-tested. No tests yet; the infra is wired up first to keep follow-up commits focused on behaviour. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
Adds a pure helper that walks an OpenAPI/RJSF schema and tags every string field whose name matches the conventional credential patterns (access/secret keys, passwords, tokens, private keys, api keys) with a `SensitiveStringWidget` binding in the uiSchema. Cozystack chart schemas do not annotate sensitive fields with a `format: password` hint, so the detection is name-based and runs in the same style as the existing storageClass/backupClassName/disks helpers in SchemaForm. The helper lives in a separate module so it can be covered with unit tests without rendering RJSF. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
Adds an RJSF widget that renders a credential field as eight bullets plus an eye-icon toggle: clicking the eye swaps the bullets for a plain text input that forwards typing through the standard onChange contract (empty string becomes undefined). When the field is disabled or readonly the toggle is disabled and editing is blocked. The visual style mirrors the SecretRow reveal control already used in the Secrets tab. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
Wires the sensitive-field detector into SchemaForm's uiSchema pipeline and registers the toggle widget under the customWidgets map. As a result, fields like postgres' s3AccessKey and s3SecretKey on the application order/edit screens render as bullets with a click-to-reveal control instead of plain text. Detection is purely additive and does not override widgets bound by earlier detectors. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (12)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request implements automatic masking for sensitive fields like passwords and API keys in schema-driven forms. It introduces a SensitiveStringWidget with a visibility toggle and a utility to identify sensitive fields by name. Additionally, it sets up a Vitest-based testing environment with comprehensive unit tests for the new components and logic. I have no feedback to provide.
kitsunoff
left a comment
There was a problem hiding this comment.
Tested locally against a live cozystack cluster: vitest 29/29, typecheck clean.
Verified masking renders on Postgres backup s3AccessKey/s3SecretKey with the
toggle flipping between password and text. Heuristic allowlist looks tight
(tokenAudience/passwdFile correctly stay unmasked).
LGTM.
Note: the test workflow check is failing because pnpm/action-setup@v4 needs
either a version: in the workflow or packageManager in package.json — a
one-line follow-up, unrelated to the change.
What
Application config forms (the
SchemaForm-driven create/edit screens for postgres and any other chart that exposes credentials in its OpenAPI schema) now render fields likes3AccessKey,s3SecretKey,password,apiKey,privateKey,bearerTokenas a masked<input type="password">with an eye-icon toggle next to it. Click the toggle and the input flips totext; click again and it goes back to bullets.Detection is purely name-based — Cozystack chart schemas don't carry a
format: passwordhint, so the new helper splits a field name on camelCase / underscore / dash / dot boundaries and matches the resulting word tokens against a small allowlist. The split between "matches anywhere" (accesskey,secretkey,secretaccesskey,password,apikey,privatekey) and "matches only as the trailing word" (token,passwd) keeps neighbours liketokenAudience,csrfTokenName,passwdFile,publicKeyout of the set.Why
Today these fields render with the default RJSF
TextWidget, which means anyone with the dashboard on screen during a demo, a paired session, or a screenshare can read the S3 credentials a tenant typed in. Masking by default with an opt-in reveal toggle is the standard pattern for credential entry and matches the existingSecretsTabbehaviour on the application detail page.Scope
ApplicationOrderPageare not changed — both intentionally show the raw spec and changing that is a separate decision.disabledorreadonly, so a viewer of an existing application config can still inspect the stored value without being able to edit it.autoComplete="new-password"is set on the input to discourage browser password-manager prompts on configuration fields that aren't the user's login credential. Browser behaviour varies and the prompt is not fully suppressible.Test infrastructure
This PR also wires up
vitest+ React Testing Library inapps/console(no test infra existed before) and adds a small CI workflow that runspnpm typecheck && pnpm teston every push tomainand every PR. The detector and the widget are covered by 29 unit tests across two test files.Limitations
oneOf/anyOf/allOfbranches are not walked yet. AFIXME-marked test pins that behaviour so the gap is visible.format: passwordto the upstream chart schemas would let this widget be triggered explicitly; that work belongs incozystack/cozystack.