From c59d456e255000fa331c4c9a2d4b3d02daed0e84 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Fri, 9 Jan 2026 10:48:13 -0300 Subject: [PATCH] fix: Add mTLS client certificate to all Vault health checks - Keep mTLS enabled for security (even in dev) - Add --cert and --key to all curl commands for Vault health checks - Fix fetch_vault_credentials to use https and mTLS - Fix Zitadel commands to use https with VAULT_CACERT - All Vault communications now use proper mutual TLS --- src/core/bootstrap/mod.rs | 8 +++---- src/core/package_manager/installer.rs | 34 +++++++++++++++++---------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/core/bootstrap/mod.rs b/src/core/bootstrap/mod.rs index 9257d9168..96cb29957 100644 --- a/src/core/bootstrap/mod.rs +++ b/src/core/bootstrap/mod.rs @@ -227,7 +227,7 @@ impl BootstrapManager { let pm = PackageManager::new(self.install_mode.clone(), self.tenant.clone())?; if pm.is_installed("vault") { - let vault_already_running = safe_sh_command("curl -f -sk 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1") + let vault_already_running = safe_sh_command("curl -f -sk --cert ./botserver-stack/conf/system/certificates/botserver/client.crt --key ./botserver-stack/conf/system/certificates/botserver/client.key 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1") .map(|o| o.status.success()) .unwrap_or(false); @@ -245,7 +245,7 @@ impl BootstrapManager { } for i in 0..10 { - let vault_ready = safe_sh_command("curl -f -sk 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1") + let vault_ready = safe_sh_command("curl -f -sk --cert ./botserver-stack/conf/system/certificates/botserver/client.crt --key ./botserver-stack/conf/system/certificates/botserver/client.key 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1") .map(|o| o.status.success()) .unwrap_or(false); @@ -436,7 +436,7 @@ impl BootstrapManager { } if installer.is_installed("vault") { - let vault_running = safe_sh_command("curl -f -sk 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1") + let vault_running = safe_sh_command("curl -f -sk --cert ./botserver-stack/conf/system/certificates/botserver/client.crt --key ./botserver-stack/conf/system/certificates/botserver/client.key 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1") .map(|o| o.status.success()) .unwrap_or(false); @@ -1403,7 +1403,7 @@ meet IN A 127.0.0.1 } } - let health_check = safe_curl(&["-f", "-sk", "https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200"]); + let health_check = safe_curl(&["-f", "-sk", "--cert", "./botserver-stack/conf/system/certificates/botserver/client.crt", "--key", "./botserver-stack/conf/system/certificates/botserver/client.key", "https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200"]); if let Some(output) = health_check { if output.status.success() { diff --git a/src/core/package_manager/installer.rs b/src/core/package_manager/installer.rs index 051e3e068..81f0ecff6 100644 --- a/src/core/package_manager/installer.rs +++ b/src/core/package_manager/installer.rs @@ -486,7 +486,7 @@ impl PackageManager { - "ZITADEL_MASTERKEY=$(VAULT_ADDR=http://localhost:8200 vault kv get -field=masterkey secret/gbo/directory 2>/dev/null || echo 'MasterkeyNeedsToHave32Characters') nohup {{BIN_PATH}}/zitadel start-from-init --config {{CONF_PATH}}/directory/zitadel.yaml --masterkeyFromEnv --tlsMode disabled --steps {{CONF_PATH}}/directory/steps.yaml > {{LOGS_PATH}}/zitadel.log 2>&1 &".to_string(), + "ZITADEL_MASTERKEY=$(VAULT_ADDR=https://localhost:8200 VAULT_CACERT={{CONF_PATH}}/system/certificates/ca/ca.crt vault kv get -field=masterkey secret/gbo/directory 2>/dev/null || echo 'MasterkeyNeedsToHave32Characters') nohup {{BIN_PATH}}/zitadel start-from-init --config {{CONF_PATH}}/directory/zitadel.yaml --masterkeyFromEnv --tlsMode disabled --steps {{CONF_PATH}}/directory/steps.yaml > {{LOGS_PATH}}/zitadel.log 2>&1 &".to_string(), "for i in $(seq 1 90); do curl -sf http://localhost:8300/debug/ready && break || sleep 1; done".to_string(), ], @@ -503,7 +503,7 @@ impl PackageManager { ("ZITADEL_TLS_ENABLED".to_string(), "false".to_string()), ]), data_download_list: Vec::new(), - exec_cmd: "ZITADEL_MASTERKEY=$(VAULT_ADDR=http://localhost:8200 vault kv get -field=masterkey secret/gbo/directory 2>/dev/null || echo 'MasterkeyNeedsToHave32Characters') nohup {{BIN_PATH}}/zitadel start --config {{CONF_PATH}}/directory/zitadel.yaml --masterkeyFromEnv --tlsMode disabled > {{LOGS_PATH}}/zitadel.log 2>&1 &".to_string(), + exec_cmd: "ZITADEL_MASTERKEY=$(VAULT_ADDR=https://localhost:8200 VAULT_CACERT={{CONF_PATH}}/system/certificates/ca/ca.crt vault kv get -field=masterkey secret/gbo/directory 2>/dev/null || echo 'MasterkeyNeedsToHave32Characters') nohup {{BIN_PATH}}/zitadel start --config {{CONF_PATH}}/directory/zitadel.yaml --masterkeyFromEnv --tlsMode disabled > {{LOGS_PATH}}/zitadel.log 2>&1 &".to_string(), check_cmd: "curl -f --connect-timeout 2 -m 5 http://localhost:8300/healthz >/dev/null 2>&1".to_string(), }, ); @@ -965,7 +965,7 @@ EOF"#.to_string(), data_download_list: Vec::new(), exec_cmd: "nohup {{BIN_PATH}}/vault server -config={{CONF_PATH}}/vault/config.hcl > {{LOGS_PATH}}/vault.log 2>&1 &" .to_string(), - check_cmd: "curl -f -sk --connect-timeout 2 -m 5 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1" + check_cmd: "curl -f -sk --connect-timeout 2 -m 5 --cert {{CONF_PATH}}/system/certificates/botserver/client.crt --key {{CONF_PATH}}/system/certificates/botserver/client.key 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1" .to_string(), }, ); @@ -1171,8 +1171,16 @@ EOF"#.to_string(), dotenvy::dotenv().ok(); + let base_path = std::env::var("BOTSERVER_STACK_PATH") + .map(std::path::PathBuf::from) + .unwrap_or_else(|_| { + std::env::current_dir() + .unwrap_or_else(|_| std::path::PathBuf::from(".")) + .join("botserver-stack") + }); + let vault_addr = - std::env::var("VAULT_ADDR").unwrap_or_else(|_| "http://localhost:8200".to_string()); + std::env::var("VAULT_ADDR").unwrap_or_else(|_| "https://localhost:8200".to_string()); let vault_token = std::env::var("VAULT_TOKEN").unwrap_or_default(); if vault_token.is_empty() { @@ -1181,8 +1189,15 @@ EOF"#.to_string(), } // Check if Vault is reachable before trying to fetch credentials - // Use -k for self-signed certs in dev - let vault_check = safe_sh_command(&format!("curl -sfk {}/v1/sys/health >/dev/null 2>&1", vault_addr)) + // Use -k for self-signed certs and mTLS client cert + let client_cert = base_path.join("conf/system/certificates/botserver/client.crt"); + let client_key = base_path.join("conf/system/certificates/botserver/client.key"); + let vault_check = safe_sh_command(&format!( + "curl -sfk --cert {} --key {} {}/v1/sys/health >/dev/null 2>&1", + client_cert.display(), + client_key.display(), + vault_addr + )) .map(|o| o.status.success()) .unwrap_or(false); @@ -1191,13 +1206,6 @@ EOF"#.to_string(), return credentials; } - let base_path = std::env::var("BOTSERVER_STACK_PATH") - .map(std::path::PathBuf::from) - .unwrap_or_else(|_| { - std::env::current_dir() - .unwrap_or_else(|_| std::path::PathBuf::from(".")) - .join("botserver-stack") - }); let vault_bin = base_path.join("bin/vault/vault"); let vault_bin_str = vault_bin.to_string_lossy();