fix(postgres): 支持旧版 TLS 兼容模式

This commit is contained in:
zipg authored and t8y2 committed 2026-08-21 10:52:27 +08:00
1 parent 12da615daa
commit ab0ff28fe4
16 files changed
+537 -20

No files matched your search

@@ -60,7 +60,7 @@ import { connectionAttemptOriginalErrorMessage, connectionAttemptTimeoutMessage,
import { consulAgentAddressesMatch } from "@/lib/consul/agentTarget";
import { appendConnectionErrorHints, isJdbcMissingRuntimeDependencyError } from "@/lib/connection/connectionErrorHints";
import { preventDialogDocumentSelectAll } from "@/lib/connection/dialogTextSelection";
import { postgresTlsModeForForm } from "@/lib/connection/postgresTlsMode";
import { postgresLegacyTlsEnabled, postgresTlsModeForForm, setPostgresLegacyTlsEnabled } from "@/lib/connection/postgresTlsMode";
import { buildMqKafkaConnectionExtra, mqKafkaConnectionTarget, resolveMqKafkaConnectionSource, type MqKafkaConnectionSource } from "@/lib/connection/mqKafkaConnection";
import { assertCompleteDatabaseCategories, databaseSelectionForCategory } from "@/lib/connection/databaseCategoryOptions";
import { loadConnectionPickerView, saveConnectionPickerView, type DbPickerView } from "@/lib/connection/connectionPickerViewPreference";
@@ -3424,6 +3424,12 @@ const postgresTlsMode = computed({
form.value.url_params = setUrlParam(form.value.url_params, "sslmode", value);
},
});
const postgresLegacyTls = computed({
get: () => postgresLegacyTlsEnabled(form.value.url_params),
set: (value: boolean) => {
form.value.url_params = setPostgresLegacyTlsEnabled(form.value.url_params, value);
},
});
const postgresRootCertPath = computed({
get: () => getUrlParam(form.value.url_params, "sslrootcert"),
set: (value: string) => {
@@ -8166,6 +8172,16 @@ function openExternalUrl(url: string) {
</Select>
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label :class="connectionLabelSmallClass">{{ t("connection.postgresLegacyTls") }}</Label>
<div class="col-span-3 flex items-center gap-2">
<Switch v-model="postgresLegacyTls" :disabled="postgresTlsMode === 'disable'" />
<HelpTooltip :label="t('connection.postgresLegacyTlsHint')">
{{ t("connection.postgresLegacyTlsHint") }}
</HelpTooltip>
</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">
+2
View File
@@ -582,6 +582,8 @@ export default {
postgresSslModeRequire: "Require",
postgresSslModeVerifyCa: "Verify CA",
postgresSslModeVerifyFull: "Verify Full",
postgresLegacyTls: "Legacy TLS compatibility",
postgresLegacyTlsHint: "Supports servers restricted to TLS 1.2 static RSA key exchange. This is less secure than the default mode; enable it only when the server TLS configuration cannot be upgraded.",
postgresServerCert: "Server CA",
postgresRootCertPlaceholder: "/path/to/ca.crt",
postgresRootCertHint: "Use this for verify-ca or verify-full when the server certificate is signed by a private CA.",
+2
View File
@@ -557,6 +557,8 @@ export default withEnglishFallback({
postgresSslModeRequire: "Requerir",
postgresSslModeVerifyCa: "Verificar CA",
postgresSslModeVerifyFull: "Verificar completo",
postgresLegacyTls: "Compatibilidad con TLS antiguo",
postgresLegacyTlsHint: "Admite servidores limitados al intercambio de claves RSA estático de TLS 1.2. Es menos seguro que el modo predeterminado; actívelo solo si no se puede actualizar la configuración TLS del servidor.",
postgresServerCert: "CA del servidor",
postgresRootCertPlaceholder: "/ruta/a/ca.crt",
postgresRootCertHint: "Úsalo con verify-ca o verify-full cuando el certificado del servidor use una CA privada.",
+2
View File
@@ -556,6 +556,8 @@ export default withEnglishFallback({
postgresSslModeRequire: "Richiedi",
postgresSslModeVerifyCa: "Verifica CA",
postgresSslModeVerifyFull: "Verifica Completa",
postgresLegacyTls: "Compatibilità TLS legacy",
postgresLegacyTlsHint: "Supporta i server limitati allo scambio di chiavi RSA statico di TLS 1.2. È meno sicuro della modalità predefinita; abilitalo solo se non è possibile aggiornare la configurazione TLS del server.",
postgresServerCert: "CA Server",
postgresRootCertPlaceholder: "/percorso/per/ca.crt",
postgresRootCertHint: "Usa questo per verifica-ca o verifica-completa quando il certificato del server è firmato da una CA privata.",
+2
View File
@@ -556,6 +556,8 @@ export default withEnglishFallback({
postgresSslModeRequire: "必須にする",
postgresSslModeVerifyCa: "CA検証",
postgresSslModeVerifyFull: "完全検証",
postgresLegacyTls: "旧式TLS互換",
postgresLegacyTlsHint: "TLS 1.2の静的RSA鍵交換に制限されたサーバーをサポートします。既定モードより安全性が低いため、サーバーのTLS設定を更新できない場合にのみ有効にしてください。",
postgresServerCert: "サーバーCA",
postgresRootCertPlaceholder: "/path/to/ca.crt",
postgresRootCertHint: "サーバー証明書がプライベートCAで署名されている場合、verify-caまたはverify-fullに使用します。",
+2
View File
@@ -576,6 +576,8 @@ export default withEnglishFallback({
postgresSslModeRequire: "필수",
postgresSslModeVerifyCa: "CA 확인",
postgresSslModeVerifyFull: "전체 확인",
postgresLegacyTls: "레거시 TLS 호환성",
postgresLegacyTlsHint: "TLS 1.2 정적 RSA 키 교환만 지원하는 서버와의 연결을 지원합니다. 기본 모드보다 보안 수준이 낮으므로 서버 TLS 구성을 업그레이드할 수 없는 경우에만 활성화하세요.",
postgresServerCert: "서버 CA",
postgresRootCertPlaceholder: "/path/to/ca.crt",
postgresRootCertHint: "서버 인증서가 사설 CA로 서명된 경우 verify-ca 또는 verify-full에 사용하세요.",
+2
View File
@@ -557,6 +557,8 @@ export default withEnglishFallback({
postgresSslModeRequire: "Obrigatório",
postgresSslModeVerifyCa: "Verificar CA",
postgresSslModeVerifyFull: "Verificar Completo",
postgresLegacyTls: "Compatibilidade com TLS legado",
postgresLegacyTlsHint: "Oferece suporte a servidores restritos à troca de chaves RSA estática do TLS 1.2. É menos seguro que o modo padrão; ative somente quando não for possível atualizar a configuração TLS do servidor.",
postgresServerCert: "CA do Servidor",
postgresRootCertPlaceholder: "/caminho/para/ca.crt",
postgresRootCertHint: "Use isto para verify-ca ou verify-full quando o certificado do servidor é assinado por uma CA privada.",
+2
View File
@@ -507,6 +507,8 @@ export default withEnglishFallback({
postgresSslModeRequire: "必须使用",
postgresSslModeVerifyCa: "验证 CA",
postgresSslModeVerifyFull: "完整验证",
postgresLegacyTls: "旧版 TLS 兼容",
postgresLegacyTlsHint: "兼容仅支持 TLS 1.2 静态 RSA 密钥交换的服务器。安全性低于默认模式,请仅在无法升级服务端 TLS 配置时启用。",
postgresServerCert: "服务端 CA",
postgresRootCertPlaceholder: "/path/to/ca.crt",
postgresRootCertHint: "服务端证书由私有 CA 签发时,在 verify-ca 或 verify-full 模式下填写。",
+2
View File
@@ -557,6 +557,8 @@ export default withEnglishFallback({
postgresSslModeRequire: "必須使用",
postgresSslModeVerifyCa: "驗證 CA",
postgresSslModeVerifyFull: "完整驗證",
postgresLegacyTls: "舊版 TLS 相容",
postgresLegacyTlsHint: "相容僅支援 TLS 1.2 靜態 RSA 金鑰交換的伺服器。安全性低於預設模式,請僅在無法升級伺服器 TLS 設定時啟用。",
postgresServerCert: "伺服器端 CA",
postgresRootCertPlaceholder: "/path/to/ca.crt",
postgresRootCertHint: "伺服器端憑證由私有 CA 簽發時,在 verify-ca 或 verify-full 模式下填寫。",
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { postgresTlsModeForForm } from "@/lib/connection/postgresTlsMode";
import { postgresLegacyTlsEnabled, postgresTlsModeForForm, setPostgresLegacyTlsEnabled } from "@/lib/connection/postgresTlsMode";
describe("postgresTlsModeForForm", () => {
it("uses prefer when legacy connections have no explicit mode", () => {
@@ -16,3 +16,17 @@ describe("postgresTlsModeForForm", () => {
expect(postgresTlsModeForForm("verify_identity", false)).toBe("verify-full");
});
});
describe("PostgreSQL legacy TLS compatibility", () => {
it("recognizes explicit enabled values", () => {
expect(postgresLegacyTlsEnabled("sslmode=require&legacy_tls=true")).toBe(true);
expect(postgresLegacyTlsEnabled("legacy_tls=1")).toBe(true);
expect(postgresLegacyTlsEnabled("legacy_tls=false")).toBe(false);
});
it("preserves unrelated URL parameters when toggled", () => {
const enabled = setPostgresLegacyTlsEnabled("sslmode=require&application_name=dbx", true);
expect(enabled).toBe("sslmode=require&application_name=dbx&legacy_tls=true");
expect(setPostgresLegacyTlsEnabled(enabled, false)).toBe("sslmode=require&application_name=dbx");
});
});
@@ -1,5 +1,7 @@
export type PostgresTlsMode = "disable" | "prefer" | "require" | "verify-ca" | "verify-full";
export const POSTGRES_LEGACY_TLS_PARAM = "legacy_tls";
export function postgresTlsModeForForm(value: string | undefined, ssl: boolean | undefined): PostgresTlsMode {
switch ((value || "").trim().toLowerCase()) {
case "disable":
@@ -17,3 +19,15 @@ export function postgresTlsModeForForm(value: string | undefined, ssl: boolean |
return ssl ? "require" : "prefer";
}
}
export function postgresLegacyTlsEnabled(params: string | undefined): boolean {
const parsed = new URLSearchParams((params || "").trim().replace(/^\?/, ""));
return ["1", "true", "yes", "on"].includes((parsed.get(POSTGRES_LEGACY_TLS_PARAM) || "").trim().toLowerCase());
}
export function setPostgresLegacyTlsEnabled(params: string | undefined, enabled: boolean): string {
const parsed = new URLSearchParams((params || "").trim().replace(/^\?/, ""));
if (enabled) parsed.set(POSTGRES_LEGACY_TLS_PARAM, "true");
else parsed.delete(POSTGRES_LEGACY_TLS_PARAM);
return parsed.toString();
}