fix: Use SafeCommand directly for vault health check to avoid shell injection false positive
All checks were successful
BotServer CI/CD / build (push) Successful in 6m46s
All checks were successful
BotServer CI/CD / build (push) Successful in 6m46s
- Replace safe_sh_command with SafeCommand::new("curl").args() in vault_health_check()
- The URL contains https:// which triggered '//' pattern detection in shell command
- Direct SafeCommand bypasses shell parsing, URL passed as single argument
- Add vault data directory existence check before recovery attempt
- Prevents 'Dangerous pattern // detected' errors during bootstrap
This commit is contained in:
parent
07a6c1edb3
commit
9919a8321c
2 changed files with 62 additions and 46 deletions
|
|
@ -90,25 +90,30 @@ pub fn vault_health_check() -> bool {
|
||||||
let vault_addr =
|
let vault_addr =
|
||||||
std::env::var("VAULT_ADDR").unwrap_or_else(|_| "https://localhost:8200".to_string());
|
std::env::var("VAULT_ADDR").unwrap_or_else(|_| "https://localhost:8200".to_string());
|
||||||
|
|
||||||
let cmd = format!(
|
let health_url = format!("{}/v1/sys/health", vault_addr);
|
||||||
"curl -f -s --connect-timeout 2 -k {}/v1/sys/health",
|
|
||||||
vault_addr
|
|
||||||
);
|
|
||||||
|
|
||||||
let output = safe_sh_command(&cmd);
|
match SafeCommand::new("curl")
|
||||||
if output.is_empty() {
|
.and_then(|c| c.args(&["-f", "-s", "--connect-timeout", "2", "-k", &health_url]))
|
||||||
return false;
|
.and_then(|c| c.execute())
|
||||||
}
|
{
|
||||||
|
Ok(output) => {
|
||||||
if let Ok(json) = serde_json::from_str::<serde_json::Value>(&output) {
|
if output.status.success() {
|
||||||
let sealed = json.get("sealed").and_then(|v| v.as_bool()).unwrap_or(true);
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
let initialized = json
|
if let Ok(json) = serde_json::from_str::<serde_json::Value>(&stdout) {
|
||||||
.get("initialized")
|
let sealed = json.get("sealed").and_then(|v| v.as_bool()).unwrap_or(true);
|
||||||
.and_then(|v| v.as_bool())
|
let initialized = json
|
||||||
.unwrap_or(false);
|
.get("initialized")
|
||||||
!sealed && initialized
|
.and_then(|v| v.as_bool())
|
||||||
} else {
|
.unwrap_or(false);
|
||||||
false
|
return !sealed && initialized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Health endpoint returns 503 when sealed but initialized
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
stdout.contains("\"initialized\":true") || stderr.contains("\"initialized\":true")
|
||||||
|
}
|
||||||
|
Err(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1387,6 +1387,15 @@ EOF"#.to_string(),
|
||||||
let vault_bin = bin_path.join("vault");
|
let vault_bin = bin_path.join("vault");
|
||||||
let vault_data = self.base_path.join("data/vault");
|
let vault_data = self.base_path.join("data/vault");
|
||||||
|
|
||||||
|
// Check if Vault data directory exists (real indicator of initialized state)
|
||||||
|
let vault_data_exists = vault_data.exists();
|
||||||
|
|
||||||
|
if !vault_data_exists {
|
||||||
|
info!("Vault data directory not found, will initialize fresh");
|
||||||
|
} else {
|
||||||
|
info!("Vault data directory found, checking health...");
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for Vault to be ready
|
// Wait for Vault to be ready
|
||||||
info!("Waiting for Vault to start...");
|
info!("Waiting for Vault to start...");
|
||||||
std::thread::sleep(std::time::Duration::from_secs(3));
|
std::thread::sleep(std::time::Duration::from_secs(3));
|
||||||
|
|
@ -1395,39 +1404,41 @@ EOF"#.to_string(),
|
||||||
std::env::var("VAULT_ADDR").unwrap_or_else(|_| "https://localhost:8200".to_string());
|
std::env::var("VAULT_ADDR").unwrap_or_else(|_| "https://localhost:8200".to_string());
|
||||||
let ca_cert = conf_path.join("system/certificates/ca/ca.crt");
|
let ca_cert = conf_path.join("system/certificates/ca/ca.crt");
|
||||||
|
|
||||||
// Check if Vault is already initialized via health endpoint
|
// Only attempt recovery if data directory exists
|
||||||
let health_cmd = format!(
|
if vault_data_exists {
|
||||||
"curl -f -s --connect-timeout 2 -k {}/v1/sys/health",
|
// Check if Vault is already initialized via health endpoint
|
||||||
vault_addr
|
let health_cmd = format!(
|
||||||
);
|
"curl -f -s --connect-timeout 2 -k {}/v1/sys/health",
|
||||||
let health_output = safe_sh_command(&health_cmd);
|
vault_addr
|
||||||
|
);
|
||||||
|
let health_output = safe_sh_command(&health_cmd);
|
||||||
|
|
||||||
let already_initialized = if let Some(ref output) = health_output {
|
let already_initialized = if let Some(ref output) = health_output {
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
if let Ok(json) = serde_json::from_str::<serde_json::Value>(
|
if let Ok(json) = serde_json::from_str::<serde_json::Value>(
|
||||||
&String::from_utf8_lossy(&output.stdout),
|
&String::from_utf8_lossy(&output.stdout),
|
||||||
) {
|
) {
|
||||||
json.get("initialized")
|
json.get("initialized")
|
||||||
.and_then(|v| v.as_bool())
|
.and_then(|v| v.as_bool())
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
false
|
// Health endpoint returns 503 when sealed but initialized
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
stdout.contains("\"initialized\":true")
|
||||||
|
|| stderr.contains("\"initialized\":true")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Health endpoint returns 503 when sealed but initialized
|
false
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
};
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
||||||
stdout.contains("\"initialized\":true")
|
|
||||||
|| stderr.contains("\"initialized\":true")
|
|
||||||
|| vault_data.exists()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vault_data.exists()
|
|
||||||
};
|
|
||||||
|
|
||||||
if already_initialized {
|
if already_initialized {
|
||||||
info!("Vault already initialized (detected via health/data), skipping init");
|
info!("Vault already initialized (detected via health/data), skipping init");
|
||||||
return self.recover_existing_vault();
|
return self.recover_existing_vault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize Vault
|
// Initialize Vault
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue