feat(raft): TLS config surface with fail-closed startup

This commit is contained in:
2026-07-31 01:14:20 +03:00
parent efa46b05c6
commit 8d083f5fdc
3 changed files with 52 additions and 0 deletions
+15
View File
@@ -44,6 +44,11 @@ type
raftPeerClientAddrs*: Table[string, tuple[host: string, port: int]]
raftWriteTimeoutMs*: int
raftLogMaxEntries*: int
raftTlsEnabled*: bool
raftTlsCertFile*: string
raftTlsKeyFile*: string
raftTlsCaFile*: string
raftTlsVerifyPeer*: bool
CompactionStrategy* = enum
csSizeTiered = "size_tiered"
@@ -86,6 +91,11 @@ proc defaultConfig*(): BaraConfig =
raftPeerClientAddrs: initTable[string, tuple[host: string, port: int]](),
raftWriteTimeoutMs: 5_000,
raftLogMaxEntries: 256,
raftTlsEnabled: false,
raftTlsCertFile: "",
raftTlsKeyFile: "",
raftTlsCaFile: "",
raftTlsVerifyPeer: false,
)
# ----------------------------------------------------------------------
@@ -213,6 +223,11 @@ proc loadConfigFromEnv*(cfg: var BaraConfig) =
cfg.raftNodeId = getEnv("BARADB_RAFT_NODE_ID", cfg.raftNodeId)
cfg.raftWriteTimeoutMs = parseEnvInt(getEnv("BARADB_RAFT_WRITE_TIMEOUT_MS", ""), cfg.raftWriteTimeoutMs)
cfg.raftLogMaxEntries = parseEnvInt(getEnv("BARADB_RAFT_LOG_MAX_ENTRIES", ""), cfg.raftLogMaxEntries)
cfg.raftTlsEnabled = parseEnvBool(getEnv("BARADB_RAFT_TLS_ENABLED", ""), cfg.raftTlsEnabled)
cfg.raftTlsCertFile = getEnv("BARADB_RAFT_TLS_CERT_FILE", cfg.raftTlsCertFile)
cfg.raftTlsKeyFile = getEnv("BARADB_RAFT_TLS_KEY_FILE", cfg.raftTlsKeyFile)
cfg.raftTlsCaFile = getEnv("BARADB_RAFT_TLS_CA_FILE", cfg.raftTlsCaFile)
cfg.raftTlsVerifyPeer = parseEnvBool(getEnv("BARADB_RAFT_TLS_VERIFY_PEER", ""), cfg.raftTlsVerifyPeer)
# Optional: client (SQL) addresses for leader write forwarding.
# Same id@host:port shape as BARADB_RAFT_PEERS, but ports are BARADB_PORT values.
let clientPeersEnv = getEnv("BARADB_RAFT_CLIENT_PEERS", "")
+6
View File
@@ -338,6 +338,12 @@ proc main() =
var raftNet: RaftNetwork = nil
if config.raftEnabled:
info("Starting Raft node " & config.raftNodeId & " on port " & $config.raftPort)
if config.raftTlsEnabled:
if config.raftTlsCertFile.len == 0 or config.raftTlsKeyFile.len == 0 or
not fileExists(config.raftTlsCertFile) or not fileExists(config.raftTlsKeyFile):
raise newException(ValueError,
"BARADB_RAFT_TLS_ENABLED=true but cert/key missing " &
"(BARADB_RAFT_TLS_CERT_FILE / BARADB_RAFT_TLS_KEY_FILE)")
let raftDataDir = config.dataDir / "raft"
createDir(raftDataDir) # idempotent; loadState reads from it, saveState writes
# Raft convention: `peers` excludes the node itself (majority math and
+31
View File
@@ -521,3 +521,34 @@ suite "Raft write classification":
check not isRaftDdl(parse("CREATE DATABASE other").stmts[0])
check not isRaftDdl(parse("INSERT INTO t (id) VALUES (1)").stmts[0])
check not isRaftDdl(parse("SELECT 1").stmts[0])
suite "Raft TLS config":
test "default config has raft TLS disabled with empty paths":
let cfg = defaultConfig()
check cfg.raftTlsEnabled == false
check cfg.raftTlsCertFile == ""
check cfg.raftTlsKeyFile == ""
check cfg.raftTlsCaFile == ""
check cfg.raftTlsVerifyPeer == false
test "env vars parse into raft TLS config":
putEnv("BARADB_RAFT_TLS_ENABLED", "true")
putEnv("BARADB_RAFT_TLS_CERT_FILE", "/tmp/raft.crt")
putEnv("BARADB_RAFT_TLS_KEY_FILE", "/tmp/raft.key")
putEnv("BARADB_RAFT_TLS_CA_FILE", "/tmp/raft-ca.crt")
putEnv("BARADB_RAFT_TLS_VERIFY_PEER", "1")
defer:
delEnv("BARADB_RAFT_TLS_ENABLED")
delEnv("BARADB_RAFT_TLS_CERT_FILE")
delEnv("BARADB_RAFT_TLS_KEY_FILE")
delEnv("BARADB_RAFT_TLS_CA_FILE")
delEnv("BARADB_RAFT_TLS_VERIFY_PEER")
var cfg = defaultConfig()
loadConfigFromEnv(cfg)
check cfg.raftTlsEnabled == true
check cfg.raftTlsCertFile == "/tmp/raft.crt"
check cfg.raftTlsKeyFile == "/tmp/raft.key"
check cfg.raftTlsCaFile == "/tmp/raft-ca.crt"
check cfg.raftTlsVerifyPeer == true