feat(cassandra): add TLS store support
This commit is contained in:
26 files changed
+1203
-36
No files matched your search
@@ -62,6 +62,7 @@ import { SQLITE_DATABASE_FILE_EXTENSIONS } from "@/lib/database/databaseFileDete
|
||||
import { connectionAttemptOriginalErrorMessage, connectionAttemptTimeoutMessage, connectionAttemptTimeoutMs } from "@/lib/connection/connectionAttemptTimeout";
|
||||
import { consulAgentAddressesMatch } from "@/lib/consul/agentTarget";
|
||||
import { appendConnectionErrorHints, isJdbcMissingRuntimeDependencyError } from "@/lib/connection/connectionErrorHints";
|
||||
import { buildCassandraExternalConfig, cassandraTlsConfigFromExternalConfig, type CassandraTlsConfig } from "@/lib/connection/cassandraTlsOptions";
|
||||
import { preventDialogDocumentSelectAll } from "@/lib/connection/dialogTextSelection";
|
||||
import { postgresLegacyTlsEnabled, postgresTlsModeForForm, setPostgresLegacyTlsEnabled } from "@/lib/connection/postgresTlsMode";
|
||||
import { buildMqKafkaConnectionExtra, mqKafkaConnectionTarget, resolveMqKafkaConnectionSource, type MqKafkaConnectionSource } from "@/lib/connection/mqKafkaConnection";
|
||||
@@ -396,6 +397,12 @@ const defaultForm = (): ConnectionForm => ({
|
||||
save_password: true,
|
||||
});
|
||||
|
||||
const cassandraTls = reactive<CassandraTlsConfig>(cassandraTlsConfigFromExternalConfig(undefined));
|
||||
|
||||
function resetCassandraTlsFields(externalConfig: unknown) {
|
||||
Object.assign(cassandraTls, cassandraTlsConfigFromExternalConfig(externalConfig));
|
||||
}
|
||||
|
||||
const elasticsearchConnectionMode = ref<ElasticsearchConnectionMode>("direct");
|
||||
const elasticsearchKibanaBasePath = ref("");
|
||||
const elasticsearchConnectivityCheckPath = ref("");
|
||||
@@ -2333,6 +2340,9 @@ function applyProfile(val: string, preserveConnectionFields = false) {
|
||||
if (profile.type !== "elasticsearch" || previousDatabaseType !== "elasticsearch") {
|
||||
resetElasticsearchProxyFields();
|
||||
}
|
||||
if (profile.type !== "cassandra" || previousDatabaseType !== "cassandra") {
|
||||
resetCassandraTlsFields(undefined);
|
||||
}
|
||||
if (!preserveConnectionFields) {
|
||||
oracleTnsAdminPath.value = "";
|
||||
form.value.port = profile.port;
|
||||
@@ -2572,6 +2582,7 @@ watch(
|
||||
} else {
|
||||
resetMqFields();
|
||||
}
|
||||
resetCassandraTlsFields(config.db_type === "cassandra" ? config.external_config : undefined);
|
||||
if (config.db_type === "nacos") {
|
||||
hydrateNacosFields(config.external_config);
|
||||
} else {
|
||||
@@ -2643,6 +2654,7 @@ watch(
|
||||
selectedType.value = "mysql";
|
||||
customDriverName.value = "";
|
||||
resetMqFields();
|
||||
resetCassandraTlsFields(undefined);
|
||||
resetNacosFields();
|
||||
resetInfluxDbFields();
|
||||
resetElasticsearchProxyFields();
|
||||
@@ -3012,6 +3024,7 @@ const tlsCapableDatabaseTypes = new Set<DatabaseType>([
|
||||
"chromadb",
|
||||
"influxdb",
|
||||
"victoriametrics",
|
||||
"cassandra",
|
||||
]);
|
||||
const supportsTlsToggle = computed(() => tlsCapableDatabaseTypes.has(form.value.db_type));
|
||||
const supportsCaCertificatePath = computed(() => form.value.db_type === "clickhouse" || form.value.db_type === "victoriametrics");
|
||||
@@ -3922,6 +3935,20 @@ function connectionConfigForSubmit(id: string, generatedName = ""): ConnectionCo
|
||||
config.database = undefined;
|
||||
config.connection_string = undefined;
|
||||
config.url_params = "";
|
||||
} else if (config.db_type === "cassandra") {
|
||||
// Go 侧在配置了 truststore/keystore 时会自动启用 TLS,前端保持一致:有 store 配置就不丢弃 external_config。
|
||||
const cassandraHasTlsStore = Boolean(cassandraTls.truststore_path.trim() || cassandraTls.truststore_password) || Boolean(cassandraTls.keystore_path.trim() || cassandraTls.keystore_password);
|
||||
if (!config.ssl && !cassandraHasTlsStore) {
|
||||
config.external_config = undefined;
|
||||
} else {
|
||||
if (cassandraTls.truststore_password && !cassandraTls.truststore_path.trim()) {
|
||||
throw new Error(t("connection.cassandraTruststorePasswordRequiresPath"));
|
||||
}
|
||||
if (cassandraTls.keystore_password && !cassandraTls.keystore_path.trim()) {
|
||||
throw new Error(t("connection.cassandraKeystorePasswordRequiresPath"));
|
||||
}
|
||||
config.external_config = buildCassandraExternalConfig(cassandraTls);
|
||||
}
|
||||
} else if (config.db_type === "nacos") {
|
||||
const nacosConfig = buildNacosAdminConfig();
|
||||
config.external_config = nacosConfig;
|
||||
@@ -5476,6 +5503,23 @@ async function browseCaCertPath() {
|
||||
}
|
||||
}
|
||||
|
||||
async function browseCassandraStore(target: "truststore" | "keystore") {
|
||||
if (!isTauriRuntime()) return;
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
const selected = await open({
|
||||
title: target === "truststore" ? t("connection.cassandraTruststoreBrowse") : t("connection.cassandraKeystoreBrowse"),
|
||||
multiple: false,
|
||||
filters: [
|
||||
{ name: "Java KeyStore / PKCS#12", extensions: ["jks", "p12", "pfx", "truststore", "keystore"] },
|
||||
{ name: "All Files", extensions: ["*"] },
|
||||
],
|
||||
});
|
||||
if (typeof selected === "string") {
|
||||
if (target === "truststore") cassandraTls.truststore_path = selected;
|
||||
else cassandraTls.keystore_path = selected;
|
||||
}
|
||||
}
|
||||
|
||||
async function browseDamengSslFilesPath() {
|
||||
if (isTauriRuntime()) {
|
||||
const { open } = await import("@tauri-apps/plugin-dialog");
|
||||
@@ -7913,6 +7957,56 @@ function openExternalUrl(url: string) {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="form.db_type === 'cassandra'">
|
||||
<div class="grid grid-cols-4 items-start gap-4">
|
||||
<Label :class="connectionLabelSmallPaddedClass">
|
||||
<span class="inline-flex items-center justify-end gap-1">
|
||||
<ShieldCheck class="h-3.5 w-3.5" />
|
||||
{{ t("connection.cassandraTruststore") }}
|
||||
</span>
|
||||
</Label>
|
||||
<div class="col-span-3 grid gap-2">
|
||||
<div class="flex items-center gap-1">
|
||||
<Input v-model="cassandraTls.truststore_path" class="flex-1" :placeholder="t('connection.cassandraTruststorePlaceholder')" :disabled="!tlsEnabled" />
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="outline" size="icon" class="h-9 w-9 shrink-0" :disabled="!tlsEnabled" @click="browseCassandraStore('truststore')">
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.cassandraTruststoreBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<PasswordInput v-model="cassandraTls.truststore_password" :placeholder="t('connection.cassandraTruststorePassword')" :disabled="!tlsEnabled" />
|
||||
<p class="text-[11px] leading-4 text-muted-foreground">{{ t("connection.cassandraTruststoreHint") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-4 items-start gap-4">
|
||||
<Label :class="connectionLabelSmallPaddedClass">
|
||||
<span class="inline-flex items-center justify-end gap-1">
|
||||
<KeyRound class="h-3.5 w-3.5" />
|
||||
{{ t("connection.cassandraKeystore") }}
|
||||
</span>
|
||||
</Label>
|
||||
<div class="col-span-3 grid gap-2">
|
||||
<div class="flex items-center gap-1">
|
||||
<Input v-model="cassandraTls.keystore_path" class="flex-1" :placeholder="t('connection.cassandraKeystorePlaceholder')" :disabled="!tlsEnabled" />
|
||||
<Tooltip v-if="isDesktop">
|
||||
<TooltipTrigger as-child>
|
||||
<Button variant="outline" size="icon" class="h-9 w-9 shrink-0" :disabled="!tlsEnabled" @click="browseCassandraStore('keystore')">
|
||||
<FolderOpen class="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{{ t("connection.cassandraKeystoreBrowse") }}</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<PasswordInput v-model="cassandraTls.keystore_password" :placeholder="t('connection.cassandraKeystorePassword')" :disabled="!tlsEnabled" />
|
||||
<p class="text-[11px] leading-4 text-muted-foreground">{{ t("connection.cassandraKeystoreHint") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="form.db_type === 'redis'" class="grid grid-cols-4 items-start gap-4">
|
||||
<Label :class="connectionLabelSmallClass">{{ t("connection.redisTlsInsecure") }}</Label>
|
||||
<label class="col-span-3 flex items-start gap-2 cursor-pointer">
|
||||
|
||||
@@ -566,6 +566,18 @@ export default withEnglishFallback({
|
||||
caCertPath: "CA sertifikatı",
|
||||
caCertPathPlaceholder: "İstəyə bağlı, məsələn, ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "Sertifikat seç",
|
||||
cassandraTruststore: "Etibar anbarı",
|
||||
cassandraTruststorePlaceholder: "/path/to/client.truststore",
|
||||
cassandraTruststorePassword: "Etibar anbarı parolu",
|
||||
cassandraTruststoreBrowse: "Cassandra etibar anbarını seçin",
|
||||
cassandraTruststoreHint: "Cassandra server sertifikatlarını yoxlamaq üçün JKS və ya PKCS#12 etibar anbarı.",
|
||||
cassandraTruststorePasswordRequiresPath: "Parolu daxil etməzdən əvvəl Cassandra etibar anbarını seçin.",
|
||||
cassandraKeystore: "Müştəri açarlar anbarı",
|
||||
cassandraKeystorePlaceholder: "/path/to/client.keystore",
|
||||
cassandraKeystorePassword: "Açarlar anbarı parolu",
|
||||
cassandraKeystoreBrowse: "Cassandra müştəri açarlar anbarını seçin",
|
||||
cassandraKeystoreHint: "Müştəri sertifikatı ilə identifikasiya üçün istəyə bağlı JKS və ya PKCS#12 açarlar anbarı.",
|
||||
cassandraKeystorePasswordRequiresPath: "Parolu daxil etməzdən əvvəl Cassandra müştəri açarlar anbarını seçin.",
|
||||
damengSslFilesPath: "Sertifikat qovluğu",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "Sertifikat qovluğunu seçin",
|
||||
|
||||
@@ -567,6 +567,18 @@ export default {
|
||||
caCertPath: "CA Certificate",
|
||||
caCertPathPlaceholder: "Optional, e.g. ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "Browse certificate",
|
||||
cassandraTruststore: "Truststore",
|
||||
cassandraTruststorePlaceholder: "/path/to/client.truststore",
|
||||
cassandraTruststorePassword: "Truststore password",
|
||||
cassandraTruststoreBrowse: "Choose Cassandra truststore",
|
||||
cassandraTruststoreHint: "JKS or PKCS#12 truststore used to verify Cassandra server certificates.",
|
||||
cassandraTruststorePasswordRequiresPath: "Select a Cassandra truststore before entering its password.",
|
||||
cassandraKeystore: "Client Keystore",
|
||||
cassandraKeystorePlaceholder: "/path/to/client.keystore",
|
||||
cassandraKeystorePassword: "Keystore password",
|
||||
cassandraKeystoreBrowse: "Choose Cassandra client keystore",
|
||||
cassandraKeystoreHint: "Optional JKS or PKCS#12 keystore for client certificate authentication.",
|
||||
cassandraKeystorePasswordRequiresPath: "Select a Cassandra client keystore before entering its password.",
|
||||
damengSslFilesPath: "Certificate directory",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "Select certificate directory",
|
||||
|
||||
@@ -546,6 +546,18 @@ export default withEnglishFallback({
|
||||
caCertPath: "Certificado CA",
|
||||
caCertPathPlaceholder: "Opcional, p. ej. ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "Buscar certificado",
|
||||
cassandraTruststore: "Almacén de confianza",
|
||||
cassandraTruststorePlaceholder: "/ruta/al/client.truststore",
|
||||
cassandraTruststorePassword: "Contraseña del almacén de confianza",
|
||||
cassandraTruststoreBrowse: "Elegir almacén de confianza de Cassandra",
|
||||
cassandraTruststoreHint: "Almacén de confianza JKS o PKCS#12 usado para verificar los certificados del servidor Cassandra.",
|
||||
cassandraTruststorePasswordRequiresPath: "Selecciona un almacén de confianza de Cassandra antes de introducir su contraseña.",
|
||||
cassandraKeystore: "Almacén de claves del cliente",
|
||||
cassandraKeystorePlaceholder: "/ruta/al/client.keystore",
|
||||
cassandraKeystorePassword: "Contraseña del almacén de claves",
|
||||
cassandraKeystoreBrowse: "Elegir almacén de claves de cliente de Cassandra",
|
||||
cassandraKeystoreHint: "Almacén de claves JKS o PKCS#12 opcional para la autenticación con certificado de cliente.",
|
||||
cassandraKeystorePasswordRequiresPath: "Selecciona un almacén de claves de cliente de Cassandra antes de introducir su contraseña.",
|
||||
damengSslFilesPath: "Directorio de certificados",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "Seleccionar directorio de certificados",
|
||||
|
||||
@@ -545,6 +545,18 @@ export default withEnglishFallback({
|
||||
caCertPath: "Certificato CA",
|
||||
caCertPathPlaceholder: "Opzionale, es. ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "Sfoglia certificato",
|
||||
cassandraTruststore: "Truststore",
|
||||
cassandraTruststorePlaceholder: "/percorso/di/client.truststore",
|
||||
cassandraTruststorePassword: "Password del truststore",
|
||||
cassandraTruststoreBrowse: "Scegli truststore Cassandra",
|
||||
cassandraTruststoreHint: "Truststore JKS o PKCS#12 usato per verificare i certificati del server Cassandra.",
|
||||
cassandraTruststorePasswordRequiresPath: "Seleziona un truststore Cassandra prima di inserirne la password.",
|
||||
cassandraKeystore: "Keystore client",
|
||||
cassandraKeystorePlaceholder: "/percorso/di/client.keystore",
|
||||
cassandraKeystorePassword: "Password del keystore",
|
||||
cassandraKeystoreBrowse: "Scegli keystore client Cassandra",
|
||||
cassandraKeystoreHint: "Keystore JKS o PKCS#12 facoltativo per l'autenticazione con certificato client.",
|
||||
cassandraKeystorePasswordRequiresPath: "Seleziona un keystore client Cassandra prima di inserirne la password.",
|
||||
damengSslFilesPath: "Directory certificati",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "Seleziona directory certificati",
|
||||
|
||||
@@ -545,6 +545,18 @@ export default withEnglishFallback({
|
||||
caCertPath: "CA証明書",
|
||||
caCertPathPlaceholder: "任意、例: ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "証明書を参照",
|
||||
cassandraTruststore: "トラストストア",
|
||||
cassandraTruststorePlaceholder: "/path/to/client.truststore",
|
||||
cassandraTruststorePassword: "トラストストアのパスワード",
|
||||
cassandraTruststoreBrowse: "Cassandra トラストストアを選択",
|
||||
cassandraTruststoreHint: "Cassandra サーバー証明書の検証に使用する JKS または PKCS#12 トラストストア。",
|
||||
cassandraTruststorePasswordRequiresPath: "パスワードを入力する前に Cassandra トラストストアを選択してください。",
|
||||
cassandraKeystore: "クライアントキーストア",
|
||||
cassandraKeystorePlaceholder: "/path/to/client.keystore",
|
||||
cassandraKeystorePassword: "キーストアのパスワード",
|
||||
cassandraKeystoreBrowse: "Cassandra クライアントキーストアを選択",
|
||||
cassandraKeystoreHint: "クライアント証明書認証用のオプションの JKS / PKCS#12 キーストア。",
|
||||
cassandraKeystorePasswordRequiresPath: "パスワードを入力する前に Cassandra クライアントキーストアを選択してください。",
|
||||
damengSslFilesPath: "証明書ディレクトリ",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "証明書ディレクトリを選択",
|
||||
|
||||
@@ -561,6 +561,18 @@ export default withEnglishFallback({
|
||||
caCertPath: "CA 인증서",
|
||||
caCertPathPlaceholder: "선택, 예: ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "인증서 찾아보기",
|
||||
cassandraTruststore: "트러스트스토어",
|
||||
cassandraTruststorePlaceholder: "/path/to/client.truststore",
|
||||
cassandraTruststorePassword: "트러스트스토어 비밀번호",
|
||||
cassandraTruststoreBrowse: "Cassandra 트러스트스토어 선택",
|
||||
cassandraTruststoreHint: "Cassandra 서버 인증서를 검증하는 JKS 또는 PKCS#12 트러스트스토어.",
|
||||
cassandraTruststorePasswordRequiresPath: "비밀번호를 입력하기 전에 Cassandra 트러스트스토어를 먼저 선택하세요.",
|
||||
cassandraKeystore: "클라이언트 키스토어",
|
||||
cassandraKeystorePlaceholder: "/path/to/client.keystore",
|
||||
cassandraKeystorePassword: "키스토어 비밀번호",
|
||||
cassandraKeystoreBrowse: "Cassandra 클라이언트 키스토어 선택",
|
||||
cassandraKeystoreHint: "클라이언트 인증서 인증용 선택적 JKS / PKCS#12 키스토어.",
|
||||
cassandraKeystorePasswordRequiresPath: "비밀번호를 입력하기 전에 Cassandra 클라이언트 키스토어를 먼저 선택하세요.",
|
||||
damengSslFilesPath: "인증서 디렉터리",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "인증서 디렉터리 선택",
|
||||
|
||||
@@ -546,6 +546,18 @@ export default withEnglishFallback({
|
||||
caCertPath: "Certificado CA",
|
||||
caCertPathPlaceholder: "Opcional, ex.: ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "Procurar certificado",
|
||||
cassandraTruststore: "Truststore",
|
||||
cassandraTruststorePlaceholder: "/caminho/do/client.truststore",
|
||||
cassandraTruststorePassword: "Senha do truststore",
|
||||
cassandraTruststoreBrowse: "Escolher truststore do Cassandra",
|
||||
cassandraTruststoreHint: "Truststore JKS ou PKCS#12 usado para verificar os certificados do servidor Cassandra.",
|
||||
cassandraTruststorePasswordRequiresPath: "Selecione um truststore do Cassandra antes de informar a senha.",
|
||||
cassandraKeystore: "Keystore do cliente",
|
||||
cassandraKeystorePlaceholder: "/caminho/do/client.keystore",
|
||||
cassandraKeystorePassword: "Senha do keystore",
|
||||
cassandraKeystoreBrowse: "Escolher keystore de cliente do Cassandra",
|
||||
cassandraKeystoreHint: "Keystore JKS ou PKCS#12 opcional para autenticação por certificado de cliente.",
|
||||
cassandraKeystorePasswordRequiresPath: "Selecione um keystore de cliente do Cassandra antes de informar a senha.",
|
||||
damengSslFilesPath: "Diretório de certificados",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "Selecionar diretório de certificados",
|
||||
|
||||
@@ -568,6 +568,18 @@ export default withEnglishFallback({
|
||||
caCertPath: "CA Sertifikası",
|
||||
caCertPathPlaceholder: "İsteğe bağlı, örn. ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "Sertifikaya gözat",
|
||||
cassandraTruststore: "Güven deposu",
|
||||
cassandraTruststorePlaceholder: "/yol/client.truststore",
|
||||
cassandraTruststorePassword: "Güven deposu parolası",
|
||||
cassandraTruststoreBrowse: "Cassandra güven deposunu seç",
|
||||
cassandraTruststoreHint: "Cassandra sunucu sertifikalarını doğrulamak için kullanılan JKS veya PKCS#12 güven deposu.",
|
||||
cassandraTruststorePasswordRequiresPath: "Parolayı girmeden önce bir Cassandra güven deposu seçin.",
|
||||
cassandraKeystore: "İstemci anahtar deposu",
|
||||
cassandraKeystorePlaceholder: "/yol/client.keystore",
|
||||
cassandraKeystorePassword: "Anahtar deposu parolası",
|
||||
cassandraKeystoreBrowse: "Cassandra istemci anahtar deposunu seç",
|
||||
cassandraKeystoreHint: "İstemci sertifikası kimlik doğrulaması için isteğe bağlı JKS veya PKCS#12 anahtar deposu.",
|
||||
cassandraKeystorePasswordRequiresPath: "Parolayı girmeden önce bir Cassandra istemci anahtar deposu seçin.",
|
||||
damengSslFilesPath: "Sertifika dizini",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "Sertifika dizinini seçin",
|
||||
|
||||
@@ -492,6 +492,18 @@ export default withEnglishFallback({
|
||||
caCertPath: "CA 证书",
|
||||
caCertPathPlaceholder: "可选,例如 ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "选择证书",
|
||||
cassandraTruststore: "信任库",
|
||||
cassandraTruststorePlaceholder: "/path/to/client.truststore",
|
||||
cassandraTruststorePassword: "信任库密码",
|
||||
cassandraTruststoreBrowse: "选择 Cassandra 信任库",
|
||||
cassandraTruststoreHint: "用于验证 Cassandra 服务端证书的 JKS 或 PKCS#12 信任库。",
|
||||
cassandraTruststorePasswordRequiresPath: "输入密码前请先选择 Cassandra 信任库。",
|
||||
cassandraKeystore: "客户端密钥库",
|
||||
cassandraKeystorePlaceholder: "/path/to/client.keystore",
|
||||
cassandraKeystorePassword: "密钥库密码",
|
||||
cassandraKeystoreBrowse: "选择 Cassandra 客户端密钥库",
|
||||
cassandraKeystoreHint: "可选,用于客户端证书认证的 JKS 或 PKCS#12 密钥库。",
|
||||
cassandraKeystorePasswordRequiresPath: "输入密码前请先选择 Cassandra 客户端密钥库。",
|
||||
damengSslFilesPath: "证书目录",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "选择证书目录",
|
||||
|
||||
@@ -546,6 +546,18 @@ export default withEnglishFallback({
|
||||
caCertPath: "CA 憑證",
|
||||
caCertPathPlaceholder: "可選,例如 ~/.yandex/RootCA.crt",
|
||||
caCertPathBrowse: "瀏覽憑證",
|
||||
cassandraTruststore: "信任庫",
|
||||
cassandraTruststorePlaceholder: "/path/to/client.truststore",
|
||||
cassandraTruststorePassword: "信任庫密碼",
|
||||
cassandraTruststoreBrowse: "選擇 Cassandra 信任庫",
|
||||
cassandraTruststoreHint: "用於驗證 Cassandra 伺服器憑證的 JKS 或 PKCS#12 信任庫。",
|
||||
cassandraTruststorePasswordRequiresPath: "輸入密碼前請先選擇 Cassandra 信任庫。",
|
||||
cassandraKeystore: "用戶端金鑰庫",
|
||||
cassandraKeystorePlaceholder: "/path/to/client.keystore",
|
||||
cassandraKeystorePassword: "金鑰庫密碼",
|
||||
cassandraKeystoreBrowse: "選擇 Cassandra 用戶端金鑰庫",
|
||||
cassandraKeystoreHint: "可選,用於用戶端憑證驗證的 JKS 或 PKCS#12 金鑰庫。",
|
||||
cassandraKeystorePasswordRequiresPath: "輸入密碼前請先選擇 Cassandra 用戶端金鑰庫。",
|
||||
damengSslFilesPath: "憑證目錄",
|
||||
damengSslFilesPathPlaceholder: "/path/to/dmcert",
|
||||
damengSslFilesPathBrowse: "選擇憑證目錄",
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildCassandraExternalConfig, cassandraTlsConfigFromExternalConfig } from "../cassandraTlsOptions";
|
||||
|
||||
describe("Cassandra TLS options", () => {
|
||||
it("reads validated truststore and keystore fields", () => {
|
||||
expect(
|
||||
cassandraTlsConfigFromExternalConfig({
|
||||
tls: {
|
||||
truststore_path: "/certs/client.truststore",
|
||||
truststore_password: "trust-secret",
|
||||
keystore_path: "/certs/client.keystore",
|
||||
keystore_password: "key-secret",
|
||||
ignored: true,
|
||||
},
|
||||
}),
|
||||
).toEqual({
|
||||
truststore_path: "/certs/client.truststore",
|
||||
truststore_password: "trust-secret",
|
||||
keystore_path: "/certs/client.keystore",
|
||||
keystore_password: "key-secret",
|
||||
});
|
||||
});
|
||||
|
||||
it("ignores malformed external values", () => {
|
||||
expect(cassandraTlsConfigFromExternalConfig({ tls: { truststore_path: 42 } })).toEqual({
|
||||
truststore_path: "",
|
||||
truststore_password: "",
|
||||
keystore_path: "",
|
||||
keystore_password: "",
|
||||
});
|
||||
});
|
||||
|
||||
it("trims paths without changing passwords", () => {
|
||||
expect(
|
||||
buildCassandraExternalConfig({
|
||||
truststore_path: " /certs/client.p12 ",
|
||||
truststore_password: " trust-secret ",
|
||||
keystore_path: " /certs/client.jks ",
|
||||
keystore_password: " key-secret ",
|
||||
}),
|
||||
).toEqual({
|
||||
tls: {
|
||||
truststore_path: "/certs/client.p12",
|
||||
truststore_password: " trust-secret ",
|
||||
keystore_path: "/certs/client.jks",
|
||||
keystore_password: " key-secret ",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("omits empty TLS store configuration", () => {
|
||||
expect(
|
||||
buildCassandraExternalConfig({
|
||||
truststore_path: "",
|
||||
truststore_password: "",
|
||||
keystore_path: "",
|
||||
keystore_password: "",
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
export interface CassandraTlsConfig {
|
||||
truststore_path: string;
|
||||
truststore_password: string;
|
||||
keystore_path: string;
|
||||
keystore_password: string;
|
||||
}
|
||||
|
||||
export interface CassandraExternalConfig {
|
||||
tls: CassandraTlsConfig;
|
||||
}
|
||||
|
||||
function stringField(value: unknown, key: keyof CassandraTlsConfig): string {
|
||||
if (!value || typeof value !== "object") return "";
|
||||
const field = (value as Record<string, unknown>)[key];
|
||||
return typeof field === "string" ? field : "";
|
||||
}
|
||||
|
||||
export function cassandraTlsConfigFromExternalConfig(value: unknown): CassandraTlsConfig {
|
||||
const tls = value && typeof value === "object" ? (value as Record<string, unknown>).tls : undefined;
|
||||
return {
|
||||
truststore_path: stringField(tls, "truststore_path"),
|
||||
truststore_password: stringField(tls, "truststore_password"),
|
||||
keystore_path: stringField(tls, "keystore_path"),
|
||||
keystore_password: stringField(tls, "keystore_password"),
|
||||
};
|
||||
}
|
||||
|
||||
export function buildCassandraExternalConfig(tls: CassandraTlsConfig): CassandraExternalConfig | undefined {
|
||||
const truststorePath = tls.truststore_path.trim();
|
||||
const keystorePath = tls.keystore_path.trim();
|
||||
if (!truststorePath && !tls.truststore_password && !keystorePath && !tls.keystore_password) return undefined;
|
||||
return {
|
||||
tls: {
|
||||
truststore_path: truststorePath,
|
||||
truststore_password: tls.truststore_password,
|
||||
keystore_path: keystorePath,
|
||||
keystore_password: tls.keystore_password,
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user