mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-23 01:11:06 +08:00
- 新增 CA 证书、客户端证书和私钥路径配置 - 为 MySQL、PostgreSQL、ClickHouse、MongoDB、Redis 等连接接入 TLS 证书 - 修正 SSL 模式下证书校验、明文回退和 DER 证书兼容问题 - 补充证书路径保存、RPC 传递和 DSN 生成回归测试 Refs #463
178 lines
4.9 KiB
Go
178 lines
4.9 KiB
Go
package db
|
||
|
||
import (
|
||
"crypto/sha256"
|
||
"crypto/tls"
|
||
"encoding/hex"
|
||
"strings"
|
||
|
||
"GoNavi-Wails/internal/connection"
|
||
"GoNavi-Wails/internal/tlsconfig"
|
||
)
|
||
|
||
const (
|
||
sslModeDisable = "disable"
|
||
sslModePreferred = "preferred"
|
||
sslModeRequired = "required"
|
||
sslModeSkipVerify = "skip-verify"
|
||
)
|
||
|
||
func normalizeSSLModeValue(raw string) string {
|
||
mode := strings.ToLower(strings.TrimSpace(raw))
|
||
switch mode {
|
||
case "", sslModePreferred, "prefer":
|
||
return sslModePreferred
|
||
case sslModeRequired, "require", "on", "true", "mandatory", "strict":
|
||
return sslModeRequired
|
||
case sslModeSkipVerify, "insecure", "skipverify", "skip_verify", "insecure-skip-verify":
|
||
return sslModeSkipVerify
|
||
case sslModeDisable, "disabled", "off", "false", "none":
|
||
return sslModeDisable
|
||
default:
|
||
return sslModePreferred
|
||
}
|
||
}
|
||
|
||
func normalizedSSLMode(config connection.ConnectionConfig) string {
|
||
if !config.UseSSL {
|
||
return sslModeDisable
|
||
}
|
||
return normalizeSSLModeValue(config.SSLMode)
|
||
}
|
||
|
||
func shouldTrySSLPreferredFallback(config connection.ConnectionConfig) bool {
|
||
return config.UseSSL && normalizeSSLModeValue(config.SSLMode) == sslModePreferred
|
||
}
|
||
|
||
func withSSLDisabled(config connection.ConnectionConfig) connection.ConnectionConfig {
|
||
next := config
|
||
next.UseSSL = false
|
||
next.SSLMode = sslModeDisable
|
||
return next
|
||
}
|
||
|
||
func resolveMySQLTLSMode(config connection.ConnectionConfig) string {
|
||
switch normalizedSSLMode(config) {
|
||
case sslModeDisable:
|
||
return "false"
|
||
case sslModeRequired:
|
||
return "true"
|
||
case sslModeSkipVerify:
|
||
return "skip-verify"
|
||
default:
|
||
return "preferred"
|
||
}
|
||
}
|
||
|
||
func hasTLSCertificatePaths(config connection.ConnectionConfig) bool {
|
||
return strings.TrimSpace(config.SSLCAPath) != "" ||
|
||
strings.TrimSpace(config.SSLCertPath) != "" ||
|
||
strings.TrimSpace(config.SSLKeyPath) != ""
|
||
}
|
||
|
||
func mysqlTLSConfigName(config connection.ConnectionConfig) string {
|
||
sum := sha256.Sum256([]byte(strings.Join([]string{
|
||
normalizedSSLMode(config),
|
||
strings.TrimSpace(config.SSLCAPath),
|
||
strings.TrimSpace(config.SSLCertPath),
|
||
strings.TrimSpace(config.SSLKeyPath),
|
||
}, "\x00")))
|
||
return "gonavi-" + hex.EncodeToString(sum[:8])
|
||
}
|
||
|
||
func resolvePostgresSSLMode(config connection.ConnectionConfig) string {
|
||
switch normalizedSSLMode(config) {
|
||
case sslModeDisable:
|
||
return "disable"
|
||
case sslModeRequired:
|
||
if strings.TrimSpace(config.SSLCAPath) != "" {
|
||
return "verify-ca"
|
||
}
|
||
return "require"
|
||
case sslModeSkipVerify:
|
||
return "require"
|
||
default:
|
||
if strings.TrimSpace(config.SSLCAPath) != "" {
|
||
return "verify-ca"
|
||
}
|
||
return "require"
|
||
}
|
||
}
|
||
|
||
func resolveSQLServerTLSSettings(config connection.ConnectionConfig) (encrypt string, trustServerCertificate string) {
|
||
switch normalizedSSLMode(config) {
|
||
case sslModeDisable:
|
||
return "disable", "true"
|
||
case sslModeRequired:
|
||
return "true", "false"
|
||
case sslModeSkipVerify:
|
||
return "true", "true"
|
||
default:
|
||
return "false", "true"
|
||
}
|
||
}
|
||
|
||
func applyPostgresSSLPathParams(params interface{ Set(string, string) }, config connection.ConnectionConfig) {
|
||
mode := normalizedSSLMode(config)
|
||
if mode != sslModeDisable && mode != sslModeSkipVerify && strings.TrimSpace(config.SSLCAPath) != "" {
|
||
params.Set("sslrootcert", strings.TrimSpace(config.SSLCAPath))
|
||
}
|
||
if mode != sslModeDisable && strings.TrimSpace(config.SSLCertPath) != "" {
|
||
params.Set("sslcert", strings.TrimSpace(config.SSLCertPath))
|
||
}
|
||
if mode != sslModeDisable && strings.TrimSpace(config.SSLKeyPath) != "" {
|
||
params.Set("sslkey", strings.TrimSpace(config.SSLKeyPath))
|
||
}
|
||
}
|
||
|
||
func resolveGenericTLSConfig(config connection.ConnectionConfig) (*tls.Config, error) {
|
||
switch normalizedSSLMode(config) {
|
||
case sslModeDisable:
|
||
return nil, nil
|
||
case sslModeRequired:
|
||
return tlsconfig.BuildClientConfig(tlsconfig.ClientConfigOptions{
|
||
Enabled: true,
|
||
CAPath: config.SSLCAPath,
|
||
CertPath: config.SSLCertPath,
|
||
KeyPath: config.SSLKeyPath,
|
||
})
|
||
case sslModeSkipVerify:
|
||
return tlsconfig.BuildClientConfig(tlsconfig.ClientConfigOptions{
|
||
Enabled: true,
|
||
InsecureSkipVerify: true,
|
||
CAPath: config.SSLCAPath,
|
||
CertPath: config.SSLCertPath,
|
||
KeyPath: config.SSLKeyPath,
|
||
})
|
||
default:
|
||
// Preferred: 先尝试 TLS(为提升兼容性默认跳过证书校验),失败时由调用方按需回退明文。
|
||
return tlsconfig.BuildClientConfig(tlsconfig.ClientConfigOptions{
|
||
Enabled: true,
|
||
InsecureSkipVerify: true,
|
||
CAPath: config.SSLCAPath,
|
||
CertPath: config.SSLCertPath,
|
||
KeyPath: config.SSLKeyPath,
|
||
})
|
||
}
|
||
}
|
||
|
||
func resolveMongoTLSSettings(config connection.ConnectionConfig) (enabled bool, insecure bool) {
|
||
switch normalizedSSLMode(config) {
|
||
case sslModeDisable:
|
||
return false, false
|
||
case sslModeRequired:
|
||
return true, false
|
||
case sslModeSkipVerify:
|
||
return true, true
|
||
default:
|
||
return true, true
|
||
}
|
||
}
|
||
|
||
func resolveTDengineNet(config connection.ConnectionConfig) string {
|
||
if normalizedSSLMode(config) == sslModeDisable {
|
||
return "ws"
|
||
}
|
||
return "wss"
|
||
}
|