feat(cassandra): add TLS store support

This commit is contained in:
以谶 authored and GitHub committed 2026-09-10 00:28:58 +08:00
1 parent e2240d4ed1
commit 38be5ba35c
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">
+12
View File
@@ -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",
+12
View File
@@ -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",
+12
View File
@@ -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",
+12
View File
@@ -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",
+12
View File
@@ -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: "証明書ディレクトリを選択",
+12
View File
@@ -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: "인증서 디렉터리 선택",
+12
View File
@@ -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",
+12
View File
@@ -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",
+12
View File
@@ -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: "选择证书目录",
+12
View File
@@ -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,
},
};
}