From eaa84a9d6c637e64bc4e0075337d39d93a7a9934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E5=B0=8F=E9=B8=AD?= Date: Wed, 29 Jul 2026 13:01:31 +0800 Subject: [PATCH 1/2] feat(sse): enable local KMS evaluation workflow --- app/(dashboard)/sse/page.tsx | 96 +++++++++++++++++++++++++----------- i18n/locales/ar-MA.json | 4 +- i18n/locales/de-DE.json | 4 +- i18n/locales/en-US.json | 4 +- i18n/locales/es-ES.json | 4 +- i18n/locales/fr-FR.json | 4 +- i18n/locales/id-ID.json | 4 +- i18n/locales/it-IT.json | 4 +- i18n/locales/ja-JP.json | 4 +- i18n/locales/ko-KR.json | 4 +- i18n/locales/pt-BR.json | 4 +- i18n/locales/ru-RU.json | 4 +- i18n/locales/tr-TR.json | 4 +- i18n/locales/vi-VN.json | 4 +- i18n/locales/zh-CN.json | 4 +- tests/lib/sse-safety.test.js | 15 ++++-- types/kms.ts | 1 + 17 files changed, 119 insertions(+), 49 deletions(-) diff --git a/app/(dashboard)/sse/page.tsx b/app/(dashboard)/sse/page.tsx index 799e8d98..4b98d6d0 100644 --- a/app/(dashboard)/sse/page.tsx +++ b/app/(dashboard)/sse/page.tsx @@ -273,7 +273,10 @@ export default function SSEPage() { const statusKind = React.useMemo(() => (statusError ? "Error" : getStatusKind(status)), [status, statusError]) const isRunning = statusKind === "Running" const hasConfiguration = !statusError && statusKind !== "NotConfigured" + const localKmsConfigured = hasConfiguration && status?.backend_type === "Local" const hasStoredVaultCredentials = status?.config_summary?.backend_summary?.has_stored_credentials === true + const hasStoredLocalMasterKey = status?.config_summary?.backend_summary?.has_master_key === true + const hasStoredLocalFilePermissions = status?.config_summary?.backend_summary?.file_permissions != null const statusBadgeValue = statusKind === "Error" ? "Error" : typeof status?.status === "string" ? status.status : statusKind @@ -535,19 +538,31 @@ export default function SSEPage() { const cacheTtlSeconds = parseOptionalInteger(values.cacheTtlSeconds) if (values.backendType === "local") { + if (!values.keyDir.trim()) { + return { error: t("Please enter an absolute local key directory path"), field: "keyDir" } + } + const filePermissions = parseOptionalInteger(values.filePermissions) return { - error: t( - "Local filesystem KMS configuration is read-only in Console until safe master-key rotation is available.", - ), + payload: { + backend_type: "Local", + key_dir: values.keyDir.trim(), + file_permissions: + localKmsConfigured && !hasStoredLocalFilePermissions ? undefined : (filePermissions ?? 384), + allow_insecure_dev_defaults: !hasStoredLocalMasterKey, + default_key_id: defaultKeyId || undefined, + timeout_seconds: timeoutSeconds ?? 30, + retry_attempts: retryAttempts ?? 3, + enable_cache: values.enableCache, + max_cached_keys: values.enableCache ? (maxCachedKeys ?? 1000) : undefined, + cache_ttl_seconds: values.enableCache ? (cacheTtlSeconds ?? 3600) : undefined, + }, } } if (values.backendType === "static") { if (!values.secretKey.trim()) { return { - error: t( - "Please enter the static KMS secret key (base64-encoded 32-byte AES-256 key).", - ), + error: t("Please enter the static KMS secret key (base64-encoded 32-byte AES-256 key)."), field: "secretKey", } } @@ -603,7 +618,14 @@ export default function SSEPage() { }, } }, - [formState, hasStoredVaultCredentials, t], + [ + formState, + hasStoredLocalFilePermissions, + hasStoredLocalMasterKey, + hasStoredVaultCredentials, + localKmsConfigured, + t, + ], ) const submitConfiguration = React.useCallback( @@ -937,12 +959,10 @@ export default function SSEPage() { const isPendingDefaultKey = pendingKeyAction?.key.key_id === status?.config_summary?.default_key_id const mutationLocked = Boolean(activeMutation || statusError || loadingStatus) - const localKmsReadOnly = hasConfiguration && formState.backendType === "local" const staticKmsReadOnly = hasConfiguration && formState.backendType === "static" - const formDisabled = mutationLocked || loadingStatus || submittingConfig || localKmsReadOnly || staticKmsReadOnly + const formDisabled = mutationLocked || loadingStatus || submittingConfig || staticKmsReadOnly const mutationInFlight = Boolean(activeMutation || submittingConfig || creatingKey || processingKeyAction) - const canSetCreatedKeyAsDefault = - status?.backend_type !== "Local" && status?.backend_type !== "Static" && !isConfigDirty + const canSetCreatedKeyAsDefault = status?.backend_type !== "Static" && !isConfigDirty return ( <> @@ -1101,13 +1121,17 @@ export default function SSEPage() { {configFormError} ) : null} - {localKmsReadOnly ? ( + {formState.backendType === "local" ? ( - {t("Local filesystem")} + {t("Warning")} - {t( - "Local filesystem KMS configuration is read-only in Console until safe master-key rotation is available.", - )} + {localKmsConfigured + ? t( + "Local KMS is intended for evaluation only. The key directory and file permissions are locked after configuration; changing or rotating the local master key is not supported.", + ) + : t( + "Local KMS is intended for evaluation only. Keys created without a server-managed master key are stored using plaintext development mode. Do not use this backend for production data.", + )} ) : null} @@ -1130,15 +1154,13 @@ export default function SSEPage() { onValueChange={(value) => updateFormState("backendType", value as ConfigFormState["backendType"]) } - disabled={formDisabled} + disabled={formDisabled || localKmsConfigured} > - - {t("Local filesystem")} - + {t("Local filesystem")} {t("HashiCorp Vault KV2")} {t("HashiCorp Vault Transit Engine")} {t("Static single-key (built-in)")} @@ -1216,7 +1238,7 @@ export default function SSEPage() { autoComplete="off" placeholder={t("Enter an absolute path such as D:/data/kms-keys")} spellCheck={false} - disabled={formDisabled} + disabled={formDisabled || localKmsConfigured} required aria-required="true" aria-invalid={configFormErrorField === "keyDir"} @@ -1241,7 +1263,7 @@ export default function SSEPage() { value={formState.filePermissions} onChange={(event) => updateFormState("filePermissions", event.target.value)} placeholder="384" - disabled={formDisabled} + disabled={formDisabled || localKmsConfigured} /> {t("Use decimal values such as 384 for 0o600.")} @@ -1532,7 +1554,7 @@ export default function SSEPage() {

{t("KMS Keys Management")}

- {t("Create, rotate, and inspect the keys managed by your KMS backend.")} + {t("Create a new KMS key and optionally make it the default SSE key.")}
@@ -1548,7 +1570,13 @@ export default function SSEPage() {